public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core
@ 2018-09-21  8:25 Chris Co
  2018-09-21  8:25 ` [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec Chris Co
                   ` (27 more replies)
  0 siblings, 28 replies; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

REF: https://github.com/christopherco/edk2-platforms/tree/winiot_hmb_v1

v0:
* https://lists.01.org/pipermail/edk2-devel/2018-July/027213.html
* https://lists.01.org/pipermail/edk2-devel/2018-July/027266.html
* https://lists.01.org/pipermail/edk2-devel/2018-July/027333.html
* https://lists.01.org/pipermail/edk2-devel/2018-July/027409.html

The patch set supports the bring up of Windows 10 IoT Core on
Solidrun's Hummingboard Edge board running NXP's i.MX 6Quad SoC.

This patch set is a preliminary submission, with the goal to get further review
feedback from maintainers since the v0 version had too many initial issues to
conduct a full review.

Changes in this patch set from v0:
* Merged the 4 previous patch sets into one.
* All code should now follow the edk2 coding style.
* SMBIOS driver refactored to use PCDs. Fixed UUID generation to use MAC address.
* Updated ACPI HIDs to proper NXP IDs where applicable.
* Removed unnecessary (and spec-violating) _DSD methods from our ACPI tables.
* General code cleanup and refactoring.
* Add Silicon package support for i.MX 6Solo/DualLite, 6SoloX, 6DualPlus/QuadPlus
families in iMX6Pkg.

Known issues remaining from previous review:
* Silicon/NXP/iMXPlatformPkg: SdhcDxe fixed initialization needs to be moved to
a PlatformDxe init and use NonDiscoverableDeviceRegistrationLib.
* Platform/Microsoft: Left in SdMmcDxe code. Alternatives are still under
evaluation.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Christopher Co (27):
  Platform/Microsoft: Add OpteeClientPkg dec
  Platform/Microsoft: Add SdMmc Dxe Driver
  Platform/Microsoft: Add MsPkg
  Silicon/NXP: Add iMXPlatformPkg dec
  Silicon/NXP: Add UART library support for i.MX platforms
  Silicon/NXP: Add I2C library support for i.MX platforms
  Silicon/NXP: Add i.MX display library support
  Silicon/NXP: Add Virtual RTC support for i.MX platform
  Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  Silicon/NXP: Add iMX6Pkg dec
  Silicon/NXP: Add i.MX6 SoC header files
  Silicon/NXP: Add i.MX6 I/O MUX library
  Silicon/NXP: Add support for iMX SDHC
  Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
  Silicon/NXP: Add i.MX6 GPT Timer library
  Silicon/NXP: Add i.MX6 Timer DXE driver
  Silicon/NXP: Add i.MX6 USB Phy Library
  Silicon/NXP: Add i.MX6 Clock Library
  Silicon/NXP: Add i.MX6 ACPI tables
  Silicon/NXP: Add i.MX6 Board init library
  Silicon/NXP: Add i.MX6 PCIe DXE driver
  Silicon/NXP: Add i.MX6 GOP driver
  Silicon/NXP: Add i.MX6 Smbios Driver
  Silicon/NXP: Add i.MX6 common dsc and fdf files
  Platform/Solidrun: Add Hummingboard Peripheral Initialization
  Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables
  Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files

 Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c                                          |  548 +++++
 Platform/Microsoft/Drivers/SdMmcDxe/Debug.c                                            |  363 +++
 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c                                         | 1775 ++++++++++++++
 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h                                         |  231 ++
 Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c                                           |  609 +++++
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c                                            |  886 +++++++
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h                                            |  529 +++++
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf                                       |   49 +
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h                                          |  505 ++++
 Platform/Microsoft/Include/Protocol/RpmbIo.h                                           |  268 +++
 Platform/Microsoft/Include/Protocol/Sdhc.h                                             |  197 ++
 Platform/Microsoft/MsPkg.dec                                                           |   39 +
 Platform/Microsoft/MsPkg.dsc                                                           |   31 +
 Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec                                   |   49 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf                 |   55 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl                       |   38 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl                 |   71 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl            |   33 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl                   |   54 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl                   |   32 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl                   |  234 ++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl                  |  144 ++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl                   |   43 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl                  |  198 ++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl                   |  343 +++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc            |  141 ++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf            |  117 +
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c      |  634 +++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h      |  705 ++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf     |   91 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc                                               |  408 ++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc                                               |  142 ++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h                                           |  106 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl                                           |  106 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl                                            |   74 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl                                           |   55 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl                                            |   67 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl                                           |  298 +++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl                                       |  106 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl                                            |   85 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl                                           |  133 ++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl                                            |  103 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl                                           |   33 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc                                               |   60 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc                                               |  120 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc                                               |   92 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc                                               |   95 +
 Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc                                               |   53 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c                                             |  423 ++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h                                             |  277 +++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c                                               |   69 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h                                               |   28 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c                                           |  455 ++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h                                           |  175 ++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c                                 |  399 ++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h                                 |  331 +++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c                                  |  458 ++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h                                  |  195 ++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c                                              |   96 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h                                              |   33 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c                                            |  475 ++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h                                            |   20 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf                                          |   70 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c                                              |  761 ++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h                                              |  529 +++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c                                             |   88 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h                                             |   32 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h                                               |  236 ++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c                                              |   93 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h                                              |   67 +
 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c                                | 1139 +++++++++
 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h                                |  145 ++
 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf                              |   66 +
 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c                      | 1774 ++++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h                      |   44 +
 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf                    |   84 +
 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c                                           |  278 +++
 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf                                      |   55 +
 Silicon/NXP/iMX6Pkg/Include/common_epit.h                                              |  118 +
 Silicon/NXP/iMX6Pkg/Include/common_gpt.h                                               |  271 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6.h                                                     |   39 +
 Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h                                             |   55 +
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h                                               |  105 +
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h                                            |  181 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h                                           |  176 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h                                            |  190 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h                                                |  202 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h                                            | 2466 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h                                            | 1875 +++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h                                             | 2270 ++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h                                                |   24 +
 Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h                                               |   20 +
 Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h                                                  |  332 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h                                                 |  335 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h                                                 |  301 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h                                                  | 1730 ++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6_common.h                                              | 1350 +++++++++++
 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c                                        |  246 ++
 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf                                      |   45 +
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S                             |   89 +
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c                                |  110 +
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c                                  |   88 +
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c                           |  107 +
 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c                                 | 1876 +++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf                            |   46 +
 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h                         |  221 ++
 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c                                   |  151 ++
 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf                              |   41 +
 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c                                 |  328 +++
 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf                            |   43 +
 Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc                                                  |  897 +++++++
 Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc                                                  |  287 +++
 Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc                                                  |  148 ++
 Silicon/NXP/iMX6Pkg/iMX6Pkg.dec                                                        |  143 ++
 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c                                   | 1246 ++++++++++
 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h                                   |   81 +
 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf                                 |   70 +
 Silicon/NXP/iMXPlatformPkg/Include/Platform.h                                          |   67 +
 Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h                                        |  114 +
 Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h                                           |   92 +
 Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h                                         |  162 ++
 Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h                                          |   24 +
 Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h                                           |  207 ++
 Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h                                          |  277 +++
 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c               |  243 ++
 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf             |   41 +
 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c   |  227 ++
 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf |   37 +
 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c                       |  152 ++
 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf                     |   31 +
 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c                               |  487 ++++
 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf                             |   35 +
 Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec                                          |  118 +
 133 files changed, 40660 insertions(+)
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Debug.c
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
 create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h
 create mode 100644 Platform/Microsoft/Include/Protocol/RpmbIo.h
 create mode 100644 Platform/Microsoft/Include/Protocol/Sdhc.h
 create mode 100644 Platform/Microsoft/MsPkg.dec
 create mode 100644 Platform/Microsoft/MsPkg.dsc
 create mode 100644 Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
 create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/common_epit.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/common_gpt.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_common.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
 create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
 create mode 100644 Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
 create mode 100644 Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
 create mode 100644 Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
 create mode 100644 Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/Platform.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
 create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
 create mode 100644 Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec

-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-10-31 20:43   ` Leif Lindholm
  2018-09-21  8:25 ` [PATCH edk2-platforms 02/27] Platform/Microsoft: Add SdMmc Dxe Driver Chris Co
                   ` (26 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

On Windows IoT Core devices with ARM TrustZone capabilities,
EDK2 runs in normal world and we use OP-TEE to execute
secure world operations. The overall package will contain
client-side support to invoke EDK2 services implemented as
OP-TEE trusted applications that run in secure world.

This commit adds the initial dec file to add some PCD settings
needed by other packages.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49 ++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
new file mode 100644
index 000000000000..4752eab39ce3
--- /dev/null
+++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
@@ -0,0 +1,49 @@
+## @file
+#
+#  OP-TEE client package
+#
+#  OP-TEE client package contains the client-side interface to invoke OP-TEE TAs.
+#  Certain EDKII services are implemented in Trusted Applications running in
+#  the secure world OP-TEE OS.
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = OpteeClientPkg
+  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-1bdd74ec9595
+  PACKAGE_VERSION                = 0.01
+
+[Includes]
+
+[LibraryClasses]
+
+[Guids]
+  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, { 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
+
+[PcdsFixedAtBuild]
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x00000005
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x00000006
+
+  ## The base address of the Trust Zone OpTEE OS private memory region
+  # This memory is manager privately by the OpTEE OS.
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD1|UINT64|0x00000001
+
+  ## The size of the Trust Zone OpTEE OS private memory region
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UINT64|0x00000002
+
+  ## The base address of the Trust Zone OpTEE OS shared memory region
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2|UINT64|0x00000003
+
+  ## The size of the Trust Zone OpTEE OS shared memory region
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UINT64|0x00000004
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 02/27] Platform/Microsoft: Add SdMmc Dxe Driver
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
  2018-09-21  8:25 ` [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-09-21  8:25 ` [PATCH edk2-platforms 04/27] Silicon/NXP: Add iMXPlatformPkg dec Chris Co
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This SdMmc driver adds support to boot Windows from SD and eMMC.
It implements RPMB protocol support for eMMC, unique device path
creation for each slot on the SD bus, high speed modes,
eMMC bus width auto-detection, and support for high capacity
SDXC cards.

Derived from: EmbeddedPkg\Universal\MmcDxe

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
---
 Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c    |  548 ++++++
 Platform/Microsoft/Drivers/SdMmcDxe/Debug.c      |  363 ++++
 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c   | 1775 ++++++++++++++++++++
 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h   |  231 +++
 Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c     |  609 +++++++
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c      |  886 ++++++++++
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h      |  529 ++++++
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf |   49 +
 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h    |  505 ++++++
 Platform/Microsoft/Include/Protocol/RpmbIo.h     |  268 +++
 Platform/Microsoft/Include/Protocol/Sdhc.h       |  197 +++
 11 files changed, 5960 insertions(+)

diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c b/Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c
new file mode 100644
index 000000000000..cf3ab1a44a10
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c
@@ -0,0 +1,548 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/RpmbIo.h>
+#include <Protocol/Sdhc.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "SdMmcHw.h"
+#include "SdMmc.h"
+#include "Protocol.h"
+
+VOID
+BenchmarkIo (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN SD_TRANSFER_DIRECTION  TransferDirection,
+  IN UINT32                 MediaId,
+  IN UINTN                  BufferSize,
+  IN UINT32                 Iterations
+  );
+
+EFI_STATUS
+IoBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN SD_TRANSFER_DIRECTION  TransferDirection,
+  IN UINT32                 MediaId,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSize,
+  IN OUT VOID               *Buffer
+  );
+
+VOID
+SortIoReadStatsByTotalTransferTime (
+  IN IoReadStatsEntry*   Table,
+  IN UINT32              NumEntries
+  )
+{
+  // Using the simple insertion sort
+  UINT32 Idx;
+  UINT32 J;
+
+  for (Idx = 1; Idx < NumEntries; ++Idx) {
+    IoReadStatsEntry CurrEntry = Table[Idx];
+    J = Idx;
+    while (J > 0 &&
+           Table[J - 1].TotalTransferTimeUs < CurrEntry.TotalTransferTimeUs) {
+      Table[J] = Table[J - 1];
+      --J;
+    }
+    Table[J] = CurrEntry;
+  }
+}
+
+VOID
+BenchmarkIo (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN SD_TRANSFER_DIRECTION  TransferDirection,
+  IN UINT32                 MediaId,
+  IN UINTN                  BufferSize,
+  IN UINT32                 Iterations
+  )
+{
+  ASSERT (Iterations > 0);
+
+  VOID        *Buffer;
+  UINT32      BufferSizeKB;
+  UINT32      CurrIteration;
+  UINT64      EndTime;
+  UINT32      KBps;
+  UINT64      StartTime;
+  EFI_STATUS  Status;
+  UINT64      TotalTransfersTimeUs;
+
+  BufferSizeKB = INT_DIV_ROUND (BufferSize, 1024);
+  Buffer = AllocateZeroPool (BufferSize);
+  if (Buffer == NULL) {
+    LOG_ERROR ("BenchmarkIo() : No enough memory to allocate %dKB buffer", BufferSizeKB);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  CurrIteration = Iterations;
+  TotalTransfersTimeUs = 0;
+
+  while (CurrIteration--) {
+    StartTime = GetPerformanceCounter ();
+    Status = IoBlocks (
+      This,
+      TransferDirection,
+      MediaId,
+      0, // Lba
+      BufferSize,
+      Buffer
+    );
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+
+    EndTime = GetPerformanceCounter ();
+    TotalTransfersTimeUs += (((EndTime - StartTime) * 1000000UL) / gHpcTicksPerSeconds);
+  }
+
+  KBps = (UINT32) (((UINT64) BufferSizeKB * (UINT64) Iterations * 1000000UL) / TotalTransfersTimeUs);
+  LOG_INFO (
+    "- BenchmarkIo(%a, %dKB)\t: Xfr Avg:%dus\t%dKBps\t%dMBps",
+    (TransferDirection == SdTransferDirectionRead) ? "Read" : "Write",
+    BufferSizeKB,
+    (UINT32) (TotalTransfersTimeUs / Iterations),
+    KBps,
+    INT_DIV_ROUND (KBps, 1024));
+
+Exit:
+  if (Buffer != NULL) {
+    FreePool (Buffer);
+  }
+}
+
+EFI_STATUS
+IoBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN SD_TRANSFER_DIRECTION  TransferDirection,
+  IN UINT32                 MediaId,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSize,
+  IN OUT VOID               *Buffer
+  )
+{
+  CONST SD_COMMAND  *Cmd;
+  VOID              *CurrentBuffer;
+  SDHC_INSTANCE     *HostInst;
+  UINT32            BlockCount;
+  UINT32            BytesRemaining;
+  UINTN             CurrentBufferSize;
+  UINT32            CurrentLba;
+  UINT32            Retry;
+  EFI_STATUS        Status;
+
+  HostInst = SDHC_INSTANCE_FROM_BLOCK_IO_THIS (This);
+  ASSERT (HostInst);
+  ASSERT (HostInst->HostExt);
+
+  if (This->Media->MediaId != MediaId) {
+    Status = EFI_MEDIA_CHANGED;
+    goto Exit;
+  }
+
+  if (Buffer == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  // Check if a Card is Present
+  if (!HostInst->BlockIo.Media->MediaPresent) {
+    Status = EFI_NO_MEDIA;
+    goto Exit;
+  }
+
+  // Reading 0 Byte is valid
+  if (BufferSize == 0) {
+    Status = EFI_SUCCESS;
+    goto Exit;
+  }
+
+  if ((TransferDirection == SdTransferDirectionWrite) && (This->Media->ReadOnly == TRUE)) {
+    Status = EFI_WRITE_PROTECTED;
+    goto Exit;
+  }
+
+    // The buffer size must be an exact multiple of the block size
+  if ((BufferSize % This->Media->BlockSize) != 0) {
+    Status = EFI_BAD_BUFFER_SIZE;
+    goto Exit;
+  }
+
+  BlockCount = BufferSize / This->Media->BlockSize;
+
+  // All blocks must be within the device
+  if ((Lba + BlockCount - 1) > (This->Media->LastBlock)) {
+    LOG_ERROR (
+      "Data span is out of media address range. (Media Last Block LBA = 0x%lx"
+      "Data Last Block LBA = 0x%lx)",
+      This->Media->LastBlock,
+      (Lba + BlockCount - 1));
+
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  // Check the alignment
+  if ((This->Media->IoAlign > 2) && (((UINTN) Buffer & (This->Media->IoAlign - 1)) != 0)) {
+    LOG_ERROR (
+      "Invalid buffer address alignment (Buffer = %p, IoAlign = %d)",
+      Buffer,
+      This->Media->IoAlign);
+
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  if (TransferDirection == SdTransferDirectionRead) {
+    if (BlockCount == 1) {
+      Cmd = &CmdReadSingleBlock;
+    } else {
+      Cmd = &CmdReadMultiBlock;
+    }
+  } else {
+    if (BlockCount == 1) {
+      Cmd = &CmdWriteSingleBlock;
+    } else {
+      Cmd = &CmdWriteMultiBlock;
+    }
+  }
+
+  CONST UINT32 DataCommandRetryCount = 3;
+  CONST UINT32 MaxTransferSize =
+    HostInst->HostCapabilities.MaximumBlockCount * This->Media->BlockSize;
+  BytesRemaining = BufferSize;
+  CurrentBuffer = Buffer;
+  CurrentLba = (UINT32) Lba;
+
+  for (; BytesRemaining > 0;) {
+    if (BytesRemaining < MaxTransferSize) {
+      CurrentBufferSize = BytesRemaining;
+    } else {
+      CurrentBufferSize = MaxTransferSize;
+    }
+
+    for (Retry = 0; Retry < DataCommandRetryCount; ++Retry) {
+      Status = SdhcSendDataCommand (
+        HostInst,
+        Cmd,
+        CurrentLba,
+        CurrentBufferSize,
+        CurrentBuffer);
+
+      if (!EFI_ERROR (Status)) {
+        if (Retry > 0) {
+          LOG_TRACE ("SdhcSendDataCommand succeeded after %d retry", Retry);
+        }
+        break;
+      }
+
+      // On SdhcSendDataCommand return, proper error recovery has been performed
+      // and it should be safe to retry the same transfer.
+      LOG_ERROR ("SdhcSendDataCommand failed on retry %d", Retry);
+    }
+
+    BytesRemaining -= CurrentBufferSize;
+    CurrentLba += CurrentBufferSize / This->Media->BlockSize;
+    CurrentBuffer = (VOID*) ((UINTN) CurrentBuffer + CurrentBufferSize);
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "IoBlocks(%c, LBA:0x%08lx, Size(B):0x%x): SdhcSendDataCommand() failed. %r",
+      ((TransferDirection == SdTransferDirectionRead) ? 'R' : 'W'),
+      Lba,
+      BufferSize,
+      Status);
+  }
+
+  return Status;
+}
+
+// EFI_BLOCK_IO Protocol Callbacks
+
+/**
+  Reset the block device.
+
+  This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
+  It resets the block device hardware.
+  ExtendedVerification is ignored in this implementation.
+
+  @param  This                   Indicates a pointer to the calling context.
+  @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive
+                                 verification operation of the device during reset.
+
+  @retval EFI_SUCCESS            The block device was reset.
+  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoReset (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN BOOLEAN                ExtendedVerification
+  )
+{
+  SDHC_INSTANCE   *HostInst;
+
+  LOG_TRACE ("BlockIoReset()");
+
+  HostInst = SDHC_INSTANCE_FROM_BLOCK_IO_THIS (This);
+  return SoftReset (HostInst);
+}
+
+/**
+  Reads the requested number of blocks from the device.
+
+  This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
+  It reads the requested number of blocks from the device.
+  All the blocks are read, or an error is returned.
+
+  @param  This                   Indicates a pointer to the calling context.
+  @param  MediaId                The media ID that the read request is for.
+  @param  Lba                    The starting logical block address to read from on the device.
+  @param  BufferSize             The size of the Buffer in bytes.
+                                 This must be a multiple of the intrinsic block size of the device.
+  @param  Buffer                 A pointer to the destination buffer for the data. The caller is
+                                 responsible for either having implicit or explicit ownership of the buffer.
+
+  @retval EFI_SUCCESS            The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the read operation.
+  @retval EFI_NO_MEDIA           There is no media in the device.
+  @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
+  @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic block size of the device.
+  @retval EFI_INVALID_PARAMETER  The read request contains LBAs that are not valid,
+                                 or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoReadBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN UINT32                 MediaId,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSize,
+  OUT VOID                  *Buffer
+  )
+{
+  LOG_TRACE ("BlockIoReadBlocks()");
+
+#if SDMMC_BENCHMARK_IO
+  STATIC BOOLEAN  BenchmarkDone;
+  UINT32          CurrByteSize;
+
+  BenchmarkDone = FALSE;
+  if (!BenchmarkDone) {
+
+    LOG_INFO ("Benchmarking BlockIo Read");
+
+    CurrByteSize = 512;
+    CONST UINT32 MaxByteSize = 8388608; // 8MB Max
+    for (; CurrByteSize <= MaxByteSize; CurrByteSize *= 2) {
+      BenchmarkIo (This, SdTransferDirectionRead, MediaId, CurrByteSize, 10);
+    }
+
+    BenchmarkDone = TRUE;
+  }
+#endif // SDMMC_BENCHMARK_IO
+
+#if SDMMC_COLLECT_STATISTICS
+  SDHC_INSTANCE   *HostInst;
+  UINT32          BlockIdx;
+  UINT64          EndTime;
+  UINT32          NumBlocks;
+  UINT64          StartTime;
+  EFI_STATUS      Status;
+  UINT32          TotalReadBlocksCount;
+  UINT32          TotalReadTimeUs;
+
+  NumBlocks = BufferSize / This->Media->BlockSize;
+  HostInst = SDHC_INSTANCE_FROM_BLOCK_IO_THIS (This);
+  CONST UINT32 TableSize = ARRAYSIZE (HostInst->IoReadStats);
+  IoReadStatsEntry *CurrentReadEntry = NULL;
+
+  for (BlockIdx = 0; BlockIdx < TableSize; ++BlockIdx) {
+    IoReadStatsEntry *Entry = HostInst->IoReadStats + BlockIdx;
+    // Reached end of table and didn't find a match, append an entry
+    if (Entry->NumBlocks == 0) {
+      ++HostInst->IoReadStatsNumEntries;
+      Entry->NumBlocks = NumBlocks;
+    }
+
+    if (Entry->NumBlocks == NumBlocks) {
+      CurrentReadEntry = Entry;
+      ++Entry->Count;
+      break;
+    }
+  }
+  ASSERT (BlockIdx < TableSize);
+
+  StartTime = GetPerformanceCounter ();
+
+  Status = IoBlocks (
+    This,
+    SdTransferDirectionRead,
+    MediaId,
+    Lba,
+    BufferSize,
+    Buffer
+  );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  EndTime = GetPerformanceCounter ();
+
+  ASSERT (CurrentReadEntry != NULL);
+  CurrentReadEntry->TotalTransferTimeUs +=
+    (UINT32) (((EndTime - StartTime) * 1000000UL) / gHpcTicksPerSeconds);
+
+  // Run statistics and dump updates
+  SortIoReadStatsByTotalTransferTime (
+    HostInst->IoReadStats,
+    HostInst->IoReadStatsNumEntries);
+
+  IoReadStatsEntry *MaxNumBlocksEntry = HostInst->IoReadStats;
+  IoReadStatsEntry *MaxCountEntry = HostInst->IoReadStats;
+  TotalReadTimeUs = 0;
+  TotalReadBlocksCount = 0;
+
+  LOG_INFO (" #Blks\tCnt\tAvg(us)\tAll(us)");
+
+  for (BlockIdx = 0; BlockIdx < HostInst->IoReadStatsNumEntries; ++BlockIdx) {
+    IoReadStatsEntry *CurrEntry = HostInst->IoReadStats + BlockIdx;
+
+    if (CurrEntry->NumBlocks > MaxNumBlocksEntry->NumBlocks) {
+      MaxNumBlocksEntry = CurrEntry;
+    }
+
+    if (CurrEntry->Count > MaxCountEntry->Count) {
+      MaxCountEntry = CurrEntry;
+    }
+
+    TotalReadTimeUs += CurrEntry->TotalTransferTimeUs;
+    TotalReadBlocksCount += (CurrEntry->NumBlocks * CurrEntry->Count);
+
+    // Show only the top 5 time consuming transfers
+    if (BlockIdx < 5) {
+      LOG_INFO (
+        " %d\t%d\t%d\t%d",
+        (UINT32) CurrEntry->NumBlocks,
+        (UINT32) CurrEntry->Count,
+        (UINT32) (CurrEntry->TotalTransferTimeUs / CurrEntry->Count),
+        (UINT32) CurrEntry->TotalTransferTimeUs);
+    }
+  }
+
+  LOG_INFO (
+    "MaxNumBlocksEntry: %d %d %dus",
+    (UINT32) MaxNumBlocksEntry->NumBlocks,
+    (UINT32) MaxNumBlocksEntry->Count,
+    (UINT32) MaxNumBlocksEntry->TotalTransferTimeUs);
+
+  LOG_INFO (
+    "MaxCountEntry: %d %d %dus",
+    (UINT32) MaxCountEntry->NumBlocks,
+    (UINT32) MaxCountEntry->Count,
+    (UINT32) MaxCountEntry->TotalTransferTimeUs);
+
+  LOG_INFO (
+    "UEFI spent %dus~%ds reading %dMB from SDCard\n",
+    TotalReadTimeUs,
+    INT_DIV_ROUND (TotalReadTimeUs, 1000000),
+    INT_DIV_ROUND (TotalReadBlocksCount * This->Media->BlockSize, (1024 * 1024)));
+Exit:
+  return Status;
+
+#else
+  return IoBlocks (This, SdTransferDirectionRead, MediaId, Lba, BufferSize, Buffer);
+#endif // SDMMC_COLLECT_STATISTICS
+}
+
+/**
+  Writes a specified number of blocks to the device.
+
+  This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
+  It writes a specified number of blocks to the device.
+  All blocks are written, or an error is returned.
+
+  @param  This                   Indicates a pointer to the calling context.
+  @param  MediaId                The media ID that the write request is for.
+  @param  Lba                    The starting logical block address to be written.
+  @param  BufferSize             The size of the Buffer in bytes.
+                                 This must be a multiple of the intrinsic block size of the device.
+  @param  Buffer                 Pointer to the source buffer for the data.
+
+  @retval EFI_SUCCESS            The data were written correctly to the device.
+  @retval EFI_WRITE_PROTECTED    The device cannot be written to.
+  @retval EFI_NO_MEDIA           There is no media in the device.
+  @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
+  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the write operation.
+  @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic
+                                 block size of the device.
+  @retval EFI_INVALID_PARAMETER  The write request contains LBAs that are not valid,
+                                 or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoWriteBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN UINT32                 MediaId,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSize,
+  IN VOID                   *Buffer
+  )
+{
+  LOG_TRACE ("BlockIoWriteBlocks()");
+
+  return IoBlocks (This, SdTransferDirectionWrite, MediaId, Lba, BufferSize, Buffer);
+}
+
+/**
+  Flushes all modified data to a physical block device.
+
+  @param  This                   Indicates a pointer to the calling context.
+
+  @retval EFI_SUCCESS            All outstanding data were written correctly to the device.
+  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to write data.
+  @retval EFI_NO_MEDIA           There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This
+  )
+{
+  LOG_TRACE ("BlockIoFlushBlocks()");
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/Debug.c b/Platform/Microsoft/Drivers/SdMmcDxe/Debug.c
new file mode 100644
index 000000000000..79e56543a3ea
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/Debug.c
@@ -0,0 +1,363 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/RpmbIo.h>
+#include <Protocol/Sdhc.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "SdMmcHw.h"
+#include "SdMmc.h"
+#include "Protocol.h"
+
+CONST CHAR8 *mStrUnit[] = { "100kbit/s", "1Mbit/s", "10Mbit/s", "100MBit/s",
+                            "Unknown", "Unknown", "Unknown", "Unknown" };
+CONST CHAR8 *mStrValue[] = { "UNDEF", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0", "3.5", "4.0", "4.5", "5.0",
+                             "Unknown", "Unknown", "Unknown", "Unknown" };
+
+VOID
+PrintCid (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_CID   *MmcCid;
+  SD_CID    *SdCid;
+
+  LOG_INFO ("- PrintCid");;
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    SdCid = &HostInst->CardInfo.Registers.Sd.Cid;
+    LOG_INFO ("\t- Manufacturer ID: 0x%x", (UINT32) SdCid->MID);
+    LOG_INFO ("\t- OEM ID: 0x%x", (UINT32) SdCid->OID);
+    LOG_INFO (
+      "\t- Product name: %c%c%c%c%c",
+      SdCid->PNM[4],
+      SdCid->PNM[3],
+      SdCid->PNM[2],
+      SdCid->PNM[1],
+      SdCid->PNM[0]);
+
+    LOG_INFO (
+      "\t- Manufacturing date: %d/%d",
+      (UINT32) (SdCid->MDT & 0xF),
+      (UINT32) (((SdCid->MDT >> 4) & 0x3F) + 2000));
+    LOG_INFO ("\t- Product serial number: 0x%X", SdCid->PSN);
+    LOG_INFO ("\t- Product revision: %d", (UINT32) SdCid->PRV);
+
+    LOG_INFO ("\t- OEM ID: 0x%x", (UINT32) SdCid->OID);
+    LOG_INFO ("\t- Manufacturer ID: 0x%x", (UINT32) SdCid->MID);
+  } else {
+    MmcCid = &HostInst->CardInfo.Registers.Mmc.Cid;
+    LOG_INFO ("\t- Manufacturer ID: 0x%x", (UINT32) MmcCid->MID);
+    LOG_INFO ("\t- OEM ID: 0x%x", (UINT32) MmcCid->OID);
+    LOG_INFO (
+      "\t- Product name: %c%c%c%c%c%c\n",
+      MmcCid->PNM[5],
+      MmcCid->PNM[4],
+      MmcCid->PNM[3],
+      MmcCid->PNM[2],
+      MmcCid->PNM[1],
+      MmcCid->PNM[0]);
+
+    LOG_INFO (
+      "\t- Manufacturing date: %d/%d",
+      (UINT32) (MmcCid->MDT >> 4),
+      (UINT32) (MmcCid->MDT & 0xF) + 1997);
+
+    LOG_INFO ("\t- Product serial number: 0x%X", MmcCid->PSN);
+    LOG_INFO ("\t- Product revision: %d", (UINT32) MmcCid->PRV);
+  }
+}
+
+VOID
+PrintCsd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_CSD   *MmcCsd;
+  MMC_EXT_CSD *MmcExtCsd;
+  SD_CSD    *SdCsd;
+  UINT32    CardSizeGB;
+
+  LOG_INFO ("- PrintCsd");
+  CardSizeGB =
+    (UINT32) INT_DIV_ROUND (HostInst->CardInfo.ByteCapacity, (UINT64) (1024 * 1024 * 1024));
+
+  LOG_INFO (
+    "\t- CardSize: %ld~%dGB, BlockSize:%d LastBlock LBA:0x%08x",
+    HostInst->CardInfo.ByteCapacity,
+    CardSizeGB,
+    HostInst->BlockIo.Media->BlockSize,
+    (UINT32) HostInst->BlockIo.Media->LastBlock);
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    SdCsd = &HostInst->CardInfo.Registers.Sd.Csd;
+    if (SdCsd->CSD_STRUCTURE == 0) {
+      LOG_INFO ("- SD CSD Version 1.01-1.10/Version 2.00/Standard Capacity");
+    } else if (SdCsd->CSD_STRUCTURE == 1) {
+      LOG_INFO ("- SD CSD Version 2.00/High Capacity");
+    } else {
+      LOG_INFO ("- SD CSD Version Higher than v3.3");
+    }
+
+    LOG_INFO (
+      "\t- SW Write Protect: Temp:%d Permanent:%d",
+      (UINT32) SdCsd->TMP_WRITE_PROTECT,
+      (UINT32) SdCsd->PERM_WRITE_PROTECT);
+
+    LOG_INFO ("\t- Supported card command class: 0x%X", SdCsd->CCC);
+
+    LOG_INFO (
+      "\t- Speed: %a %a (TRAN_SPEED:%x)",
+      mStrValue[(SdCsd->TRAN_SPEED >> 3) & 0xF],
+      mStrUnit[SdCsd->TRAN_SPEED & 7],
+      (UINT32) SdCsd->TRAN_SPEED);
+
+    LOG_INFO (
+      "\t- Maximum Read Data Block: %d (READ_BL_LEN:%x)",
+      (UINT32) (1 << SdCsd->READ_BL_LEN),
+      (UINT32) SdCsd->READ_BL_LEN);
+
+    LOG_INFO (
+      "\t- Maximum Write Data Block: %d (WRITE_BL_LEN:%x)",
+      (UINT32) (1 << SdCsd->WRITE_BL_LEN),
+      (UINT32) SdCsd->WRITE_BL_LEN);
+
+    if (!SdCsd->FILE_FORMAT_GRP) {
+      if (SdCsd->FILE_FORMAT == 0) {
+        LOG_INFO ("\t- Format (0): Hard disk-like file system with partition table");
+      } else if (SdCsd->FILE_FORMAT == 1) {
+        LOG_INFO ("\t- Format (1): DOS FAT (floppy-like) with boot sector only (no partition table)");
+      } else if (SdCsd->FILE_FORMAT == 2) {
+        LOG_INFO ("\t- Format (2): Universal File Format");
+      } else {
+        LOG_INFO ("\t- Format (3): Others/Unknown");
+      }
+    } else {
+      LOG_INFO ("\t- Format: Reserved");
+    }
+  } else {
+    MmcCsd = &HostInst->CardInfo.Registers.Mmc.Csd;
+    MmcExtCsd = &HostInst->CardInfo.Registers.Mmc.ExtCsd;
+
+    if (MmcExtCsd->CardType & MmcExtCsdCardTypeNormalSpeed) {
+      LOG_INFO ("\t- Normal-Speed MMC @ 26MHz");
+    }
+
+    if (MmcExtCsd->CardType & MmcExtCsdCardTypeHighSpeed) {
+      LOG_INFO ("\t- High-Speed MMC @ 52MHz");
+    }
+
+    if (MmcExtCsd->CardType & MmcExtCsdCardTypeDdr1v8) {
+      LOG_INFO ("\t- High-Speed DDR MMC @ 52MHz - 1.8V or 3V I/O");
+    }
+
+    if (MmcExtCsd->CardType & MmcExtCsdCardTypeDdr1v2) {
+      LOG_INFO ("\t- High-Speed DDR MMC @ 52MHz - 1.2VI/O");
+    }
+
+    LOG_INFO (
+      "\t- SW Write Protect: Temp:%d Permenant:%d",
+      (UINT32) MmcCsd->TMP_WRITE_PROTECT,
+      (UINT32) MmcCsd->PERM_WRITE_PROTECT);
+
+    LOG_INFO ("\t- SpecVersion: %d.x", (UINT32) MmcCsd->SPEC_VERS);
+    LOG_INFO ("\t- Supported card command class: 0x%X", MmcCsd->CCC);
+
+    LOG_INFO (
+      "\t- Current Max Speed: %a %a (TRAN_SPEED:%x)",
+      mStrValue[(MmcCsd->TRAN_SPEED >> 3) & 0xF],
+      mStrUnit[MmcCsd->TRAN_SPEED & 7],
+      (UINT32) MmcCsd->TRAN_SPEED);
+
+    LOG_INFO (
+      "\t- Maximum Read Data Block: %d (READ_BL_LEN:%x)",
+      (UINT32) (1 << MmcCsd->READ_BL_LEN),
+      (UINT32) MmcCsd->READ_BL_LEN);
+
+    LOG_INFO (
+      "\t- Maximum Write Data Block: %d (WRITE_BL_LEN:%x)",
+      (UINT32) (1 << MmcCsd->WRITE_BL_LEN),
+      (UINT32) MmcCsd->WRITE_BL_LEN);
+
+    if (!MmcCsd->FILE_FORMAT_GRP) {
+      if (MmcCsd->FILE_FORMAT == 0) {
+        LOG_INFO ("\t- Format (0): Hard disk-like file system with partition table");
+      } else if (MmcCsd->FILE_FORMAT == 1) {
+        LOG_INFO ("\t- Format (1): DOS FAT (floppy-like) with boot sector only (no partition table)");
+      } else if (MmcCsd->FILE_FORMAT == 2) {
+        LOG_INFO ("\t- Format (2): Universal File Format");
+      } else {
+        LOG_INFO ("\t- Format (3): Others/Unknown");
+      }
+    } else {
+      LOG_INFO ("\t- Format: Reserved");
+    }
+  }
+}
+
+VOID
+GetAndPrintCardStatus (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  CARD_STATUS CardStatus;
+  EFI_STATUS Status;
+
+  // If the card has not been selected, then we can't get its status
+  if (HostInst->CardInfo.RCA == 0x0) {
+    return;
+  }
+
+  Status = SdhcSendCommand (HostInst, &CmdSendStatus, 0);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  CardStatus.AsUint32 = HostInst->CmdResponse[0];
+  PrintCardStatus (HostInst, CardStatus);
+}
+
+VOID
+PrintCardStatus (
+  IN SDHC_INSTANCE  *HostInst,
+  IN CARD_STATUS    CardStatus
+  )
+{
+  switch (HostInst->CardInfo.CardFunction) {
+  case CardFunctionSd:
+    LOG_INFO (
+      "Status: APP_CMD:%d READY_FOR_DATA:%d CURRENT_STATE:%d(%a) "
+      "CARD_IS_LOCKED:%d",
+      CardStatus.Fields.APP_CMD,
+      CardStatus.Fields.READY_FOR_DATA,
+      CardStatus.Fields.CURRENT_STATE,
+      CardStateToString (CardStatus.Fields.CURRENT_STATE),
+      CardStatus.Fields.CARD_IS_LOCKED);
+
+    break;
+
+  case CardFunctionMmc:
+    LOG_INFO (
+      "Status: APP_CMD:%d URGENT_BKOPS:%d READY_FOR_DATA:%d "
+      "CURRENT_STATE:%d(%a) CARD_IS_LOCKED:%d",
+      CardStatus.Fields.APP_CMD,
+      CardStatus.Fields.URGENT_BKOPS,
+      CardStatus.Fields.READY_FOR_DATA,
+      CardStatus.Fields.CURRENT_STATE,
+      CardStateToString (CardStatus.Fields.CURRENT_STATE),
+      CardStatus.Fields.CARD_IS_LOCKED);
+
+    break;
+
+  default:
+    ASSERT (FALSE);
+  }
+
+  if (IsCardStatusError (HostInst, CardStatus)) {
+    LOG_INFO ("Errors:");
+
+    if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+      if (CardStatus.Fields.AKE_SEQ_ERROR) {
+        LOG_INFO ("\t- SWITCH_ERROR");
+      }
+    }
+
+    if (HostInst->CardInfo.CardFunction == CardFunctionMmc) {
+      if (CardStatus.Fields.SWITCH_ERROR) {
+        LOG_INFO ("\t- SWITCH_ERROR");
+      }
+
+      if (CardStatus.Fields.OVERRUN) {
+        LOG_INFO ("\t- OVERRUN");
+      }
+
+      if (CardStatus.Fields.UNDERRUN) {
+        LOG_INFO ("\t- UNDERRUN");
+      }
+    }
+
+    if (CardStatus.Fields.ERASE_RESET) {
+      LOG_INFO ("\t- ERASE_RESET");
+    }
+
+    if (CardStatus.Fields.WP_ERASE_SKIP) {
+      LOG_INFO ("\t- WP_ERASE_SKIP");
+    }
+
+    if (CardStatus.Fields.CID_CSD_OVERWRITE) {
+      LOG_INFO ("\t- CID_CSD_OVERWRITE");
+    }
+
+    if (CardStatus.Fields.ERROR) {
+      LOG_INFO ("\t- ERROR");
+    }
+
+    if (CardStatus.Fields.CC_ERROR) {
+      LOG_INFO ("\t- CC_ERROR");
+    }
+
+    if (CardStatus.Fields.CARD_ECC_FAILED) {
+      LOG_INFO ("\t- CARD_ECC_FAILED");
+    }
+
+    if (CardStatus.Fields.ILLEGAL_COMMAND) {
+      LOG_INFO ("\t- ILLEGAL_COMMAND");
+    }
+
+    if (CardStatus.Fields.COM_CRC_ERROR) {
+      LOG_INFO ("\t- COM_CRC_ERROR");
+    }
+
+    if (CardStatus.Fields.LOCK_UNLOCK_FAILED) {
+      LOG_INFO ("\t- LOCK_UNLOCK_FAILED");
+    }
+
+    if (CardStatus.Fields.WP_VIOLATION) {
+      LOG_INFO ("\t- WP_VIOLATION");
+    }
+
+    if (CardStatus.Fields.ERASE_PARAM) {
+      LOG_INFO ("\t- ERASE_PARAM");
+    }
+
+    if (CardStatus.Fields.ERASE_SEQ_ERROR) {
+      LOG_INFO ("\t- ERASE_SEQ_ERROR");
+    }
+
+    if (CardStatus.Fields.BLOCK_LEN_ERROR) {
+      LOG_INFO ("\t- BLOCK_LEN_ERROR");
+    }
+
+    if (CardStatus.Fields.ADDRESS_MISALIGN) {
+      LOG_INFO ("\t- ADDRESS_MISALIGN");
+    }
+
+    if (CardStatus.Fields.ADDRESS_OUT_OF_RANGE) {
+      LOG_INFO ("\t- ADDRESS_OUT_OF_RANGE");
+    }
+  }
+}
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c b/Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c
new file mode 100644
index 000000000000..0e14aa5301a2
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c
@@ -0,0 +1,1775 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/RpmbIo.h>
+#include <Protocol/Sdhc.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "SdMmcHw.h"
+#include "SdMmc.h"
+#include "Protocol.h"
+
+EFI_STATUS
+InitializeDevice (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_SDHC_PROTOCOL   *HostExt;
+  EFI_STATUS          Status;
+
+  LOG_TRACE ("InitializDevice()");
+  ASSERT (!HostInst->SlotInitialized);
+
+#if SDMMC_BENCHMARK_IO
+  UINT64              InitializationStartTime;
+  InitializationStartTime = HpcTimerStart ();
+#endif // SDMMC_BENCHMARK_IO
+
+  HostExt = HostInst->HostExt;
+  ASSERT (HostExt);
+  ASSERT (HostInst->BlockIo.Media->MediaPresent);
+
+  ZeroMem (&HostInst->CardInfo, sizeof (HostInst->CardInfo));
+
+  // SD/MMC cards on reset start in default normal speed mode
+  HostInst->CardInfo.CurrentSpeedMode = CardSpeedModeNormalSpeed;
+
+  Status = HostExt->SoftwareReset (HostExt, SdhcResetTypeAll);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("HostExt->SoftwareReset() failed. %r", Status);
+    return Status;
+  }
+
+  Status = HostExt->SetClock (HostExt, SD_IDENT_MODE_CLOCK_FREQ_HZ);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("HostExt->SetClock() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcQueryCardType (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcQueryCardType() failed. %r", Status);
+    return Status;
+  }
+
+  switch (HostInst->CardInfo.CardFunction) {
+  case CardFunctionComboSdSdio:
+    LOG_ERROR ("Combo SD/SDIO function is not supported");
+    return EFI_UNSUPPORTED;
+  case CardFunctionSdio:
+    LOG_ERROR ("SDIO function is not supported");
+    return EFI_UNSUPPORTED;
+  case CardFunctionSd:
+    Status = InitializeSdDevice (HostInst);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("InitializeSdDevice() failed. %r", Status);
+      return Status;
+    }
+    break;
+  case CardFunctionMmc:
+    Status = InitializeMmcDevice (HostInst);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("InitializeMmcDevice() failed. %r", Status);
+      return Status;
+    }
+    break;
+  default:
+    LOG_ASSERT ("Unknown device function");
+    return EFI_UNSUPPORTED;
+  }
+
+  PrintCid (HostInst);
+  PrintCsd (HostInst);
+
+  Status = SdhcSetBlockLength (HostInst, SD_BLOCK_LENGTH_BYTES);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSetBlockLength() failed. %r", Status);
+    return Status;
+  }
+
+  ASSERT (HostInst->CardInfo.CardFunction == CardFunctionSd ||
+          HostInst->CardInfo.CardFunction == CardFunctionMmc);
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    HostInst->BlockIo.Media->RemovableMedia = TRUE;
+    HostInst->BlockIo.Media->MediaId = HostInst->CardInfo.Registers.Sd.Cid.PSN;
+  } else {
+    // Assume BGA form factor eMMC
+    HostInst->BlockIo.Media->RemovableMedia = FALSE;
+
+    // Use the card product serial number as MediaId
+    HostInst->BlockIo.Media->MediaId = HostInst->CardInfo.Registers.Mmc.Cid.PSN;
+  }
+
+  HostInst->SlotInitialized = TRUE;
+
+#if SDMMC_BENCHMARK_IO
+  UINT64 ElapsedTimeMs;
+  ElapsedTimeMs = HpcTimerElapsedMilliseconds (InitializationStartTime);
+  LOG_INFO ("Initialization completed in %ldms", ElapsedTimeMs);
+#endif // SDMMC_BENCHMARK_IO
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeSdDevice (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_STATUS Status;
+
+  Status = SdhcSendOpCondSd (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendOpCondSd() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendCidAll (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCidAll() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendRelativeAddr (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendRelativeAddr() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendCid (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCid() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendCsd (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCsd() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSelectDevice (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSelectDevice() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSwitchBusWidthSd (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSwitchBusWidthSd() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSwitchSpeedModeSd (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSwitchSpeedModeSd() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSetMaxClockFrequency (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSetMaxClockFrequency() failed. %r", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeMmcDevice (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_STATUS Status;
+
+  Status = SdhcSendCidAll (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCidAll() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendRelativeAddr (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendRelativeAddr() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendCid (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCid() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendCsd (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCsd() failed. %r", Status);
+    return Status;
+  }
+
+  if (HostInst->CardInfo.Registers.Mmc.Csd.SPEC_VERS < MMC_MIN_SUPPORTED_SPEC_VERS) {
+    LOG_ERROR (
+      "MMC %d.x is not supported, Minimum supported is MMC %d.x",
+      HostInst->CardInfo.Registers.Mmc.Csd.SPEC_VERS,
+      MMC_MIN_SUPPORTED_SPEC_VERS);
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = SdhcSelectDevice (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSelectDevice() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSendExtCsdMmc (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendExtCsdMmc() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSwitchSpeedModeMmc (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSwitchSpeedModeMmc() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSwitchBusWidthMmc (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSwitchBusWidthMmc() failed. %r", Status);
+    return Status;
+  }
+
+  Status = SdhcSetMaxClockFrequency (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSetMaxClockFrequency() failed. %r", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcRecoverFromErrors (
+  IN SDHC_INSTANCE      *HostInst,
+  IN CONST SD_COMMAND   *Cmd
+  )
+{
+  EFI_SDHC_PROTOCOL   *HostExt;
+  CARD_STATUS         CardStatus;
+  EFI_STATUS          Status;
+
+  LOG_TRACE (
+    "*** %cCMD%d Error recovery sequence start ***",
+    (Cmd->Class == SdCommandClassApp ? 'A' : ' '),
+    (UINT32) Cmd->Index);
+
+  HostExt = HostInst->HostExt;
+  HostInst->ErrorRecoveryAttemptCount += 1;
+
+  if (HostInst->ErrorRecoveryAttemptCount > SDMMC_ERROR_RECOVERY_ATTEMPT_THRESHOLD) {
+    LOG_ERROR ("RecursiveErrorRecoveryCount exceeded the threshold. Error is unrecoverable!");
+    Status = EFI_PROTOCOL_ERROR;
+    goto Exit;
+  }
+
+  GetAndPrintCardStatus (HostInst);
+
+  LOG_TRACE ("Reseting CMD line ...");
+  Status = HostExt->SoftwareReset (HostExt, SdhcResetTypeCmd);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("HostExt->SoftwareReset(SdhcResetTypeCmd) failed. %r", Status);
+  }
+
+  if (Cmd->TransferType != SdTransferTypeNone &&
+      Cmd->TransferType != SdTransferTypeUndefined) {
+
+    LOG_TRACE ("Reseting DAT line ...");
+    Status = HostExt->SoftwareReset (HostExt, SdhcResetTypeData);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("HostExt->SoftwareReset(SdhcResetTypeData) failed. %r", Status);
+    }
+  }
+
+  if (EFI_ERROR (Status)) {
+    LOG_TRACE ("CMD and/or DATA normal error recovery failed, trying SDHC soft-reset");
+    Status = SoftReset (HostInst);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("All trials to recover from errors failed. %r");
+      goto Exit;
+    }
+  }
+
+  if (CmdsAreEqual (Cmd, &CmdWriteMultiBlock) ||
+      CmdsAreEqual (Cmd, &CmdReadMultiBlock)) {
+
+    Status = SdhcSendStatus (HostInst, &CardStatus);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("SdhcSendStatus() failed. (Status = %r)", Status);
+      goto Exit;
+    }
+
+    if (CardStatus.Fields.CURRENT_STATE != CardStateTran) {
+      LOG_TRACE ("Stopping transmission ...");
+      Status = SdhcStopTransmission (HostInst);
+      if (EFI_ERROR (Status)) {
+        goto Exit;
+      }
+
+      // Multi read/write failure reason will be written in the STOP_TRANSMISSION
+      // response as part of the card status error flags.
+      CardStatus.AsUint32 = HostInst->CmdResponse[0];
+      PrintCardStatus (HostInst, CardStatus);
+    }
+  }
+
+Exit:
+
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "*** %cCMD%d Error recovery sequence failed "
+      "(Status = %r, ErrorRecoveryAttemptCount = %d) ***",
+      (Cmd->Class == SdCommandClassApp ? 'A' : ' '),
+      (UINT32) Cmd->Index,
+      Status,
+      HostInst->ErrorRecoveryAttemptCount);
+
+  } else {
+    LOG_TRACE (
+      "*** %cCMD%d Error recovery sequence completed successfully "
+      "(ErrorRecoveryAttemptCount = %d) ***",
+      (Cmd->Class == SdCommandClassApp ? 'A' : ' '),
+      (UINT32) Cmd->Index,
+      HostInst->ErrorRecoveryAttemptCount);
+  }
+
+  HostInst->ErrorRecoveryAttemptCount -= 1;
+
+  return Status;
+}
+
+EFI_STATUS
+SdhcSendCommandHelper (
+  IN SDHC_INSTANCE        *HostInst,
+  IN CONST SD_COMMAND     *Cmd,
+  IN UINT32               Arg,
+  IN SD_COMMAND_XFR_INFO  *XfrInfo
+  )
+{
+  EFI_SDHC_PROTOCOL   *HostExt;
+  CARD_STATUS         CardStatus;
+  UINT32              CmdAppArg;
+  EFI_STATUS          Status;
+
+  HostExt = HostInst->HostExt;
+  if (Cmd->Class == SdCommandClassApp) {
+    CmdAppArg = HostInst->CardInfo.RCA << 16;
+    Status = HostExt->SendCommand (HostExt, &CmdAppSd, CmdAppArg, NULL);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "HostExt->SendCommand(%cCMD%d, 0x%08x) failed. %r",
+        (Cmd->Class == SdCommandClassApp ? 'A' : ' '),
+        (UINT32) Cmd->Index,
+        CmdAppArg,
+        Status);
+
+      return Status;
+    }
+  }
+
+  Status = HostExt->SendCommand (HostExt, Cmd, Arg, XfrInfo);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "HostExt->SendCommand(%cCMD%d, 0x%08x) failed. %r",
+      (Cmd->Class == SdCommandClassApp ? 'A' : ' '),
+      (UINT32) Cmd->Index,
+      Arg,
+      Status);
+
+    return Status;
+  }
+
+  Status = HostExt->ReceiveResponse (HostExt, Cmd, HostInst->CmdResponse);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("HostExt->ReceiveResponse() failed. %r", Status);
+    return Status;
+  }
+
+  if ((Cmd->ResponseType == SdResponseTypeR1) ||
+      (Cmd->ResponseType == SdResponseTypeR1B)) {
+
+    CardStatus.AsUint32 = HostInst->CmdResponse[0];
+
+    if (IsCardStatusError (HostInst, CardStatus)) {
+      LOG_ERROR (
+        "%cCMD%d card status error detected",
+        (Cmd->Class == SdCommandClassApp ? 'A' : ' '),
+        (UINT32) Cmd->Index);
+
+      PrintCardStatus (HostInst, CardStatus);
+
+      return EFI_DEVICE_ERROR;
+    }
+  }
+
+  HostInst->PreLastSuccessfulCmd = HostInst->LastSuccessfulCmd;
+  HostInst->LastSuccessfulCmd = Cmd;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSendCommand (
+  IN SDHC_INSTANCE      *HostInst,
+  IN CONST SD_COMMAND   *Cmd,
+  IN UINT32             Arg
+  )
+{
+  EFI_STATUS Status;
+
+  Status = SdhcSendCommandHelper (HostInst, Cmd, Arg, NULL);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("Send no-data command failed. %r", Status);
+    SdhcRecoverFromErrors (HostInst, Cmd);
+    return Status;
+  }
+
+  // SWITCH command can change card state to prog, we should wait the card to
+  // transfer back to tran state and rais the READY_FOR_DATA flag to make sure
+  // that switch operation was completed successfully
+  if (CmdsAreEqual (Cmd, &CmdSwitchMmc) ||
+      CmdsAreEqual (Cmd, &CmdSwitchSd)) {
+    Status = SdhcWaitForTranStateAndReadyForData (HostInst);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "SdhcWaitForTranStateAndReadyForData() failed after successful "
+        "SWITCH command. (Status = %r)",
+        Status);
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSendDataCommand (
+  IN SDHC_INSTANCE      *HostInst,
+  IN CONST SD_COMMAND   *Cmd,
+  IN UINT32             Arg,
+  IN UINT32             BufferByteSize,
+  IN VOID               *Buffer
+  )
+{
+  EFI_SDHC_PROTOCOL     *HostExt;
+  EFI_STATUS            Status;
+  SD_COMMAND_XFR_INFO   XfrInfo;
+
+  HostExt = HostInst->HostExt;
+  ASSERT (BufferByteSize % SD_BLOCK_LENGTH_BYTES == 0);
+  XfrInfo.BlockCount = BufferByteSize / SD_BLOCK_LENGTH_BYTES;
+  XfrInfo.BlockSize = SD_BLOCK_LENGTH_BYTES;
+  XfrInfo.Buffer = Buffer;
+
+  Status = SdhcSendCommandHelper (HostInst, Cmd, Arg, &XfrInfo);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  if (Cmd->TransferDirection == SdTransferDirectionRead) {
+    Status = HostExt->ReadBlockData (
+      HostExt,
+      BufferByteSize,
+      (UINT32*) Buffer);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "HostExt->ReadBlockData(Size: 0x%xB) failed. %r",
+        BufferByteSize,
+        Status);
+      goto Exit;
+    }
+  } else {
+    ASSERT (Cmd->TransferDirection == SdTransferDirectionWrite);
+    Status = HostExt->WriteBlockData (
+      HostExt,
+      BufferByteSize,
+      (UINT32*) Buffer);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "HostExt->WriteBlockData(Size: 0x%xB) failed. %r",
+        BufferByteSize,
+        Status);
+      goto Exit;
+    }
+  }
+
+  // If this is an open-ended multi-block read/write then explicitly send
+  // STOP_TRANSMISSION. A multi-block read/write with pre-defined block count
+  // will be preceeded with SET_BLOCK_COUNT.
+  if ((CmdsAreEqual (Cmd, &CmdWriteMultiBlock) ||
+       CmdsAreEqual (Cmd, &CmdReadMultiBlock)) &&
+       ((HostInst->LastSuccessfulCmd == NULL) ||
+        !CmdsAreEqual (HostInst->PreLastSuccessfulCmd, &CmdSetBlockCount))) {
+
+    Status = SdhcStopTransmission (HostInst);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("SdhcStopTransmission() failed. (Status = %r)", Status);
+      goto Exit;
+    }
+  }
+
+  Status = SdhcWaitForTranStateAndReadyForData (HostInst);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("Send data command failed. %r", Status);
+    SdhcRecoverFromErrors (HostInst, Cmd);
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+SdhcGoIdleState (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  return SdhcSendCommand (HostInst, &CmdGoIdleState, 0);
+}
+
+EFI_STATUS
+SdhcQueryCardType (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_STATUS Status;
+
+  Status = SdhcGoIdleState (HostInst);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  HostInst->CardInfo.CardFunction = CardFunctionUnknown;
+
+  Status = SdhcSendIfCondSd (HostInst);
+  if (!EFI_ERROR (Status)) {
+    HostInst->CardInfo.CardFunction = CardFunctionSd;
+  }
+
+  Status = SdhcSendOpCondSdio (HostInst);
+  if (!EFI_ERROR (Status)) {
+    if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+      // SD/SDIO Combo Device
+      HostInst->CardInfo.CardFunction = CardFunctionComboSdSdio;
+    } else {
+      HostInst->CardInfo.CardFunction = CardFunctionSdio;
+    }
+  }
+
+  if (HostInst->CardInfo.CardFunction != CardFunctionSd &&
+      HostInst->CardInfo.CardFunction != CardFunctionSdio &&
+      HostInst->CardInfo.CardFunction != CardFunctionComboSdSdio) {
+    Status = SdhcGoIdleState (HostInst);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = SdhcSendOpCondMmc (HostInst);
+    if (!EFI_ERROR (Status)) {
+      HostInst->CardInfo.CardFunction = CardFunctionMmc;
+    }
+  }
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionUnknown) {
+    return EFI_NO_MEDIA;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcWaitForTranStateAndReadyForData (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  CARD_STATUS     CardStatus;
+  UINT32          Retry;
+  EFI_STATUS      Status;
+
+  Status = SdhcSendStatus (HostInst, &CardStatus);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Retry = SDMMC_POLL_WAIT_COUNT;
+
+  while (((!CardStatus.Fields.READY_FOR_DATA && Retry) ||
+           (CardStatus.Fields.CURRENT_STATE != CardStateTran)) &&
+            Retry) {
+    gBS->Stall (SDMMC_POLL_WAIT_TIME_US);
+    --Retry;
+
+    Status = SdhcSendStatus (HostInst, &CardStatus);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  if (!Retry) {
+    LOG_ERROR ("Time-out waiting for card READY_FOR_DATA status flag");
+    PrintCardStatus (HostInst, CardStatus);
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSendCid (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  UINT32      CmdArg;
+  EFI_STATUS  Status;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+
+  Status = SdhcSendCommand (HostInst, &CmdSendCid, CmdArg);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    gBS->CopyMem (
+      (VOID*) &HostInst->CardInfo.Registers.Sd.Cid,
+      (VOID*) HostInst->CmdResponse,
+      sizeof (SD_CID));
+
+  } else if (HostInst->CardInfo.CardFunction == CardFunctionMmc) {
+    gBS->CopyMem (
+      (VOID*) &HostInst->CardInfo.Registers.Mmc.Cid,
+      (VOID*) HostInst->CmdResponse,
+      sizeof (MMC_CID));
+
+    C_ASSERT (sizeof (HostInst->RpmbIo.Cid) == EFI_RPMB_CID_SIZE);
+    gBS->CopyMem (
+      (VOID*) &HostInst->RpmbIo.Cid,
+      (VOID*) HostInst->CmdResponse,
+      EFI_RPMB_CID_SIZE);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSendCsd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_CSD     *MmcCsd;
+  SD_CSD      *SdCsd;
+  SD_CSD_2    *SdCsd2;
+  UINT32      BlockNr;
+  UINT64      ByteCapacity;
+  UINT32      CmdArg;
+  UINT32      DeviceSize;
+  UINT32      MaxBlockLen;
+  UINT32      Mult;
+  UINT64      NumBlocks;
+  EFI_STATUS  Status;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  Status = SdhcSendCommand (HostInst, &CmdSendCsd, CmdArg);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ByteCapacity = 0;
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    gBS->CopyMem (
+      (VOID*) &HostInst->CardInfo.Registers.Sd.Csd,
+      (VOID*) HostInst->CmdResponse,
+      sizeof (SD_CSD));
+    if (HostInst->CardInfo.Registers.Sd.Csd.CSD_STRUCTURE == 0) {
+      SdCsd = (SD_CSD*) &HostInst->CardInfo.Registers.Sd.Csd;
+      DeviceSize = ((SdCsd->C_SIZEHigh10 << 2) | SdCsd->C_SIZELow2);
+      Mult = 1 << (SdCsd->C_SIZE_MULT + 2);
+      BlockNr = (DeviceSize + 1) * Mult;
+      MaxBlockLen = 1 << SdCsd->READ_BL_LEN;
+      ByteCapacity = BlockNr * MaxBlockLen;
+    } else {
+      SdCsd2 = (SD_CSD_2*) &HostInst->CardInfo.Registers.Sd.Csd;
+      MaxBlockLen = 1 << SdCsd2->READ_BL_LEN;
+      ByteCapacity = (UINT64) (SdCsd2->C_SIZE + 1) * 512llu * 1024llu;
+    }
+  } else if (HostInst->CardInfo.CardFunction == CardFunctionMmc) {
+    gBS->CopyMem (
+      (VOID*) &HostInst->CardInfo.Registers.Mmc.Csd,
+      (VOID*) HostInst->CmdResponse,
+      sizeof (MMC_CSD));
+    // HighCapacity MMC requires reading EXT_CSD to calculate capacity
+    if (!HostInst->CardInfo.HighCapacity) {
+      MmcCsd = (MMC_CSD*) &HostInst->CardInfo.Registers.Mmc.Csd;
+      DeviceSize = ((MmcCsd->C_SIZEHigh10 << 2) | MmcCsd->C_SIZELow2);
+      Mult = 1 << (MmcCsd->C_SIZE_MULT + 2);
+      BlockNr = (DeviceSize + 1) * Mult;
+      MaxBlockLen = 1 << MmcCsd->READ_BL_LEN;
+      ByteCapacity = BlockNr * MaxBlockLen;
+    }
+  }
+
+  HostInst->CardInfo.ByteCapacity = ByteCapacity;
+  HostInst->BlockIo.Media->BlockSize = SD_BLOCK_LENGTH_BYTES;
+  NumBlocks = (ByteCapacity / SD_BLOCK_LENGTH_BYTES);
+  if (NumBlocks > 0) {
+    HostInst->BlockIo.Media->LastBlock = (NumBlocks - 1);
+  } else {
+    HostInst->BlockIo.Media->LastBlock = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSelectDevice (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  UINT32 CmdArg;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  return SdhcSendCommand (HostInst, &CmdSelect, CmdArg);
+}
+
+EFI_STATUS
+SdhcDeselectDevice (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  return SdhcSendCommand (HostInst, &CmdDeselect, 0);
+}
+
+EFI_STATUS
+SdhcSendAppCmd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  UINT32 CmdArg;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  return SdhcSendCommand (HostInst, &CmdAppSd, CmdArg);
+}
+
+EFI_STATUS
+SdhcStopTransmission (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  UINT32 CmdArg;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  return SdhcSendCommand (HostInst, &CmdStopTransmission, CmdArg);
+}
+
+EFI_STATUS
+SdhcSendCidAll (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  return SdhcSendCommand (HostInst, &CmdSendCidAll, 0);
+}
+
+EFI_STATUS
+SdhcSendRelativeAddr (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  UINT32      CmdArg;
+  EFI_STATUS  Status;
+
+  CmdArg = 0;
+  // Unlike SD memory, MMC cards don't publish their RCA, instead it should be
+  // manually assigned by the SDHC
+  if (HostInst->CardInfo.CardFunction == CardFunctionMmc) {
+    HostInst->CardInfo.RCA = 0xCCCC;
+    CmdArg = HostInst->CardInfo.RCA << 16;
+  }
+
+  Status = SdhcSendCommand (HostInst, &CmdSendRelativeAddr, CmdArg);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (HostInst->CardInfo.CardFunction != CardFunctionMmc) {
+    HostInst->CardInfo.RCA = (HostInst->CmdResponse[0] >> 16);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateCardMaxFreq (
+  IN SDHC_INSTANCE *HostInst,
+  OUT UINT32* MaxClkFreqHz
+  )
+{
+  UINT32    TimeValue;
+  UINT32    TranSpeed;
+  UINT32    TransferRateBitPerSecond;
+
+  ASSERT (HostInst != NULL);
+  ASSERT (MaxClkFreqHz != NULL);
+
+  TransferRateBitPerSecond = 0;
+  TimeValue = 0;
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    TranSpeed = HostInst->CardInfo.Registers.Sd.Csd.TRAN_SPEED;
+  } else {
+    TranSpeed = HostInst->CardInfo.Registers.Mmc.Csd.TRAN_SPEED;
+  }
+
+  // Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
+  switch (TranSpeed & 0x7) { // 2
+  case 0: // 100kbit/s
+    TransferRateBitPerSecond = 100 * 1000;
+    break;
+
+  case 1: // 1Mbit/s
+    TransferRateBitPerSecond = 1 * 1000 * 1000;
+    break;
+
+  case 2: // 10Mbit/s
+    TransferRateBitPerSecond = 10 * 1000 * 1000;
+    break;
+
+  case 3: // 100Mbit/s
+    TransferRateBitPerSecond = 100 * 1000 * 1000;
+    break;
+
+  default:
+    LOG_ERROR ("Invalid parameter");
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //Calculate Time value (Bits 6:3 of TRAN_SPEED)
+  switch ((TranSpeed >> 3) & 0xF) { // 6
+  case 0x1:
+    TimeValue = 10;
+    break;
+
+  case 0x2:
+    TimeValue = 12;
+    break;
+
+  case 0x3:
+    TimeValue = 13;
+    break;
+
+  case 0x4:
+    TimeValue = 15;
+    break;
+
+  case 0x5:
+    TimeValue = 20;
+    break;
+
+  case 0x6:
+    if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+      TimeValue = 25;
+    } else {
+      TimeValue = 26;
+    }
+    break;
+
+  case 0x7:
+    TimeValue = 30;
+    break;
+
+  case 0x8:
+    TimeValue = 35;
+    break;
+
+  case 0x9:
+    TimeValue = 40;
+    break;
+
+  case 0xA:
+    TimeValue = 45;
+    break;
+
+  case 0xB:
+    if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+      TimeValue = 50;
+    } else {
+      TimeValue = 52;
+    }
+    break;
+
+  case 0xC:
+    TimeValue = 55;
+    break;
+
+  case 0xD:
+    TimeValue = 60;
+    break;
+
+  case 0xE:
+    TimeValue = 70;
+    break;
+
+  case 0xF:
+    TimeValue = 80;
+    break;
+
+  default:
+    LOG_ERROR ("Invalid parameter");
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *MaxClkFreqHz = (TransferRateBitPerSecond * TimeValue) / 10;
+
+  LOG_TRACE (
+    "TransferRateUnitId=%d TimeValue*10=%d, CardFrequency=%dKHz",
+    TranSpeed & 0x7,
+    TimeValue,
+    *MaxClkFreqHz / 1000);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSetMaxClockFrequency (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_SDHC_PROTOCOL   *HostExt;
+  UINT32              MaxClkFreqHz;
+  EFI_STATUS          Status;
+
+  HostExt = HostInst->HostExt;
+  MaxClkFreqHz = 0;
+
+  // Currently only NormalSpeed and HighSpeed supported
+  ASSERT (HostInst->CardInfo.CurrentSpeedMode == CardSpeedModeNormalSpeed ||
+          HostInst->CardInfo.CurrentSpeedMode == CardSpeedModeHighSpeed);
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    Status = CalculateCardMaxFreq (HostInst, &MaxClkFreqHz);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  } else {
+    if (HostInst->CardInfo.CurrentSpeedMode == CardSpeedModeNormalSpeed) {
+      Status = CalculateCardMaxFreq (HostInst, &MaxClkFreqHz);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    } else if (HostInst->CardInfo.CurrentSpeedMode == CardSpeedModeHighSpeed) {
+      MaxClkFreqHz = MMC_HIGH_SPEED_MODE_CLOCK_FREQ_HZ;
+    }
+  }
+
+  Status = HostExt->SetClock (HostExt, MaxClkFreqHz);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSetBlockLength (
+  IN SDHC_INSTANCE  *HostInst,
+  IN UINT32         BlockByteLength
+  )
+{
+  LOG_TRACE ("SdhcSetBlockLength(BlockByteLength=%d)", BlockByteLength);
+
+  return SdhcSendCommand (HostInst, &CmdSetBlockLength, BlockByteLength);
+}
+
+EFI_STATUS
+SdhcSetBlockCount (
+  IN SDHC_INSTANCE  *HostInst,
+  IN UINT32         BlockCount,
+  IN BOOLEAN        ReliableWrite
+  )
+{
+  UINT32 CmdArg;
+
+  LOG_TRACE (
+    "SdhcSetBlockCount(BlockCount=%d, ReliableWrite=%d)",
+    BlockCount,
+    ReliableWrite);
+
+  // JEDEC Standard No. 84-A441, Page 76
+  // Set bit[31] as 1 to indicate Reliable Write type of programming access.
+  if (ReliableWrite) {
+    CmdArg = BlockCount | (1 << 31);
+  } else {
+    CmdArg = BlockCount;
+  }
+
+  return SdhcSendCommand (HostInst, &CmdSetBlockCount, CmdArg);
+}
+
+EFI_STATUS
+SdhcSendStatus (
+  IN SDHC_INSTANCE  *HostInst,
+  OUT CARD_STATUS   *CardStatus
+  )
+{
+  UINT32      CmdArg;
+  EFI_STATUS  Status;
+
+  LOG_TRACE ("SdhcSendStatus()");
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  Status = SdhcSendCommand (HostInst, &CmdSendStatus, CmdArg);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CardStatus->AsUint32 = HostInst->CmdResponse[0];
+
+  return EFI_SUCCESS;
+}
+
+// SD Specific Functions
+EFI_STATUS
+SdhcSendScrSd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  SD_SCR      *Scr;
+  UINT32      CmdArg;
+  EFI_STATUS  Status;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  Status = SdhcSendDataCommand (
+    HostInst,
+    &CmdAppSendScrSd,
+    CmdArg,
+    sizeof (HostInst->BlockBuffer),
+    HostInst->BlockBuffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CopyMem (
+    &HostInst->CardInfo.Registers.Sd.Scr,
+    HostInst->BlockBuffer,
+    sizeof (SD_SCR));
+
+  Scr = (SD_SCR*) &HostInst->BlockBuffer;
+  LOG_TRACE ("SD_SCR:");
+  LOG_TRACE ("  SD_SPEC=%d", (UINT32) Scr->SD_SPEC);
+  LOG_TRACE ("  SD_SPEC3=%d", (UINT32) Scr->SD_SPEC3);
+  LOG_TRACE (
+    "  SD_BUS_WIDTHS=%x, 1-Bit?%d, 4-Bit?%d",
+    (UINT32) Scr->SD_BUS_WIDTH,
+    (UINT32) ((Scr->SD_BUS_WIDTH & BIT1) ? 1 : 0),
+    (UINT32) ((Scr->SD_BUS_WIDTH & BIT2) ? 1 : 0));
+  LOG_TRACE (
+    "  CMD_SUPPORT=%x, CMD23?%d, CMD20?%d",
+    (UINT32) Scr->CMD_SUPPORT,
+    (UINT32) ((Scr->CMD_SUPPORT & BIT2) ? 1 : 0),
+    (UINT32) ((Scr->CMD_SUPPORT & BIT1) ? 1 : 0));
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSendIfCondSd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  SEND_IF_COND_ARG            CmdArg;
+  SEND_IF_COND_CMD_RESPONSE   CmdStatus;
+  EFI_STATUS                  Status;
+
+  CmdArg.AsUint32 = 0;
+  // Recommended check pattern per SD Specs
+  CmdArg.Fields.CheckPattern = 0xAA;
+
+  // Our current implementation does not support more than HighSpeed voltage 2V7-3V6 (i.e no 1V8)
+  CmdArg.Fields.VoltageSupplied = SD_CMD8_VOLTAGE_27_36;
+
+  Status = SdhcSendCommand (HostInst, &CmdSendIfCondSd, CmdArg.AsUint32);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CmdStatus.AsUint32 = HostInst->CmdResponse[0];
+  if (CmdStatus.Fields.CheckPattern != CmdArg.Fields.CheckPattern ||
+      CmdStatus.Fields.VoltageSupplied != CmdArg.Fields.VoltageSupplied) {
+    return EFI_UNSUPPORTED;
+  }
+
+  HostInst->CardInfo.HasExtendedOcr = TRUE;
+
+  return EFI_SUCCESS;;
+}
+
+EFI_STATUS
+SdhcSendOpCondSd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  SD_OCR_EX             *OcrEx;
+  SD_SEND_OP_COND_ARG   CmdArg;
+  SD_OCR                Ocr;
+  UINT32                Retry;
+  EFI_STATUS            Status;
+
+  // With arg set to 0, it means read OCR
+  Status = SdhcSendCommand (HostInst, &CmdAppSendOpCondSd, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  HostInst->CardInfo.Registers.Sd.Ocr.AsUint32 = HostInst->CmdResponse[0];
+
+  CmdArg.AsUint32 = 0;
+  Retry = SDMMC_POLL_WAIT_COUNT;
+
+  CmdArg.Fields.VoltageWindow = HostInst->CardInfo.Registers.Sd.Ocr.Fields.VoltageWindow;
+  // Host support for High Capacity is assumed
+  CmdArg.Fields.HCS = 1;
+  while (Retry) {
+    Status = SdhcSendCommand (HostInst, &CmdAppSendOpCondSd, CmdArg.AsUint32);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Ocr.AsUint32 = HostInst->CmdResponse[0];
+    if (Ocr.Fields.PowerUp) {
+      LOG_TRACE ("SD Card PowerUp Complete");
+      if (HostInst->CardInfo.HasExtendedOcr) {
+        OcrEx = (SD_OCR_EX*) &Ocr;
+        if (OcrEx->Fields.CCS) {
+          LOG_TRACE ("Card is SD2.0 or later HighCapacity SDHC or SDXC");
+          HostInst->CardInfo.HighCapacity = TRUE;
+        } else {
+          LOG_TRACE ("Card is SD2.0 or later StandardCapacity SDSC");
+          HostInst->CardInfo.HighCapacity = FALSE;
+        }
+      }
+      break;
+    }
+    gBS->Stall (SDMMC_POLL_WAIT_TIME_US);
+    --Retry;
+  }
+
+  if (!Retry) {
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSwitchBusWidthSd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_SDHC_PROTOCOL *HostExt;
+  UINT32 CmdArg;
+  EFI_STATUS Status;
+
+  HostExt = HostInst->HostExt;
+  CmdArg = 0x2; // 4-bit
+  Status = SdhcSendCommand (HostInst, &CmdAppSetBusWidthSd, CmdArg);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = HostExt->SetBusWidth (HostExt, SdBusWidth4Bit);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSwitchSpeedModeSd (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  return EFI_SUCCESS;
+}
+
+// SDIO Specific Functions
+EFI_STATUS
+SdhcSendOpCondSdio (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  return SdhcSendCommand (HostInst, &CmdSendOpCondSdio, 0);
+}
+
+// Mmc Specific Functions
+EFI_STATUS
+SdhcSendOpCondMmc (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_OCR               *Ocr;
+  MMC_SEND_OP_COND_ARG  CmdArg;
+  UINT32                Retry;
+  EFI_STATUS            Status;
+
+  CmdArg.AsUint32 = 0;
+  Retry = SDMMC_POLL_WAIT_COUNT;
+  Ocr = &HostInst->CardInfo.Registers.Mmc.Ocr;
+  CmdArg.Fields.VoltageWindow = SD_OCR_HIGH_VOLTAGE_WINDOW;
+  CmdArg.Fields.AccessMode = SdOcrAccessSectorMode;
+  while (Retry) {
+    Status = SdhcSendCommand (HostInst, &CmdSendOpCondMmc, CmdArg.AsUint32);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    HostInst->CardInfo.Registers.Mmc.Ocr.AsUint32 = HostInst->CmdResponse[0];
+    if (Ocr->Fields.PowerUp) {
+      LOG_TRACE ("MMC Card PowerUp Complete");
+      if (Ocr->Fields.AccessMode == SdOcrAccessSectorMode) {
+        LOG_TRACE ("Card is MMC HighCapacity");
+        HostInst->CardInfo.HighCapacity = TRUE;
+      } else {
+        LOG_TRACE ("Card is MMC StandardCapacity");
+        HostInst->CardInfo.HighCapacity = FALSE;
+      }
+
+      if ((Ocr->Fields.VoltageWindow & SD_OCR_HIGH_VOLTAGE_WINDOW) != SD_OCR_HIGH_VOLTAGE_WINDOW) {
+        LOG_ERROR (
+          "MMC Card does not support High Voltage, expected profile:%x actual profile:%x",
+          (UINT32) SD_OCR_HIGH_VOLTAGE_WINDOW,
+          (UINT32) Ocr->Fields.VoltageWindow);
+        return EFI_UNSUPPORTED;
+      }
+      break;
+    }
+    gBS->Stall (SDMMC_POLL_WAIT_TIME_US);
+    --Retry;
+  }
+
+  if (!Retry) {
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSwitchBusWidthMmc (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_EXT_CSD         *ExtCsd;
+  EFI_SDHC_PROTOCOL   *HostExt;
+  SD_BUS_WIDTH        BusWidth;
+  UINT32              CmdArg;
+  UINT8               ExtCsdPowerClass;
+  EFI_STATUS          Status;
+  MMC_SWITCH_CMD_ARG  SwitchCmdArg;
+
+  HostExt = HostInst->HostExt;
+  BusWidth = SdBusWidth8Bit;
+  ExtCsd = &HostInst->CardInfo.Registers.Mmc.ExtCsd;
+  Status = SdhcSendExtCsdMmc (HostInst);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Figure out current requirements for target bus width. An inrease in current consumption
+  // may require switching the card to a higher power class
+  if (BusWidth == SdBusWidth8Bit) {
+    if (HostInst->CardInfo.CurrentSpeedMode == CardSpeedModeHighSpeed) {
+      ExtCsdPowerClass = MMC_EXT_CSD_POWER_CLASS_8BIT (ExtCsd->PowerClass52Mhz36V);
+    } else {
+      ExtCsdPowerClass = MMC_EXT_CSD_POWER_CLASS_8BIT (ExtCsd->PowerClass26Mhz36V);
+    }
+  } else if (BusWidth == SdBusWidth4Bit) {
+    if (HostInst->CardInfo.CurrentSpeedMode == CardSpeedModeHighSpeed) {
+      ExtCsdPowerClass = MMC_EXT_CSD_POWER_CLASS_4BIT (ExtCsd->PowerClass52Mhz36V);
+    } else {
+      ExtCsdPowerClass = MMC_EXT_CSD_POWER_CLASS_4BIT (ExtCsd->PowerClass26Mhz36V);
+    }
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  // Only do power class switch if the target bus width requires more current than the
+  // allowed by the current power class in EXT_CSD
+  if (ExtCsdPowerClass > HostInst->CardInfo.Registers.Mmc.ExtCsd.PowerClass) {
+    CmdArg = ExtCsdPowerClass;
+    CmdArg <<= 8;
+    CmdArg |= 0x03BB0000;
+    Status = SdhcSendCommand (
+      HostInst,
+      &CmdSwitchMmc,
+      CmdArg);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("Error detected on switching PowerClass function");
+      return Status;
+    }
+
+    Status = SdhcSendExtCsdMmc (HostInst);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    // Sanity check that wanted power-class are set per requested
+    if (HostInst->CardInfo.Registers.Mmc.ExtCsd.PowerClass != ExtCsdPowerClass) {
+      LOG_ERROR (
+        "MMC EXT_CSD not reporting correct PowerClass after switch. Expected:%x Actual:%x",
+        (UINT32) ExtCsdPowerClass,
+        (UINT32) HostInst->CardInfo.Registers.Mmc.ExtCsd.PowerClass);
+      return EFI_PROTOCOL_ERROR;
+    }
+  }
+
+  // Switch bus width
+  SwitchCmdArg.AsUint32 = 0;
+  SwitchCmdArg.Fields.Access = MmcSwitchCmdAccessTypeWriteByte;
+  SwitchCmdArg.Fields.Index = MmcExtCsdBitIndexBusWidth;
+
+  if (BusWidth == SdBusWidth8Bit) {
+    SwitchCmdArg.Fields.Value = MmcExtCsdBusWidth8Bit;
+  } else {
+    SwitchCmdArg.Fields.Value = MmcExtCsdBusWidth4Bit;
+  }
+
+  Status = SdhcSendCommand (
+    HostInst,
+    &CmdSwitchMmc,
+    SwitchCmdArg.AsUint32);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("Error detected on switching BusWidth function");
+    return Status;
+  }
+
+  Status = HostExt->SetBusWidth (HostExt, BusWidth);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSwitchSpeedModeMmc (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_SWITCH_CMD_ARG  CmdArg;
+  EFI_STATUS          Status;
+
+  CmdArg.AsUint32 = 0;
+  CmdArg.Fields.Access = MmcSwitchCmdAccessTypeWriteByte;
+  CmdArg.Fields.Index = MmcExtCsdBitIndexHsTiming;
+  CmdArg.Fields.Value = 1;
+
+  Status = SdhcSendCommand (
+    HostInst,
+    &CmdSwitchMmc,
+    CmdArg.AsUint32);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("Error detected on switching HighSpeed function");
+    return Status;
+  }
+
+  HostInst->CardInfo.CurrentSpeedMode = CardSpeedModeHighSpeed;
+
+  Status = SdhcSendExtCsdMmc (HostInst);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (!HostInst->CardInfo.Registers.Mmc.ExtCsd.HighSpeedTiming) {
+    LOG_ERROR ("MMC EXT_CSD not reporting HighSpeed timing after switch");
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSendExtCsdMmc (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  MMC_EXT_CSD   *ExtCsd;
+  UINT32        CmdArg;
+  EFI_STATUS    Status;
+
+  CmdArg = HostInst->CardInfo.RCA << 16;
+  ExtCsd = &HostInst->CardInfo.Registers.Mmc.ExtCsd;
+  Status = SdhcSendDataCommand (
+    HostInst,
+    &CmdSendExtCsdMmc,
+    CmdArg,
+    sizeof (HostInst->BlockBuffer),
+    HostInst->BlockBuffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CopyMem (ExtCsd, HostInst->BlockBuffer, sizeof (MMC_EXT_CSD));
+  HostInst->CardInfo.ByteCapacity = (UINT64) ExtCsd->SectorCount * 512llu;
+  HostInst->BlockIo.Media->LastBlock = ExtCsd->SectorCount - 1;
+  HostInst->RpmbIo.ReliableSectorCount = ExtCsd->ReliableWriteSectorCount;
+  HostInst->RpmbIo.RpmbSizeMult = ExtCsd->RpmbSizeMult;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSwitchPartitionMmc (
+  IN SDHC_INSTANCE                  *HostInst,
+  IN MMC_EXT_CSD_PARTITION_ACCESS   Partition
+  )
+{
+  MMC_SWITCH_CMD_ARG            CmdArg;
+  MMC_EXT_CSD_PARTITION_CONFIG  PartConfig;
+  EFI_STATUS                    Status;
+
+  LOG_TRACE (
+    "SdhcSwitchPartitionMmc(Partition=%a)",
+    MmcPartitionAccessToString (Partition));
+
+  PartConfig.AsUint8 = HostInst->CardInfo.Registers.Mmc.ExtCsd.PartitionConfig;
+  PartConfig.Fields.PARTITION_ACCESS = Partition;
+
+  // Write the partition type to EXT_CSD[PARTITION_CONFIG].PARTITION_ACCESS
+  ZeroMem (&CmdArg, sizeof (MMC_SWITCH_CMD_ARG));
+  CmdArg.Fields.Access = MmcSwitchCmdAccessTypeWriteByte;
+  CmdArg.Fields.Index = MmcExtCsdBitIndexPartitionConfig;
+  CmdArg.Fields.Value = PartConfig.AsUint8;
+
+  Status = SdhcSendCommand (HostInst, &CmdSwitchMmc, CmdArg.AsUint32);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSendCommand failed. (Status = %r)");
+    return Status;
+  }
+
+  // Re-read the EXT_CSD to verify the partition switch physically happenned
+  Status = SdhcSendExtCsdMmc (HostInst);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  PartConfig.AsUint8 = HostInst->CardInfo.Registers.Mmc.ExtCsd.PartitionConfig;
+  if (PartConfig.Fields.PARTITION_ACCESS != Partition) {
+    LOG_ERROR (
+      "Current partition indicated by EXT_CSD doesn't match the "
+      "partition the MMC should have switched to. Expected:%a Actual:%a",
+      MmcPartitionAccessToString (Partition),
+      MmcPartitionAccessToString (PartConfig.Fields.PARTITION_ACCESS));
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  LOG_TRACE (
+    "Switched from partition %a to %a successfully",
+    MmcPartitionAccessToString (HostInst->CurrentMmcPartition),
+    MmcPartitionAccessToString (Partition));
+
+  HostInst->CurrentMmcPartition = Partition;
+
+  return EFI_SUCCESS;
+}
+
+// SD command definitions
+CONST SD_COMMAND CmdGoIdleState = {
+  0,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeNone,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendOpCondMmc = {
+  1,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR3,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendCidAll = {
+  2,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR2,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendRelativeAddr = {
+  3,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR6,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendOpCondSdio = {
+  5,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR4,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSwitchSd = {
+  6,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionRead
+};
+
+CONST SD_COMMAND CmdSwitchMmc = {
+  6,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1B,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdAppSetBusWidthSd = {
+  6,
+  SdCommandTypeUndefined,
+  SdCommandClassApp,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSelect = {
+  7,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1B,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdDeselect = {
+  7,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeNone,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendIfCondSd = {
+  8,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR6,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendExtCsdMmc = {
+  8,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionRead
+};
+
+CONST SD_COMMAND CmdSendCsd = {
+  9,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR2,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendCid = {
+  10,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR2,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSwitchVoltageSd = {
+  11,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdStopTransmission = {
+  12,
+  SdCommandTypeAbort,
+  SdCommandClassStandard,
+  SdResponseTypeR1B,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdSendStatus = {
+  13,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdBusTestReadMmc = {
+  14,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionRead
+};
+
+CONST SD_COMMAND CmdSetBlockLength = {
+  16,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdReadSingleBlock = {
+  17,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionRead
+};
+
+CONST SD_COMMAND CmdReadMultiBlock = {
+  18,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeMultiBlock,
+  SdTransferDirectionRead
+};
+
+CONST SD_COMMAND CmdBusTestWriteMmc = {
+  19,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionWrite
+};
+
+CONST SD_COMMAND CmdSetBlockCount = {
+  23,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdWriteSingleBlock = {
+  24,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionWrite
+};
+
+CONST SD_COMMAND CmdWriteMultiBlock = {
+  25,
+  SdCommandTypeUndefined,
+  SdCommandClassStandard,
+  SdResponseTypeR1,
+  SdTransferTypeMultiBlock,
+  SdTransferDirectionWrite
+};
+
+CONST SD_COMMAND CmdAppSendOpCondSd = {
+  41,
+  SdCommandTypeUndefined,
+  SdCommandClassApp,
+  SdResponseTypeR3,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdAppSetClrCardDetectSd = {
+  42,
+  SdCommandTypeUndefined,
+  SdCommandClassApp,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
+
+CONST SD_COMMAND CmdAppSendScrSd = {
+  51,
+  SdCommandTypeUndefined,
+  SdCommandClassApp,
+  SdResponseTypeR1,
+  SdTransferTypeSingleBlock,
+  SdTransferDirectionRead
+};
+
+CONST SD_COMMAND CmdAppSd = {
+  55,
+  SdCommandTypeUndefined,
+  SdCommandClassApp,
+  SdResponseTypeR1,
+  SdTransferTypeNone,
+  SdTransferDirectionUndefined
+};
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h b/Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h
new file mode 100644
index 000000000000..b6c09435989c
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h
@@ -0,0 +1,231 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __PROTOCOL_H__
+#define __PROTOCOL_H__
+
+EFI_STATUS
+InitializeDevice (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+InitializeSdDevice (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+InitializeMmcDevice (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendCommand (
+  IN SDHC_INSTANCE      *HostInst,
+  IN CONST SD_COMMAND   *Cmd,
+  IN UINT32             Arg
+  );
+
+EFI_STATUS
+SdhcSendDataCommand (
+  IN SDHC_INSTANCE      *HostInst,
+  IN CONST SD_COMMAND   *Cmd,
+  IN UINT32             Arg,
+  IN UINT32             BufferByteSize,
+  IN OUT VOID           *Buffer
+  );
+
+// SD/SDIO/MMC Generic Functions
+
+EFI_STATUS
+SdhcRecoverFromErrors (
+  IN SDHC_INSTANCE      *HostInst,
+  IN CONST SD_COMMAND   *Cmd
+  );
+
+EFI_STATUS
+SdhcQueryCardType (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcGoIdleState (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendCidAll (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendRelativeAddr (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcWaitForTranStateAndReadyForData (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendCid (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendCsd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendAppCmd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSelectDevice (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcDeselectDevice (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcStopTransmission (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSetMaxClockFrequency (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSetBlockLength (
+  IN SDHC_INSTANCE  *HostInst,
+  IN UINT32          BlockByteLength
+  );
+
+EFI_STATUS
+SdhcSetBlockCount (
+  IN SDHC_INSTANCE  *HostInst,
+  IN UINT32         BlockCount,
+  IN BOOLEAN        ReliableWrite
+  );
+
+EFI_STATUS
+SdhcSendStatus (
+  IN SDHC_INSTANCE  *HostInst,
+  OUT CARD_STATUS   *CardStatus
+  );
+
+// SD Specific Functions
+
+EFI_STATUS
+SdhcSendScrSd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendOpCondSd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendIfCondSd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSwitchBusWidthSd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSwitchSpeedModeSd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+// SDIO Specific Functions
+
+EFI_STATUS
+SdhcSendOpCondSdio (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+// MMC Specific Functions
+
+EFI_STATUS
+SdhcSendOpCondMmc (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSwitchBusWidthMmc (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+
+EFI_STATUS
+SdhcSwitchSpeedModeMmc (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSendExtCsdMmc (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+EFI_STATUS
+SdhcSwitchPartitionMmc (
+  IN SDHC_INSTANCE                  *HostInst,
+  IN MMC_EXT_CSD_PARTITION_ACCESS   Partition
+  );
+
+// SD/MMC Commands
+
+extern CONST SD_COMMAND CmdGoIdleState;
+extern CONST SD_COMMAND CmdSendOpCondMmc;
+extern CONST SD_COMMAND CmdSendCidAll;
+extern CONST SD_COMMAND CmdSendRelativeAddr;
+extern CONST SD_COMMAND CmdSendOpCondSdio;
+extern CONST SD_COMMAND CmdSwitchSd;
+extern CONST SD_COMMAND CmdSwitchMmc;
+extern CONST SD_COMMAND CmdAppSetBusWidthSd;
+extern CONST SD_COMMAND CmdSelect;
+extern CONST SD_COMMAND CmdDeselect;
+extern CONST SD_COMMAND CmdSendIfCondSd;
+extern CONST SD_COMMAND CmdSendExtCsdMmc;
+extern CONST SD_COMMAND CmdSendCsd;
+extern CONST SD_COMMAND CmdSendCid;
+extern CONST SD_COMMAND CmdSwitchVoltageSd;
+extern CONST SD_COMMAND CmdStopTransmission;
+extern CONST SD_COMMAND CmdSendStatus;
+extern CONST SD_COMMAND CmdBusTestReadMmc;
+extern CONST SD_COMMAND CmdSetBlockLength;
+extern CONST SD_COMMAND CmdReadSingleBlock;
+extern CONST SD_COMMAND CmdReadMultiBlock;
+extern CONST SD_COMMAND CmdBusTestWriteMmc;
+extern CONST SD_COMMAND CmdSetBlockCount;
+extern CONST SD_COMMAND CmdWriteSingleBlock;
+extern CONST SD_COMMAND CmdWriteMultiBlock;
+extern CONST SD_COMMAND CmdAppSendOpCondSd;
+extern CONST SD_COMMAND CmdAppSetClrCardDetectSd;
+extern CONST SD_COMMAND CmdAppSendScrSd;
+extern CONST SD_COMMAND CmdAppSd;
+
+#endif // __PROTOCOL_H__
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c b/Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c
new file mode 100644
index 000000000000..b0af15b7a749
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c
@@ -0,0 +1,609 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/RpmbIo.h>
+#include <Protocol/Sdhc.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "SdMmcHw.h"
+#include "SdMmc.h"
+#include "Protocol.h"
+
+C_ASSERT(sizeof(EFI_RPMB_DATA_PACKET) == SD_BLOCK_LENGTH_BYTES);
+
+EFI_RPMB_DATA_PACKET ResultRequest = {
+  { 0 }, // Stuff
+  { 0 }, // MAC
+  { 0 }, // Data
+  { 0 }, // Nonce
+  { 0 }, // WriteCounter
+  { 0 }, // Address
+  { 0 }, // PacketCount
+  { 0 }, // OperationResult
+  { 0x00, EFI_RPMB_REQUEST_RESULT_REQUEST } // RequestType
+};
+
+// JEDEC Standard No. 84-A441:
+// Byte order of the RPMB data frame is MSB first, e.g. Write Counter MSB [11]
+// is storing the upmost byte of the counter value.
+
+VOID
+Uint16ToRpmbBytes (
+  IN UINT16   Value,
+  OUT UINT8   *RpmbBytes
+  )
+{
+  ASSERT (RpmbBytes != NULL);
+
+  RpmbBytes[0] = (UINT8) (Value >> 8);
+  RpmbBytes[1] = (UINT8) (Value & 0xF);
+}
+
+
+UINT16
+RpmbBytesToUint16 (
+  IN CONST UINT8  *RpmbBytes
+  )
+{
+  ASSERT (RpmbBytes != NULL);
+
+  return ((UINT16) RpmbBytes[0] << 8) | ((UINT16) RpmbBytes[1]);
+}
+
+EFI_STATUS
+RpmbRead (
+  IN SDHC_INSTANCE          *HostInst,
+  IN EFI_RPMB_DATA_PACKET   *Request,
+  OUT EFI_RPMB_DATA_BUFFER  *Response
+  )
+{
+  EFI_STATUS Status;
+
+  Status = SdhcSetBlockCount (HostInst, 1, FALSE);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSetBlockCount() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  Status = SdhcSendDataCommand (
+    HostInst,
+    &CmdWriteMultiBlock,
+    0, // LBA argument is ignored for RPMB access, the eMMC will use instead the Address
+       // field of the RPMB packet
+    sizeof (*Request),
+    Request);
+
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "Failed to write the Read request data packet. (Status = %r)",
+      Status);
+
+    return Status;
+  }
+
+  Status = SdhcSetBlockCount (HostInst, Response->PacketCount, FALSE);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSetBlockCount() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  Status = SdhcSendDataCommand (
+    HostInst,
+    &CmdReadMultiBlock,
+    0, // LBA argument is ignored for RPMB access, the eMMC will use instead the Address
+       // field of the RPMB packet
+    Response->PacketCount * sizeof(*Response->Packets),
+    Response->Packets);
+
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "Failed to read the Read request data packet. (Status = %r)",
+      Status);
+
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RpmbWrite (
+  IN SDHC_INSTANCE          *HostInst,
+  IN EFI_RPMB_DATA_BUFFER   *Request
+  )
+{
+  EFI_STATUS Status;
+
+  Status = SdhcSetBlockCount (HostInst, Request->PacketCount, TRUE);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SdhcSetBlockCount() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  Status = SdhcSendDataCommand (
+    HostInst,
+    &CmdWriteMultiBlock,
+    0, // LBA argument is ignored for RPMB access, the eMMC will use instead the Address
+       // field of the RPMB packet
+    Request->PacketCount * sizeof(*Request->Packets),
+    Request->Packets);
+
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "Failed to write the Read request data packet. (Status = %r)",
+      Status);
+
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RpmbQueryResult (
+  IN SDHC_INSTANCE          *HostInst,
+  OUT EFI_RPMB_DATA_PACKET  *Response
+  )
+{
+  EFI_RPMB_DATA_BUFFER  ResponseBuffer;
+  EFI_STATUS            Status;
+
+  ResponseBuffer.PacketCount = 1;
+  ResponseBuffer.Packets = Response;
+
+  Status = RpmbRead (HostInst, &ResultRequest, &ResponseBuffer);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRead() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RpmbProgramKeyRequest (
+  IN SDHC_INSTANCE          *HostInst,
+  IN EFI_RPMB_DATA_PACKET   *Request,
+  OUT EFI_RPMB_DATA_PACKET  *Response
+  )
+{
+  EFI_RPMB_DATA_BUFFER  RequestBuffer;
+  EFI_STATUS            Status;
+
+  RequestBuffer.PacketCount = 1;
+  RequestBuffer.Packets = Request;
+
+  Status = RpmbWrite (HostInst, &RequestBuffer);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbWrite() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  Status = RpmbQueryResult (HostInst, Response);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbQueryResult() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RpmbReadCounterRequest (
+  IN SDHC_INSTANCE          *HostInst,
+  IN EFI_RPMB_DATA_PACKET   *Request,
+  OUT EFI_RPMB_DATA_PACKET  *Response
+  )
+{
+  EFI_RPMB_DATA_BUFFER  ResponseBuffer;
+  EFI_STATUS            Status;
+
+  ResponseBuffer.PacketCount = 1;
+  ResponseBuffer.Packets = Response;
+
+  Status = RpmbRead (HostInst, Request, &ResponseBuffer);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRead() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RpmbAuthenticatedWriteRequest (
+  IN SDHC_INSTANCE          *HostInst,
+  IN EFI_RPMB_DATA_BUFFER   *Request,
+  OUT EFI_RPMB_DATA_PACKET  *Response
+  )
+{
+  EFI_STATUS Status;
+
+  Status = RpmbWrite (HostInst, Request);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbWrite() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  Status = RpmbQueryResult (HostInst, Response);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbQueryResult() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RpmbAuthenticatedReadRequest (
+  IN SDHC_INSTANCE          *HostInst,
+  IN EFI_RPMB_DATA_PACKET   *Request,
+  OUT EFI_RPMB_DATA_BUFFER  *Response
+  )
+{
+  EFI_STATUS Status;
+
+  Status = RpmbRead (HostInst, Request, Response);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRead() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+VOID
+RpmbHexDump (
+  IN CONST UINT8  *Bytes,
+  IN UINTN        Len
+  )
+{
+  UINTN i;
+
+  for (i = 0; i < Len; i++) {
+    if ((i > 0) && (i % 16) == 0) {
+      LOG_VANILLA_TRACE ("\n");
+    }
+    LOG_VANILLA_TRACE ("%02x ", *Bytes);
+    ++Bytes;
+  }
+  LOG_VANILLA_TRACE ("\n");
+}
+
+VOID
+RpmbDumpPacket (
+  IN EFI_RPMB_DATA_PACKET *Packet
+  )
+{
+  LOG_TRACE ("*** RPMB Packet Dump (Packet = %p) ***", Packet);
+  LOG_TRACE ("- Write Counter");
+  RpmbHexDump (Packet->WriteCounter, EFI_RPMB_PACKET_WCOUNTER_SIZE);
+  LOG_TRACE ("- Address:");
+  RpmbHexDump (Packet->Address, EFI_RPMB_PACKET_ADDRESS_SIZE);
+  LOG_TRACE ("- Block Count:");
+  RpmbHexDump (Packet->BlockCount, EFI_RPMB_PACKET_BLOCKCOUNT_SIZE);
+  LOG_TRACE ("- Result:");
+  RpmbHexDump (Packet->OperationResult, EFI_RPMB_PACKET_RESULT_SIZE);
+  LOG_TRACE ("- Req/Res Type:");
+  RpmbHexDump (Packet->RequestOrResponseType, EFI_RPMB_PACKET_TYPE_SIZE);
+}
+
+EFI_STATUS
+RpmbRequest (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_BUFFER   *Request,
+  OUT EFI_RPMB_DATA_BUFFER  *Response
+  )
+{
+  SDHC_INSTANCE                 *HostInst;
+  MMC_EXT_CSD_PARTITION_ACCESS  CurrentPartition;
+  UINT16                        RequestType;
+  EFI_STATUS                    Status;
+  BOOLEAN                       SwitchPartition;
+  EFI_STATUS                    SwitchStatus;
+
+  SwitchPartition = FALSE;
+  Status = EFI_SUCCESS;
+  SwitchStatus = EFI_SUCCESS;
+
+  ASSERT (This);
+  ASSERT (Request);
+  ASSERT (Response);
+
+  HostInst = SDHC_INSTANCE_FROM_RPMB_IO_THIS (This);
+  ASSERT (HostInst);
+  ASSERT (HostInst->HostExt);
+
+  CurrentPartition = HostInst->CurrentMmcPartition;
+  SwitchStatus = SdhcSwitchPartitionMmc (HostInst, MmcExtCsdPartitionAccessRpmb);
+  if (EFI_ERROR (SwitchStatus)) {
+    LOG_ERROR (
+      "SdhcSwitchPartitionMmc() failed. (SwitchStatus = %r)",
+      SwitchStatus);
+
+    goto Exit;
+  }
+
+  SwitchPartition = TRUE;
+
+  ASSERT (Request->PacketCount > 0);
+  ASSERT (Request->Packets != NULL);
+  RequestType = RpmbBytesToUint16 (Request->Packets[0].RequestOrResponseType);
+
+  switch (RequestType) {
+  case EFI_RPMB_REQUEST_PROGRAM_KEY:
+    Status = RpmbProgramKeyRequest (HostInst, Request->Packets, Response->Packets);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("RpmbProgramKeyRequest() failed. (Status = %r)", Status);
+      goto Exit;
+    }
+    break;
+
+  case EFI_RPMB_REQUEST_COUNTER_VALUE:
+    Status = RpmbReadCounterRequest (HostInst, Request->Packets, Response->Packets);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("RpmbReadCounterRequest() failed. (Status = %r)", Status);
+      goto Exit;
+    }
+    break;
+
+  case EFI_RPMB_REQUEST_AUTH_READ:
+    Status = RpmbAuthenticatedReadRequest (HostInst, Request->Packets, Response);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("RpmbAuthenticatedReadRequest() failed. (Status = %r)", Status);
+      goto Exit;
+    }
+    break;
+
+  case EFI_RPMB_REQUEST_AUTH_WRITE:
+    Status = RpmbAuthenticatedWriteRequest (HostInst, Request, Response->Packets);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR ("RpmbAuthenticatedWriteRequest() failed. (Status = %r)", Status);
+      goto Exit;
+    }
+    break;
+
+  default:
+
+    ASSERT (FALSE);
+  }
+
+Exit:
+
+  if (SwitchPartition) {
+    SwitchStatus = SdhcSwitchPartitionMmc (HostInst, CurrentPartition);
+    if (EFI_ERROR (SwitchStatus)) {
+
+      LOG_ERROR (
+        "SdhcSwitchPartitionMmc() failed. (SwitchStatus = %r)",
+        SwitchStatus);
+    }
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  } else {
+    return SwitchStatus;
+  }
+}
+
+/** Authentication key programming request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ProgrammingRequest A data packet describing a key programming request.
+  @param[out] ResultResponse A caller allocated data packet which will receive the
+  key programming result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during key programming any other eMMC internal failure is reported
+  in the Result field of the returned response data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoProgramKey (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ProgrammingRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ResultResponse
+  )
+{
+  EFI_RPMB_DATA_BUFFER  RequestBuffer;
+  EFI_RPMB_DATA_BUFFER  ResponseBuffer;
+  EFI_STATUS            Status;
+
+  LOG_TRACE ("RpmbIoProgramKey()");
+
+  if ((This == NULL) || (ProgrammingRequest == NULL) || (ResultResponse == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (RpmbBytesToUint16 (ProgrammingRequest->RequestOrResponseType) != EFI_RPMB_REQUEST_PROGRAM_KEY) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RequestBuffer.PacketCount = 1;
+  RequestBuffer.Packets = ProgrammingRequest;
+
+  ResponseBuffer.PacketCount = 1;
+  ResponseBuffer.Packets = ResultResponse;
+
+  Status = RpmbRequest (This, &RequestBuffer, &ResponseBuffer);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRequest() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return Status;
+}
+
+/** Reading of the write counter value request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ReadRequest A data packet describing a read counter value request.
+  @param[out] ReadResponse A caller allocated data packet which will receive
+  the counter value read response. If counter has expired bit 7 is set to 1 in
+  returned Result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during counter read or any other eMMC internal failure is reported
+  in the Result field of the returned response data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoReadCounter (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ReadRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ReadResponse
+  )
+{
+  EFI_RPMB_DATA_BUFFER  RequestBuffer;
+  EFI_RPMB_DATA_BUFFER  ResponseBuffer;
+  EFI_STATUS            Status;
+
+  LOG_TRACE ("RpmbIoReadCounter()");
+
+  if ((This == NULL) || (ReadRequest == NULL) || (ReadResponse == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (RpmbBytesToUint16 (ReadRequest->RequestOrResponseType) != EFI_RPMB_REQUEST_COUNTER_VALUE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RequestBuffer.PacketCount = 1;
+  RequestBuffer.Packets = ReadRequest;
+
+  ResponseBuffer.PacketCount = 1;
+  ResponseBuffer.Packets = ReadResponse;
+
+  Status = RpmbRequest (This, &RequestBuffer, &ResponseBuffer);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRequest() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return Status;
+}
+
+/** Authenticated data write request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] WriteRequest A sequence of data packets describing data write
+  requests and holds the data to be written.
+  @param[out] ResultResponse A caller allocated data packet which will receive
+  the data write programming result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during data programming or any other eMMC internal failure is reported
+  in the Result field of the returned data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoAuthenticatedWrite (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_BUFFER   *Request,
+  OUT EFI_RPMB_DATA_PACKET  *Response
+  )
+{
+  EFI_RPMB_DATA_BUFFER  ResponseBuffer;
+  EFI_STATUS            Status;
+
+  LOG_TRACE ("RpmbIoAuthenticatedWrite()");
+
+  if ((This == NULL) || (Request == NULL) || (Response == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Request->Packets == NULL) || (Request->PacketCount == 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (RpmbBytesToUint16 (Request->Packets->RequestOrResponseType) != EFI_RPMB_REQUEST_AUTH_WRITE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ResponseBuffer.PacketCount = 1;
+  ResponseBuffer.Packets = Response;
+
+  Status = RpmbRequest (This, Request, &ResponseBuffer);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRequest() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return Status;
+}
+
+/** Authenticated data read request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ReadRequest A data packet that describes a data read request.
+  @param[out] ReadResponse A caller allocated data packets which will receive
+  the data read.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during data fetch from the eMMC or any other eMMC internal failure
+  is reported in the Result field of the returned data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoAuthenticatedRead (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ReadRequest,
+  OUT EFI_RPMB_DATA_BUFFER  *ReadResponse
+  )
+{
+  EFI_RPMB_DATA_BUFFER  RequestBuffer;
+  EFI_STATUS            Status;
+
+  LOG_TRACE ("RpmbIoAuthenticatedRead()");
+
+  if ((This == NULL) || (ReadRequest == NULL) || (ReadResponse == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((ReadResponse->Packets == NULL) || (ReadResponse->PacketCount == 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (RpmbBytesToUint16 (ReadRequest->RequestOrResponseType) != EFI_RPMB_REQUEST_AUTH_READ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RequestBuffer.PacketCount = 1;
+  RequestBuffer.Packets = ReadRequest;
+
+  Status = RpmbRequest (This, &RequestBuffer, ReadResponse);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("RpmbRequest() failed. (Status = %r)", Status);
+    return Status;
+  }
+
+  return Status;
+}
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c
new file mode 100644
index 000000000000..bdfb5bf84083
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c
@@ -0,0 +1,886 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/RpmbIo.h>
+#include <Protocol/Sdhc.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "SdMmcHw.h"
+#include "SdMmc.h"
+#include "Protocol.h"
+
+// A template EFI_BLOCK_IO media to use for creating new EFI_BLOCK_IO protocols
+// for new SDHC instances.
+EFI_BLOCK_IO_MEDIA gSdhcMediaTemplate = {
+  0,                      // MediaId
+  TRUE,                   // RemovableMedia
+  FALSE,                  // MediaPresent
+  FALSE,                  // LogicalPartition
+  FALSE,                  // ReadOnly
+  FALSE,                  // WriteCaching
+  SD_BLOCK_LENGTH_BYTES,  // BlockSize
+  4,                      // IoAlign
+  0,                      // Pad
+  0                       // LastBlock
+};
+
+// This structure is serviced as a header.Its next field points to the first root
+// bridge device node.
+LIST_ENTRY  gSdhcInstancePool;
+UINT32 gNextSdhcInstanceId = 0;
+
+// Event triggered by the timer to check if any cards have been removed
+// or if new ones have been plugged in.
+EFI_EVENT gCheckCardsEvent;
+
+// The ARM high-performance counter frequency.
+UINT64 gHpcTicksPerSeconds = 0;
+
+VOID
+EFIAPI
+CheckCardsCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+EFI_STATUS
+EFIAPI
+UninstallAllProtocols (
+  IN SDHC_INSTANCE *HostInst
+  );
+
+BOOLEAN
+EFIAPI
+IsRpmbInstalledOnTheSystem (
+  VOID
+  );
+
+/** Initialize the SDHC Pool to support multiple SD/MMC devices.
+**/
+VOID
+InitializeSdhcPool (
+  VOID
+  )
+{
+  InitializeListHead (&gSdhcInstancePool);
+}
+
+/** Insert a new SDHC instance in the host pool.
+
+  @param[in] HostInst The SDHC instance context data.
+**/
+VOID
+InsertSdhcInstance (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  InsertTailList (&gSdhcInstancePool, &(HostInst->Link));
+}
+
+/** Removes an existing SDHC instance context data from the host pool.
+
+  @param[in] HostInst The SDHC instance data.
+**/
+VOID
+RemoveSdhcInstance (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  RemoveEntryList (&(HostInst->Link));
+}
+
+/** Creates a new SDHC instance context data.
+
+  It initializes the context data but does not attempt to perform any hardware
+  access nor install any EFI protocol. This happens later on when a card presence
+  state changes during the card check callback.
+
+  @param[in] HostExt The EFI_SDHC_PROTOCOL instance data to use as the basis for
+  SDHC instance context data creation.
+
+  @retval An SDHC instance context data on successful instance creation and return
+  NULL otherwise.
+**/
+SDHC_INSTANCE*
+CreateSdhcInstance (
+  IN EFI_SDHC_PROTOCOL  *HostExt
+  )
+{
+  SDHC_DEVICE_PATH  *DevicePath;
+  SDHC_INSTANCE     *HostInst;
+  GUID              SdhcDevicePathGuid = SDHC_DEVICE_PATH_GUID;
+  EFI_STATUS        Status;
+
+  HostInst = NULL;
+  HostInst = AllocateZeroPool (sizeof (SDHC_INSTANCE));
+  if (HostInst == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  HostInst->Signature = SDHC_INSTANCE_SIGNATURE;
+  HostInst->InstanceId = gNextSdhcInstanceId;
+  HostInst->HostExt = HostExt;
+
+  HostExt->GetCapabilities (HostExt, &HostInst->HostCapabilities);
+  ASSERT (HostInst->HostCapabilities.MaximumBlockSize > 0);
+  ASSERT (HostInst->HostCapabilities.MaximumBlockCount > 0);
+
+  // We will support 512 byte blocks only.
+  if (HostInst->HostCapabilities.MaximumBlockSize < SD_BLOCK_LENGTH_BYTES) {
+    LOG_ERROR (
+      "Unsupported max block size of %d bytes",
+      HostInst->HostCapabilities.MaximumBlockSize);
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  LOG_TRACE (
+    "Host Capabilities: MaximumBlockSize:%d MaximumBlockCount:%d",
+    HostInst->HostCapabilities.MaximumBlockSize,
+    HostInst->HostCapabilities.MaximumBlockCount);
+
+  HostInst->DevicePathProtocolInstalled = FALSE;
+  HostInst->BlockIoProtocolInstalled = FALSE;
+  HostInst->RpmbIoProtocolInstalled = FALSE;
+
+  // Initialize BlockIo Protocol.
+  HostInst->BlockIo.Media = AllocateCopyPool (sizeof (EFI_BLOCK_IO_MEDIA), &gSdhcMediaTemplate);
+  if (HostInst->BlockIo.Media == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  HostInst->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;
+  HostInst->BlockIo.Reset = BlockIoReset;
+  HostInst->BlockIo.ReadBlocks = BlockIoReadBlocks;
+  HostInst->BlockIo.WriteBlocks = BlockIoWriteBlocks;
+  HostInst->BlockIo.FlushBlocks = BlockIoFlushBlocks;
+
+  // Initialize DevicePath Protocol.
+  DevicePath = &HostInst->DevicePath;
+
+  // Initialize device path based on SDHC DeviceId and delay SlotNode initialization
+  // until the card in Slot0 is type identified.
+  DevicePath->SdhcNode.Header.Type = HARDWARE_DEVICE_PATH;
+  DevicePath->SdhcNode.Header.SubType = HW_VENDOR_DP;
+  *((UINT16*) &DevicePath->SdhcNode.Header.Length) = SDHC_NODE_PATH_LENGTH;
+  DevicePath->SdhcId = HostInst->HostExt->SdhcId;
+  CopyGuid (&DevicePath->SdhcNode.Guid, &SdhcDevicePathGuid);
+
+  SetDevicePathEndNode (&DevicePath->EndNode);
+
+  // Initialize RpmbIo Protocol.
+  HostInst->RpmbIo.Revision = EFI_RPMB_IO_PROTOCOL_REVISION;
+  HostInst->RpmbIo.AuthenticatedRead = RpmbIoAuthenticatedRead;
+  HostInst->RpmbIo.AuthenticatedWrite = RpmbIoAuthenticatedWrite;
+  HostInst->RpmbIo.ProgramKey = RpmbIoProgramKey;
+  HostInst->RpmbIo.ReadCounter = RpmbIoReadCounter;
+
+  // Don't publish any protocol yet, until the SDHC device is fully initialized and
+  // ready for IO.
+  ++gNextSdhcInstanceId;
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    if (HostInst != NULL && HostInst->BlockIo.Media != NULL) {
+      FreePool (HostInst->BlockIo.Media);
+      HostInst->BlockIo.Media = NULL;
+    }
+
+    if (HostInst != NULL) {
+      FreePool (HostInst);
+      HostInst = NULL;
+    }
+  }
+
+  return HostInst;
+}
+
+/** Destroys an existing SDHC instance context data.
+
+  It uninstalls all protocols installed on that instance, free allocated memory
+  and invokes the SDHC clean-up callback.
+
+  @param[in] HostInst The SDHC instance context data to destroy.
+
+  @retval EFI_SUCCESS on successful destruction and cleanup, return an EFI error
+  code otherwise.
+**/
+EFI_STATUS
+DestroySdhcInstance (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_STATUS Status;
+
+  Status = UninstallAllProtocols (HostInst);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Free Memory allocated for the EFI_BLOCK_IO protocol
+  if (HostInst->BlockIo.Media) {
+    FreePool (HostInst->BlockIo.Media);
+  }
+
+  HostInst->HostExt->Cleanup (HostInst->HostExt);
+  HostInst->HostExt = NULL;
+
+  FreePool (HostInst);
+
+  return EFI_SUCCESS;
+}
+
+// UEFI Driver Model EFI_DRIVER_BINDING_PROTOCOL Callbacks
+
+/**
+    Tests to see if this driver supports a given controller. If a child device is provided,
+    it further tests to see if this driver supports creating a handle for the specified child device.
+
+    @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+    @param ControllerHandle     The handle of the controller to test. This handle must support a protocol
+                                interface that supplies an I/O abstraction to the driver. Sometimes
+                                just the presence of this I/O abstraction is enough for the driver to
+                                determine if it supports ControllerHandle. Sometimes, the driver may
+                                use the services of the I/O abstraction to determine if this driver
+                                supports ControllerHandle.
+    @param RemainingDevicePath  A pointer to the remaining portion of a device path. For bus drivers,
+                                if this parameter is not NULL, then the bus driver must determine if
+                                the bus controller specified by ControllerHandle and the child controller
+                                specified by RemainingDevicePath
+**/
+EFI_STATUS
+EFIAPI
+SdMmcDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_SDHC_PROTOCOL   *HostExt;
+  EFI_DEV_PATH_PTR    Node;
+  EFI_STATUS          Status;
+
+  // Check RemainingDevicePath validation.
+  if (RemainingDevicePath != NULL) {
+
+    // Check if RemainingDevicePath is the End of Device Path Node,
+    // if yes, go on checking other conditions.
+    if (!IsDevicePathEnd (RemainingDevicePath)) {
+
+      // If RemainingDevicePath isn't the End of Device Path Node,
+      // check its validation.
+
+      Node.DevPath = RemainingDevicePath;
+      if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
+          Node.DevPath->SubType != HW_VENDOR_DP ||
+          DevicePathNodeLength (Node.DevPath) != sizeof (VENDOR_DEVICE_PATH)) {
+        Status = EFI_UNSUPPORTED;
+        goto Exit;
+      }
+    }
+  }
+
+  // Check if SDHC protocol is installed by platform.
+
+  Status = gBS->OpenProtocol (
+    Controller,
+    &gEfiSdhcProtocolGuid,
+    (VOID **) &HostExt,
+    This->DriverBindingHandle,
+    Controller,
+    EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (Status == EFI_ALREADY_STARTED) {
+    Status = EFI_SUCCESS;
+    goto Exit;
+  }
+
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  // Close the SDHC used to perform the supported test.
+  gBS->CloseProtocol (
+    Controller,
+    &gEfiSdhcProtocolGuid,
+    This->DriverBindingHandle,
+    Controller);
+
+Exit:
+  return Status;
+}
+
+/**
+    Starts a device controller or a bus controller. The Start() and Stop() services of the
+    EFI_DRIVER_BINDING_PROTOCOL mirror each other.
+
+    @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+    @param ControllerHandle     The handle of the controller to start. This handle must support a
+                                protocol interface that supplies an I/O abstraction to the driver.
+    @param RemainingDevicePath  A pointer to the remaining portion of a device path. For a bus driver,
+                                if this parameter is NULL, then handles for all the children of Controller
+                                are created by this driver.
+                                If this parameter is not NULL and the first Device Path Node is not
+                                the End of Device Path Node, then only the handle for the child device
+                                specified by the first Device Path Node of RemainingDevicePath is created
+                                by this driver.
+                                If the first Device Path Node of RemainingDevicePath is the End of Device
+                                Path Node, no child handle is created by this driver.
+**/
+EFI_STATUS
+EFIAPI
+SdMmcDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_SDHC_PROTOCOL   *HostExt;
+  SDHC_INSTANCE       *HostInst;
+  EFI_STATUS          Status;
+
+  LOG_TRACE ("SdMmcDriverStart()");
+
+  // Check RemainingDevicePath validation.
+  if (RemainingDevicePath != NULL) {
+
+    // Check if RemainingDevicePath is the End of Device Path Node,
+    // if yes, return EFI_SUCCESS.
+    if (IsDevicePathEnd (RemainingDevicePath)) {
+      Status = EFI_SUCCESS;
+      goto Exit;
+    }
+  }
+
+  // Get the SDHC protocol.
+
+  Status = gBS->OpenProtocol (
+    Controller,
+    &gEfiSdhcProtocolGuid,
+    (VOID **) &HostExt,
+    This->DriverBindingHandle,
+    Controller,
+    EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_ALREADY_STARTED) {
+      Status = EFI_SUCCESS;
+    }
+    goto Exit;
+  }
+
+  HostInst = CreateSdhcInstance (HostExt);
+  if (HostInst != NULL) {
+    HostInst->MmcHandle = Controller;
+    InsertSdhcInstance (HostInst);
+
+    LOG_INFO (
+      "SDHC%d instance creation completed. Detecting card presence...",
+      HostInst->HostExt->SdhcId);
+
+    // Detect card presence now which will initialize the SDHC.
+    CheckCardsCallback (NULL, NULL);
+  } else {
+    LOG_ERROR ("CreateSdhcInstance failed. %r", Status);
+  }
+
+Exit:
+  return Status;
+}
+
+/**
+    Stops a device controller or a bus controller. The Start() and Stop() services of the
+    EFI_DRIVER_BINDING_PROTOCOL mirror each other.
+
+    @param This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+                                Type EFI_DRIVER_BINDING_PROTOCOL is defined in Section 10.1.
+    @param ControllerHandle     A handle to the device being stopped. The handle must support a bus
+                                specific I/O protocol for the driver to use to stop the device.
+    @param NumberOfChildren     The number of child device handles in ChildHandleBuffer.
+    @param ChildHandleBuffer    An array of child handles to be freed. May be NULL if NumberOfChildren is 0.
+**/
+EFI_STATUS
+EFIAPI
+SdMmcDriverStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN UINTN                        NumberOfChildren,
+  IN EFI_HANDLE                   *ChildHandleBuffer
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  SDHC_INSTANCE   *HostInst;
+  EFI_STATUS      Status;
+
+  Status = EFI_SUCCESS;
+
+  LOG_TRACE ("SdMmcDriverStop()");
+
+  // For each registered SDHC instance.
+  CurrentLink = gSdhcInstancePool.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &gSdhcInstancePool && (Status == EFI_SUCCESS)) {
+    HostInst = SDHC_INSTANCE_FROM_LINK (CurrentLink);
+    ASSERT (HostInst != NULL);
+
+    // Close gEfiMmcHostProtocolGuid opened on the SDHC.
+    Status = gBS->CloseProtocol (
+      Controller,
+      &gEfiSdhcProtocolGuid,
+      (VOID **) &HostInst->HostExt,
+      This->DriverBindingHandle);
+
+    // Remove SDHC instance from the pool.
+    RemoveSdhcInstance (HostInst);
+
+    // Destroy SDHC instance.
+    DestroySdhcInstance (HostInst);
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SoftReset (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  SDHC_DEVICE_PATH    *DevicePath;
+  CHAR16              *DevicePathText;
+  EFI_SDHC_PROTOCOL   *HostExt;
+  MMC_EXT_CSD_PARTITION_CONFIG PartConfig;
+  EFI_STATUS          Status;
+
+  HostExt = HostInst->HostExt;
+  DevicePathText = NULL;
+
+  ASSERT (HostInst->HostExt != NULL);
+  LOG_TRACE ("Performing Soft-Reset for SDHC%d", HostExt->SdhcId);
+
+  Status = UninstallAllProtocols (HostInst);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  HostInst->SlotInitialized = FALSE;
+
+  // Clear all media settings regardless of card presence.
+  HostInst->BlockIo.Media->MediaId = 0;
+  HostInst->BlockIo.Media->RemovableMedia = FALSE;
+  HostInst->BlockIo.Media->MediaPresent = FALSE;
+  HostInst->BlockIo.Media->LogicalPartition = FALSE;
+  HostInst->BlockIo.Media->WriteCaching = FALSE;
+  HostInst->BlockIo.Media->BlockSize = 0;
+  HostInst->BlockIo.Media->IoAlign = 4;
+  HostInst->BlockIo.Media->LastBlock = 0;
+  HostInst->BlockIo.Media->LowestAlignedLba = 0;
+  HostInst->BlockIo.Media->LogicalBlocksPerPhysicalBlock = 0;
+  HostInst->BlockIo.Media->OptimalTransferLengthGranularity = 0;
+  HostInst->BlockIo.Media->ReadOnly = FALSE;
+
+  HostInst->RpmbIo.ReliableSectorCount = 0;
+  HostInst->RpmbIo.RpmbSizeMult = 0;
+  ZeroMem (HostInst->RpmbIo.Cid, sizeof (HostInst->RpmbIo.Cid));
+
+  HostInst->BlockIo.Media->MediaPresent = HostInst->HostExt->IsCardPresent (HostInst->HostExt);
+  if (!HostInst->BlockIo.Media->MediaPresent) {
+    // Even if the media is not present, we`d like to communicate that status up
+    // to the storage stack by means of installing the BlockIo protocol.
+    Status =
+      gBS->InstallMultipleProtocolInterfaces (
+        &HostInst->MmcHandle,
+        &gEfiBlockIoProtocolGuid,
+        &HostInst->BlockIo,
+        NULL);
+
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "SoftReset(): Failed installing EFI_BLOCK_IO_PROTOCOL interface. %r",
+        Status);
+
+      goto Exit;
+    }
+
+    HostInst->BlockIoProtocolInstalled = TRUE;
+    LOG_INFO ("SDHC%d media not present, skipping device initialization", HostExt->SdhcId);
+    goto Exit;
+  } else {
+    HostInst->BlockIo.Media->ReadOnly = HostExt->IsReadOnly (HostExt);
+    if (HostInst->BlockIo.Media->ReadOnly) {
+      LOG_INFO ("SDHC%d media is read-only", HostExt->SdhcId);
+    }
+  }
+
+  Status = InitializeDevice (HostInst);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("SoftReset(): InitializeDevice() failed. %r", Status);
+    goto Exit;
+  }
+
+  // Update SlotNode subtype based on the card type identified.
+  // Note that we only support 1 slot per SDHC, i.e It is assumed that no more
+  // than 1 SD/MMC card connected to the same SDHC block on the system.
+  DevicePath = &HostInst->DevicePath;
+  if (HostInst->CardInfo.CardFunction == CardFunctionSd) {
+    DevicePath->SlotNode.SD.Header.Type = MESSAGING_DEVICE_PATH;
+    DevicePath->SlotNode.SD.Header.SubType = MSG_SD_DP;
+    *((UINT16*) &DevicePath->SlotNode.SD.Header.Length) = sizeof (SD_DEVICE_PATH);
+    DevicePath->SlotNode.SD.SlotNumber = 0;
+  } else {
+    ASSERT (HostInst->CardInfo.CardFunction == CardFunctionMmc);
+    DevicePath->SlotNode.MMC.Header.Type = MESSAGING_DEVICE_PATH;
+    DevicePath->SlotNode.MMC.Header.SubType = MSG_EMMC_DP;
+    *((UINT16*) &DevicePath->SlotNode.MMC.Header.Length) = sizeof (EMMC_DEVICE_PATH);
+    DevicePath->SlotNode.MMC.SlotNumber = 0;
+  }
+
+  // Print a text representation of the Slot device path.
+  DevicePathText = ConvertDevicePathToText ((EFI_DEVICE_PATH_PROTOCOL*) DevicePath, FALSE, FALSE);
+
+  if (DevicePathText == NULL) {
+    LOG_ERROR ("SoftReset(): ConvertDevicePathToText() failed.");
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  LOG_INFO ("Recognized device: %s", DevicePathText);
+
+  Status =
+    gBS->InstallMultipleProtocolInterfaces (
+      &HostInst->MmcHandle,
+      &gEfiBlockIoProtocolGuid,
+      &HostInst->BlockIo,
+      NULL);
+
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "SoftReset(): Failed installing EFI_BLOCK_IO_PROTOCOL interface. %r",
+      Status);
+
+    goto Exit;
+  }
+
+  HostInst->BlockIoProtocolInstalled = TRUE;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+      &HostInst->MmcHandle,
+      &gEfiDevicePathProtocolGuid,
+      &HostInst->DevicePath,
+      NULL);
+
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR (
+      "SoftReset(): Failed installing EFI_DEVICE_PATH_PROTOCOL interface. %r",
+      Status);
+
+    goto Exit;
+  }
+
+  HostInst->DevicePathProtocolInstalled = TRUE;
+
+  if (HostInst->CardInfo.CardFunction == CardFunctionMmc) {
+    if (!IsRpmbInstalledOnTheSystem ()) {
+      Status = gBS->InstallMultipleProtocolInterfaces (
+          &HostInst->MmcHandle,
+          &gEfiRpmbIoProtocolGuid,
+          &HostInst->RpmbIo,
+          NULL);
+
+      if (EFI_ERROR (Status)) {
+        LOG_ERROR (
+          "SoftReset(): Failed installing EFI_RPMB_IO_PROTOCOL interface. %r",
+          Status);
+
+        goto Exit;
+      }
+
+      LOG_INFO ("RpmbIo protocol installed for MMC: %s", DevicePathText);
+
+      HostInst->RpmbIoProtocolInstalled = TRUE;
+
+      // Track current partition in a separate variable to void having to
+      // ready the MMC EXT_CSD everytime we do partition switch to have
+      // an updated current partition. SdhostSwitchPartitionMmc will keep
+      // track of that variable.
+      PartConfig.AsUint8 = HostInst->CardInfo.Registers.Mmc.ExtCsd.PartitionConfig;
+      HostInst->CurrentMmcPartition =
+        (MMC_EXT_CSD_PARTITION_ACCESS) PartConfig.Fields.PARTITION_ACCESS;
+
+    } else {
+      LOG_ERROR (
+        "SoftReset(): RpmbIo protocol is already installed on the system. "
+        "The requirement is that only 1 MMC on the system should have RpmbIo "
+        "protocol installed. Skipping RpmbIo protocol installation for %s",
+        DevicePathText);
+    }
+  }
+
+  LOG_TRACE ("All required protocols installed successfully for %s", DevicePathText);
+
+Exit:
+
+  // On error we should uninstall all protocols except BlockIo, it should
+  // always be present since it represents the SDHC physical existance not
+  // the card, other protocols are card dependant and are pure representation
+  // of one or more card features
+  if (EFI_ERROR (Status)) {
+    if (HostInst->RpmbIoProtocolInstalled) {
+      Status = gBS->UninstallMultipleProtocolInterfaces (
+          HostInst->MmcHandle,
+          &gEfiRpmbIoProtocolGuid,
+          &HostInst->RpmbIo,
+          NULL);
+
+      if (EFI_ERROR (Status)) {
+        LOG_ERROR (
+          "SoftReset(): Failed to uninstall EFI_RPMB_IO_PROTOCOL interface. %r",
+          Status);
+      } else {
+        HostInst->RpmbIoProtocolInstalled = FALSE;
+      }
+    }
+
+    if (HostInst->DevicePathProtocolInstalled) {
+      Status = gBS->UninstallMultipleProtocolInterfaces (
+          HostInst->MmcHandle,
+          &gEfiDevicePathProtocolGuid,
+          &HostInst->DevicePath,
+          NULL);
+
+      if (EFI_ERROR (Status)) {
+        LOG_ERROR (
+          "SoftReset(): Failed to uninstall EFI_DEVICE_PATH_PROTOCOL interface. %r",
+          Status);
+      } else {
+        HostInst->DevicePathProtocolInstalled = FALSE;
+      }
+    }
+  }
+
+  if (DevicePathText != NULL) {
+    FreePool (DevicePathText);
+  }
+
+  return Status;
+}
+
+VOID
+EFIAPI
+CheckCardsCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  SDHC_INSTANCE   *HostInst;
+  BOOLEAN         CardInserted;
+  BOOLEAN         CardEjected;
+  BOOLEAN         IsCardPresent;
+  EFI_STATUS      Status;
+
+  // For each registered SDHC instance
+  CurrentLink = gSdhcInstancePool.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &gSdhcInstancePool) {
+    HostInst = SDHC_INSTANCE_FROM_LINK (CurrentLink);
+    ASSERT (HostInst != NULL);
+
+    IsCardPresent = HostInst->HostExt->IsCardPresent (HostInst->HostExt);
+
+    // If card is present and not initialized or card no more present but was previously
+    // initialized, then reset the instance
+    //
+    // Present Initialized  Outcome
+    // T       T            No action
+    // T       F            Reset
+    // F       T            Reset
+    // F       F            No action
+    CardEjected = HostInst->BlockIo.Media->MediaPresent && !IsCardPresent;
+    if (CardEjected) {
+      LOG_INFO ("Card ejected from SDHC%d slot", HostInst->HostExt->SdhcId);
+    }
+
+    CardInserted = !HostInst->BlockIo.Media->MediaPresent && IsCardPresent;
+    if (CardInserted) {
+      LOG_INFO ("Card inserted into SDHC%d slot", HostInst->HostExt->SdhcId);
+    }
+
+    if (CardEjected || CardInserted) {
+      Status = SoftReset (HostInst);
+      if (EFI_ERROR (Status)) {
+        LOG_ERROR ("SoftReset() failed. %r", Status);
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+}
+
+BOOLEAN
+EFIAPI
+IsRpmbInstalledOnTheSystem (
+  VOID
+  )
+{
+  EFI_RPMB_IO_PROTOCOL  RpmbIo;
+  EFI_STATUS            Status;
+
+  Status = gBS->LocateProtocol (
+    &gEfiRpmbIoProtocolGuid,
+    NULL,
+    (VOID **) &RpmbIo);
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+EFI_STATUS
+EFIAPI
+UninstallAllProtocols (
+  IN SDHC_INSTANCE  *HostInst
+  )
+{
+  EFI_STATUS Status;
+
+  LOG_TRACE ("Uninstalling SDHC%d all protocols", HostInst->HostExt->SdhcId);
+
+  if (HostInst->BlockIoProtocolInstalled) {
+    Status =
+      gBS->UninstallMultipleProtocolInterfaces (
+        HostInst->MmcHandle,
+        &gEfiBlockIoProtocolGuid,
+        &HostInst->BlockIo,
+        NULL);
+
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "UninstallAllProtocols(): Failed to uninstall EFI_BLOCK_IO_PROTOCOL. "
+        "(Status = %r)",
+        Status);
+
+      return Status;
+    }
+
+    HostInst->BlockIoProtocolInstalled = FALSE;
+  }
+
+  if (HostInst->RpmbIoProtocolInstalled) {
+    Status = gBS->UninstallMultipleProtocolInterfaces (
+        HostInst->MmcHandle,
+        &gEfiRpmbIoProtocolGuid,
+        &HostInst->RpmbIo,
+        NULL);
+
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "UninstallAllProtocols(): Failed to uninstall EFI_RPMB_IO_PROTOCOL. "
+        "(Status = %r)",
+        Status);
+
+      return Status;
+    }
+
+    HostInst->RpmbIoProtocolInstalled = FALSE;
+  }
+
+  if (HostInst->DevicePathProtocolInstalled) {
+    Status = gBS->UninstallMultipleProtocolInterfaces (
+        HostInst->MmcHandle,
+        &gEfiDevicePathProtocolGuid,
+        &HostInst->DevicePath,
+        NULL);
+
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "UninstallAllProtocols(): Failed to uninstall EFI_DEVICE_PATH_PROTOCOL. "
+        "(Status = %r)",
+        Status);
+
+      return Status;
+    }
+
+    HostInst->DevicePathProtocolInstalled = FALSE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gSdMmcDriverBindingCallbacks = {
+  SdMmcDriverSupported,
+  SdMmcDriverStart,
+  SdMmcDriverStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+EFI_STATUS
+EFIAPI
+SdMmcDxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS Status;
+
+  LOG_TRACE ("SdMmcDxeInitialize");
+
+  InitializeSdhcPool ();
+
+  // Install driver model protocols.
+  Status = EfiLibInstallDriverBindingComponentName2 (
+    ImageHandle,
+    SystemTable,
+    &gSdMmcDriverBindingCallbacks,
+    ImageHandle,
+    NULL,
+    NULL);
+  ASSERT_EFI_ERROR (Status);
+
+  // Use a timer to detect if a card has been plugged in or removed.
+  Status = gBS->CreateEvent (
+    EVT_NOTIFY_SIGNAL | EVT_TIMER,
+    TPL_CALLBACK,
+    CheckCardsCallback,
+    NULL,
+    &gCheckCardsEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->SetTimer (
+    gCheckCardsEvent,
+    TimerPeriodic,
+    (UINT64) (10 * 1000 * SDMMC_CHECK_CARD_INTERVAL_MS)); // 200 ms
+  ASSERT_EFI_ERROR (Status);
+
+  gHpcTicksPerSeconds = GetPerformanceCounterProperties (NULL, NULL);
+  ASSERT (gHpcTicksPerSeconds != 0);
+
+  return Status;
+}
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h
new file mode 100644
index 000000000000..44aa75a665e5
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h
@@ -0,0 +1,529 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __SDMMC_H__
+#define __SDMMC_H__
+
+// Define with non-zero to collect IO statistics and dump it to the terminal.
+#define SDMMC_COLLECT_STATISTICS  0
+
+// Define with non-zero to benchmark IO on the first MmcReadBlocks call and
+// dump to the terminal.
+#define SDMMC_BENCHMARK_IO        0
+
+// Lower bound of 2s poll wait time (200 x 10ms)
+#define SDMMC_POLL_WAIT_COUNT     200
+#define SDMMC_POLL_WAIT_TIME_US   10000
+
+// The period at which to check the presence state of each card on each
+// registered SDHC instance.
+#define SDMMC_CHECK_CARD_INTERVAL_MS 1000
+
+// The number of recursive error recoveries to reach before considering the
+// failure fatal, and not attempting more error recoveries.
+#define SDMMC_ERROR_RECOVERY_ATTEMPT_THRESHOLD    3
+
+// Logging Macros
+
+#define LOG_TRACE_FMT_HELPER(FMT, ...)  "SdMmc[T]:" FMT "%a\n", __VA_ARGS__
+
+#define LOG_INFO_FMT_HELPER(FMT, ...)   "SdMmc[I]:" FMT "%a\n", __VA_ARGS__
+
+#define LOG_ERROR_FMT_HELPER(FMT, ...) \
+  "SdMmc[E]:" FMT " (%a: %a, %d)\n", __VA_ARGS__
+
+#define LOG_INFO(...) \
+  DEBUG((DEBUG_INIT, LOG_INFO_FMT_HELPER(__VA_ARGS__, "")))
+
+#define LOG_VANILLA_TRACE(...) \
+  DEBUG((DEBUG_VERBOSE | DEBUG_BLKIO, __VA_ARGS__))
+
+#define LOG_TRACE(...) \
+  DEBUG((DEBUG_VERBOSE | DEBUG_BLKIO, LOG_TRACE_FMT_HELPER(__VA_ARGS__, "")))
+
+#define LOG_ERROR(...) \
+  DEBUG((DEBUG_ERROR, LOG_ERROR_FMT_HELPER(__VA_ARGS__, __FUNCTION__, __FILE__, __LINE__)))
+
+#define LOG_ASSERT(TXT) ASSERT(!"SdMmc[A]: " TXT "\n")
+
+#ifndef C_ASSERT
+#define C_ASSERT(e) _Static_assert(e, #e)
+#endif // C_ASSERT
+
+// Perform Integer division DIVIDEND/DIVISOR and return the result rounded up
+// or down to the nearest integer, where 3.5 and 3.75 are near 4, while 3.25
+// is near 3.
+#define INT_DIV_ROUND(DIVIDEND, DIVISOR) \
+  (((DIVIDEND) + ((DIVISOR) / 2)) / (DIVISOR))
+
+typedef struct {
+  UINT16  NumBlocks;
+  UINT16  Count;
+  UINT32  TotalTransferTimeUs;
+} IoReadStatsEntry;
+
+// Device Path Definitions
+//
+// eMMC and SD device paths got introduced in UEFI 2.6
+// Remove definitions below once code base migrates to UEFI 2.6
+
+#ifndef MSG_SD_DP
+// SD (Secure Digital) Device Path SubType.
+#define MSG_SD_DP   0x1A
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  UINT8                     SlotNumber;
+} SD_DEVICE_PATH;
+#endif // MSG_SD_DP
+
+#ifndef MSG_EMMC_DP
+// EMMC (Embedded MMC) Device Path SubType.
+#define MSG_EMMC_DP   0x1D
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  UINT8                     SlotNumber;
+} EMMC_DEVICE_PATH;
+#endif // MSG_EMMC_DP
+
+typedef struct {
+  VENDOR_DEVICE_PATH  SdhcNode;
+  UINT32              SdhcId;
+  union {
+    EMMC_DEVICE_PATH  MMC;
+    SD_DEVICE_PATH    SD;
+  } SlotNode;
+  EFI_DEVICE_PATH     EndNode;
+} SDHC_DEVICE_PATH;
+
+// GUID {AAFB8DAA-7340-43AC-8D49-0CCE14812489}
+#define SDHC_DEVICE_PATH_GUID \
+  { 0xaafb8daa, 0x7340, 0x43ac, { 0x8d, 0x49, 0xc, 0xce, 0x14, 0x81, 0x24, 0x89 } }
+
+// Size of SDHC node including the Sdhc ID field
+#define SDHC_NODE_PATH_LENGTH (sizeof(VENDOR_DEVICE_PATH) + sizeof(UINT32))
+
+typedef struct {
+  UINTN                         Signature;
+  LIST_ENTRY                    Link;
+  UINT32                        InstanceId;
+  EFI_HANDLE                    MmcHandle;
+  BOOLEAN                       SlotInitialized;
+  BOOLEAN                       Disabled;
+  SDHC_DEVICE_PATH              DevicePath;
+  EFI_BLOCK_IO_PROTOCOL         BlockIo;
+  EFI_RPMB_IO_PROTOCOL          RpmbIo;
+  EFI_SDHC_PROTOCOL             *HostExt;
+  SDHC_CAPABILITIES             HostCapabilities;
+  BOOLEAN                       DevicePathProtocolInstalled;
+  BOOLEAN                       BlockIoProtocolInstalled;
+  BOOLEAN                       RpmbIoProtocolInstalled;
+  MMC_EXT_CSD_PARTITION_ACCESS  CurrentMmcPartition;
+  CARD_INFO                     CardInfo;
+  UINT32                        BlockBuffer[SD_BLOCK_WORD_COUNT];
+  UINT32                        CmdResponse[4];
+  CONST SD_COMMAND              *PreLastSuccessfulCmd;
+  CONST SD_COMMAND              *LastSuccessfulCmd;
+  UINT32                        ErrorRecoveryAttemptCount;
+#ifdef MMC_COLLECT_STATISTICS
+  IoReadStatsEntry              IoReadStats[1024];
+  UINT32                        IoReadStatsNumEntries;
+#endif // COLLECT_IO_STATISTICS
+} SDHC_INSTANCE;
+
+#define SDHC_INSTANCE_SIGNATURE   SIGNATURE_32('s', 'd', 'h', 'c')
+#define SDHC_INSTANCE_FROM_BLOCK_IO_THIS(a) \
+  CR(a, SDHC_INSTANCE, BlockIo, SDHC_INSTANCE_SIGNATURE)
+#define SDHC_INSTANCE_FROM_LINK(a) \
+  CR(a, SDHC_INSTANCE, Link, SDHC_INSTANCE_SIGNATURE)
+#define SDHC_INSTANCE_FROM_RPMB_IO_THIS(a) \
+  CR (a, SDHC_INSTANCE, RpmbIo, SDHC_INSTANCE_SIGNATURE)
+
+// The ARM high-performance counter frequency
+extern UINT64 gHpcTicksPerSeconds;
+
+// EFI_BLOCK_IO Protocol Callbacks
+
+/**
+  Reset the block device.
+
+  This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
+  It resets the block device hardware.
+  ExtendedVerification is ignored in this implementation.
+
+  @param  This                   Indicates a pointer to the calling context.
+  @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive
+                                 verification operation of the device during reset.
+
+  @retval EFI_SUCCESS            The block device was reset.
+  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoReset (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN BOOLEAN                ExtendedVerification
+  );
+
+/**
+  Reads the requested number of blocks from the device.
+
+  This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
+  It reads the requested number of blocks from the device.
+  All the blocks are read, or an error is returned.
+
+  @param  This                   Indicates a pointer to the calling context.
+  @param  MediaId                The media ID that the read request is for.
+  @param  Lba                    The starting logical block address to read from on the device.
+  @param  BufferSize             The size of the Buffer in bytes.
+                                 This must be a multiple of the intrinsic block size of the device.
+  @param  Buffer                 A pointer to the destination buffer for the data. The caller is
+                                 responsible for either having implicit or explicit ownership of the buffer.
+
+  @retval EFI_SUCCESS            The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the read operation.
+  @retval EFI_NO_MEDIA           There is no media in the device.
+  @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
+  @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic block size of the device.
+  @retval EFI_INVALID_PARAMETER  The read request contains LBAs that are not valid,
+                                 or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoReadBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN UINT32                 MediaId,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSize,
+  OUT VOID                  *Buffer
+  );
+
+/**
+  Writes a specified number of blocks to the device.
+
+  This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
+  It writes a specified number of blocks to the device.
+  All blocks are written, or an error is returned.
+
+  @param  This                   Indicates a pointer to the calling context.
+  @param  MediaId                The media ID that the write request is for.
+  @param  Lba                    The starting logical block address to be written.
+  @param  BufferSize             The size of the Buffer in bytes.
+                                 This must be a multiple of the intrinsic block size of the device.
+  @param  Buffer                 Pointer to the source buffer for the data.
+
+  @retval EFI_SUCCESS            The data were written correctly to the device.
+  @retval EFI_WRITE_PROTECTED    The device cannot be written to.
+  @retval EFI_NO_MEDIA           There is no media in the device.
+  @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
+  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the write operation.
+  @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic
+                                 block size of the device.
+  @retval EFI_INVALID_PARAMETER  The write request contains LBAs that are not valid,
+                                 or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoWriteBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This,
+  IN UINT32                 MediaId,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSize,
+  IN VOID                   *Buffer
+  );
+
+/**
+  Flushes all modified data to a physical block device.
+
+  @param  This                   Indicates a pointer to the calling context.
+
+  @retval EFI_SUCCESS            All outstanding data were written correctly to the device.
+  @retval EFI_DEVICE_ERROR       The device reported an error while attempting to write data.
+  @retval EFI_NO_MEDIA           There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL *This
+  );
+
+// EFI_RPMPB_IO Protocol Callbacks
+
+/** Authentication key programming request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ProgrammingRequest A data packet describing a key programming request.
+  @param[out] ResultResponse A caller allocated data packet which will receive the
+  key programming result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during key programming any other eMMC internal failure is reported
+  in the Result field of the returned response data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoProgramKey (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *Request,
+  OUT EFI_RPMB_DATA_PACKET  *ResultResponse
+  );
+
+/** Reading of the write counter value request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ReadRequest A data packet describing a read counter value request.
+  @param[out] ReadResponse A caller allocated data packet which will receive
+  the counter value read response. If counter has expired bit 7 is set to 1 in
+  returned Result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during counter read or any other eMMC internal failure is reported
+  in the Result field of the returned response data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoReadCounter (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ReadRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ReadResponse
+  );
+
+/** Authenticated data write request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] WriteRequest A sequence of data packets describing data write
+  requests and holds the data to be written.
+  @param[out] ResultResponse A caller allocated data packet which will receive
+  the data write programming result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during data programming or any other eMMC internal failure is reported
+  in the Result field of the returned data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoAuthenticatedWrite (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_BUFFER   *WriteRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ResultResponse
+  );
+
+/** Authenticated data read request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ReadRequest A data packet that describes a data read request.
+  @param[out] ReadResponse A caller allocated data packets which will receive
+  the data read.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during data fetch from the eMMC or any other eMMC internal failure
+  is reported in the Result field of the returned data packet.
+**/
+EFI_STATUS
+EFIAPI
+RpmbIoAuthenticatedRead (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ReadRequest,
+  OUT EFI_RPMB_DATA_BUFFER  *ReadResponse
+  );
+
+// Helper Functions
+
+EFI_STATUS
+EFIAPI
+SoftReset (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+// Debugging Helpers
+
+VOID
+PrintCsd (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+VOID
+PrintCid (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+VOID
+PrintCardStatus (
+  IN SDHC_INSTANCE  *HostInst,
+  IN CARD_STATUS    CardStatus
+  );
+
+VOID
+GetAndPrintCardStatus (
+  IN SDHC_INSTANCE  *HostInst
+  );
+
+// Inlined Helper Functions
+
+__inline__
+static
+CONST CHAR8*
+MmcPartitionAccessToString (
+  IN MMC_EXT_CSD_PARTITION_ACCESS   Partition
+  )
+{
+  switch (Partition) {
+  case MmcExtCsdPartitionAccessUserArea:
+    return "UserArea";
+  case MmcExtCsdPartitionAccessBootPartition1:
+    return "Boot1";
+  case MmcExtCsdPartitionAccessBootPartition2:
+    return "Boot2";
+  case MmcExtCsdPartitionAccessRpmb:
+    return "RPMB";
+  case MmcExtCsdPartitionAccessGpp1:
+    return "GeneralPurpose1";
+  case MmcExtCsdPartitionAccessGpp2:
+    return "GeneralPurpose2";
+  case MmcExtCsdPartitionAccessGpp3:
+    return "GeneralPurpose3";
+  case MmcExtCsdPartitionAccessGpp4:
+    return "GeneralPurpose4";
+  default:
+    return "Unknown";
+  }
+}
+
+__inline__
+static
+CONST CHAR8*
+CardStateToString (
+  IN CARD_STATE   State
+  )
+{
+  switch (State) {
+  case CardStateIdle:
+    return "Idle";
+  case CardStateReady:
+    return "Ready";
+  case CardStateIdent:
+    return "Ident";
+  case CardStateStdby:
+    return "Stdby";
+  case CardStateTran:
+    return "Tran";
+  case CardStateData:
+    return "Data";
+  case CardStateRcv:
+    return "Rcv";
+  case CardStatePrg:
+    return "Prg";
+  case CardStateDis:
+    return "Dis";
+  case CardStateBtst:
+    return "Btst";
+  case CardStateSlp:
+    return "Slp";
+  default:
+    return "Reserved";
+  }
+}
+
+__inline__
+static
+BOOLEAN
+IsCardStatusError (
+  IN SDHC_INSTANCE  *HostInst,
+  IN CARD_STATUS    CardStatus
+  )
+{
+  ASSERT (HostInst != NULL);
+
+  switch (HostInst->CardInfo.CardFunction) {
+  case CardFunctionSd:
+    return CardStatus.AsUint32 & SD_CARD_STATUS_ERROR_MASK;
+  case CardFunctionMmc:
+    return CardStatus.AsUint32 & MMC_CARD_STATUS_ERROR_MASK;
+  default:
+    ASSERT (FALSE);
+    return FALSE;
+  }
+}
+
+__inline__
+static
+BOOLEAN
+CmdsAreEqual (
+  IN CONST SD_COMMAND   *Left,
+  IN CONST SD_COMMAND   *Right
+  )
+{
+  ASSERT (Left != NULL);
+  ASSERT (Right != NULL);
+
+  if (Left != Right) {
+    return (Left->Class == Right->Class) &&
+      (Left->Index == Right->Index) &&
+      (Left->ResponseType == Right->ResponseType) &&
+      (Left->TransferDirection == Right->TransferDirection) &&
+      (Left->TransferType == Right->TransferType) &&
+      (Left->Type == Right->Type);
+  }
+
+  return TRUE;
+}
+
+// Timing Helpers
+
+/** Gets the current high-performance counter tick count.
+
+  The returned tick count is considered as a time stamp and can used later in
+  elapsed time calculations.
+
+  @retval Current high-performance counter tick count.
+**/
+__inline__
+static
+UINT64
+HpcTimerStart (
+  VOID
+  )
+{
+  return GetPerformanceCounter ();
+}
+
+/** Calculates the elapsed milliseconds since a specific timer time stamp.
+
+  @param[in] TimerStartTimestamp The high-performance counter tick count to use
+  as the starting point in elapsed time calculation.
+
+  @retval The milliseconds elapsed.
+**/
+__inline__
+static
+UINT64
+HpcTimerElapsedMilliseconds (
+  IN UINT64   TimerStartTimestamp
+  )
+{
+  return (((GetPerformanceCounter () - TimerStartTimestamp) * 1000UL) /
+          gHpcTicksPerSeconds);
+}
+
+#endif // __SDMMC_H__
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
new file mode 100644
index 000000000000..59dbb2662e8c
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
@@ -0,0 +1,49 @@
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = SdMmcDxe
+  FILE_GUID                      = 16738C4A-8044-4DD8-B68E-58A53CEFF5D9
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SdMmcDxeInitialize
+
+[Sources.common]
+  BlockIo.c
+  Debug.c
+  RpmbIo.c
+  Protocol.c
+  SdMmc.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/Microsoft/MsPkg.dec
+  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  TimerLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiDevicePathProtocolGuid
+  gEfiDiskIoProtocolGuid
+  gEfiRpmbIoProtocolGuid
+  gEfiSdhcProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h
new file mode 100644
index 000000000000..fbfa49d8d3a1
--- /dev/null
+++ b/Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h
@@ -0,0 +1,505 @@
+/** @file
+*
+*  Copyright (c) Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __SDMMCHW_H__
+#define __SDMMCHW_H__
+
+#pragma pack(1)
+
+#define SD_BLOCK_LENGTH_BYTES               512
+#define SD_BLOCK_WORD_COUNT                 (SD_BLOCK_LENGTH_BYTES / sizeof (UINT32))
+#define SD_IDENT_MODE_CLOCK_FREQ_HZ         400000    // 400 KHz
+#define MMC_HIGH_SPEED_MODE_CLOCK_FREQ_HZ   52000000  // 52 MHz
+
+typedef enum {
+  CardSpeedModeUndefined = 0,
+  CardSpeedModeNormalSpeed,
+  CardSpeedModeHighSpeed
+} CARD_SPEED_MODE;
+
+typedef enum {
+  CardFunctionUnknown = 0,
+  CardFunctionSd,
+  CardFunctionSdio,
+  CardFunctionComboSdSdio,
+  CardFunctionMmc
+} CARD_FUNCTION;
+
+typedef enum {
+  CardStateIdle = 0,
+  CardStateReady,
+  CardStateIdent,
+  CardStateStdby,
+  CardStateTran,
+  CardStateData,
+  CardStateRcv,
+  CardStatePrg,
+  CardStateDis,
+  CardStateBtst,
+  CardStateSlp
+} CARD_STATE;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 RESERVED_1 : 2;            // [1:0]
+    UINT32 RESERVED_2 : 1;            // [2]
+    UINT32 AKE_SEQ_ERROR : 1;         // [3] SD
+    UINT32 RESERVED_3 : 1;            // [4]
+    UINT32 APP_CMD : 1;               // [5]
+    UINT32 URGENT_BKOPS : 1;          // [6] MMC
+    UINT32 SWITCH_ERROR : 1;          // [7] MMC
+    UINT32 READY_FOR_DATA : 1;        // [8]
+    UINT32 CURRENT_STATE : 4;         // [12:9]
+    UINT32 ERASE_RESET : 1;           // [13]
+    UINT32 RESERVED_4 : 1;            // [14]
+    UINT32 WP_ERASE_SKIP : 1;         // [15]
+    UINT32 CID_CSD_OVERWRITE : 1;     // [16]
+    UINT32 OVERRUN : 1;               // [17] MMC
+    UINT32 UNDERRUN : 1;              // [18] MMC
+    UINT32 ERROR : 1;                 // [19]
+    UINT32 CC_ERROR : 1;              // [20]
+    UINT32 CARD_ECC_FAILED : 1;       // [21]
+    UINT32 ILLEGAL_COMMAND : 1;       // [22]
+    UINT32 COM_CRC_ERROR : 1;         // [23]
+    UINT32 LOCK_UNLOCK_FAILED : 1;    // [24]
+    UINT32 CARD_IS_LOCKED : 1;        // [25]
+    UINT32 WP_VIOLATION : 1;          // [26]
+    UINT32 ERASE_PARAM : 1;           // [27]
+    UINT32 ERASE_SEQ_ERROR : 1;       // [28]
+    UINT32 BLOCK_LEN_ERROR : 1;       // [29]
+    UINT32 ADDRESS_MISALIGN : 1;      // [30]
+    UINT32 ADDRESS_OUT_OF_RANGE : 1;  // [31]
+  } Fields;
+} CARD_STATUS;
+
+#define MMC_CARD_STATUS_ERROR_MASK \
+          (BIT7 | BIT13 | BIT15 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | \
+          BIT21 | BIT22 | BIT23 | BIT24 | BIT26 | BIT27 | BIT28 | BIT29 | \
+          BIT30 | BIT31)
+
+#define SD_CARD_STATUS_ERROR_MASK \
+          (BIT3 | BIT13 | BIT15 | BIT16 | BIT19 | BIT20 | \
+          BIT21 | BIT22 | BIT23 | BIT24 | BIT26 | BIT27 | BIT28 | BIT29 | \
+          BIT30 | BIT31)
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CheckPattern : 8;
+    UINT32 VoltageSupplied : 4;
+    UINT32 RESERVED_1 : 16;
+    UINT32 CommandIndex : 6;
+  } Fields;
+} SEND_IF_COND_ARG;
+
+typedef SEND_IF_COND_ARG SEND_IF_COND_CMD_RESPONSE;
+
+// definition for VoltageAccepted in SD_CMD8_STATUS
+
+#define SD_CMD8_VOLTAGE_27_36   0x01
+#define SD_CMD8_VOLTAGE_LOW     0x02
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 VoltageWindow : 24;  // [23:0] Maps to OCR[0:23]
+    UINT32 S18R : 1;            // [24] Switching to 1.8V Request
+                                // 0b: Use Current signal voltage, 1b: Switch to 1.8V signal voltage
+
+    UINT32 RESERVED_1 : 3;      // [27:25]
+    UINT32 XPC : 1;             // SDXC Power Control [28] 0b: Power Saving, 1b: Max Performance
+    UINT32 RESERVED_2 : 1;      // [29]
+    UINT32 HCS : 1;             // Host Capacity Support [30] 0b: SDSC, 1b: SDHC or SDXC
+    UINT32 RESERVED_3 : 1;      // [31]
+  } Fields;
+} SD_SEND_OP_COND_ARG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 VoltageWindow : 24;  // [23:0] Voltage profile
+    UINT32 RESERVED_1 : 5;      // Reserved
+    UINT32 AccessMode : 2;      // 00b (byte mode), 10b (sector mode)
+    UINT32 PowerUp : 1;         // This bit is set to LOW if the card has not finished the power up routine
+  } Fields;
+} SD_OCR;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 VoltageWindow : 24;  // [23:0] Voltage profile
+    UINT32 S18A : 1;            // [24] Switching to 1.8V Accepted
+    UINT32 RESERVED_1 : 5;      // Reserved [29:25]
+    UINT32 CCS : 1;             // Card Capacity Status [30]
+    UINT32 PowerUp : 1;         // This bit is set to LOW if the card has not finished the power up routine [31]
+  } Fields;
+} SD_OCR_EX;
+
+typedef struct {
+  UINT16 MDT : 12;        // Manufacturing date [19:8]
+  UINT16 RESERVED_1 : 4;  // Reserved [23:20]
+  UINT32 PSN;             // Product serial number [55:24]
+  UINT8 PRV;              // Product revision [63:56]
+  UINT8 PNM[5];           // Product name [64:103]
+  UINT16 OID;             // OEM/Application ID [119:104]
+  UINT8 MID;              // Manufacturer ID [127:120]
+} SD_CID;
+
+typedef struct {
+  UINT16 MDT : 8;         // Manufacturing date [15:8]
+  UINT32 PSN;             // Product serial number [47:16]
+  UINT8 PRV;              // Product revision [55:48]
+  UINT8 PNM[6];           // Product name [103:56]
+  UINT8 OID;              // OEM/Application ID [111:104]
+  UINT8 CBX : 2;          // Card/BGA [113:112]
+  UINT8 RESERVED_1 : 6;   // [119:114]
+  UINT8 MID;              // Manufacturer ID [127:120]
+} MMC_CID;
+
+typedef struct {
+  UINT8 RESERVED_1 : 2;           // Reserved [9:8]
+  UINT8 FILE_FORMAT : 2;          // File format [11:10]
+  UINT8 TMP_WRITE_PROTECT : 1;    // Temporary write protection [12:12]
+  UINT8 PERM_WRITE_PROTECT : 1;   // Permanent write protection [13:13]
+  UINT8 COPY : 1;                 // Copy flag (OTP) [14:14]
+  UINT8 FILE_FORMAT_GRP : 1;      // File format group [15:15]
+  UINT16 RESERVED_2 : 5;          // Reserved [20:16]
+  UINT16 WRITE_BL_PARTIAL : 1;    // Partial blocks for write allowed [21:21]
+  UINT16 WRITE_BL_LEN : 4;        // Max. write data block length [25:22]
+  UINT16 R2W_FACTOR : 3;          // Write speed factor [28:26]
+  UINT16 RESERVED_3 : 2;          // Reserved [30:29]
+  UINT16 WP_GRP_ENABLE : 1;       // Write protect group enable [31:31]
+  UINT32 WP_GRP_SIZE : 7;         // Write protect group size [38:32]
+  UINT32 SECTOR_SIZE : 7;         // Erase sector size [45:39]
+  UINT32 ERASE_BLK_EN : 1;        // Erase single block enable [46:46]
+  UINT32 C_SIZE_MULT : 3;         // Device size multiplier [49:47]
+  UINT32 VDD_W_CURR_MAX : 3;      // Max. write current @ VDD max [52:50]
+  UINT32 VDD_W_CURR_MIN : 3;      // Max. write current @ VDD min [55:53]
+  UINT32 VDD_R_CURR_MAX : 3;      // Max. read current @ VDD max [58:56]
+  UINT32 VDD_R_CURR_MIN : 3;      // Max. read current @ VDD min [61:59]
+  UINT32 C_SIZELow2 : 2;          // Device size [63:62]
+  UINT32 C_SIZEHigh10 : 10;       // Device size [73:64]
+  UINT32 RESERVED_4 : 2;          // Reserved [75:74]
+  UINT32 DSR_IMP : 1;             // DSR implemented [76:76]
+  UINT32 READ_BLK_MISALIGN : 1;   // Read block misalignment [77:77]
+  UINT32 WRITE_BLK_MISALIGN : 1;  // Write block misalignment [78:78]
+  UINT32 READ_BL_PARTIAL : 1;     // Partial blocks for read allowed [79:79]
+  UINT32 READ_BL_LEN : 4;         // Max. read data block length [83:80]
+  UINT32 CCC : 12;                // Card command classes [95:84]
+  UINT8 TRAN_SPEED;               // Max. bus clock frequency [103:96]
+  UINT8 NSAC;                     // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+  UINT8 TAAC;                     // Data read access-time 1 [119:112]
+  UINT8 RESERVED_5 : 6;           // Reserved [125:120]
+  UINT8 CSD_STRUCTURE : 2;        // CSD structure [127:126]
+} SD_CSD;
+
+typedef struct {
+  UINT8 RESERVED_1 : 2;           // Reserved [9:8]
+  UINT8 FILE_FORMAT : 2;          // File format [11:10]
+  UINT8 TMP_WRITE_PROTECT : 1;    // Temporary write protection [12:12]
+  UINT8 PERM_WRITE_PROTECT : 1;   // Permanent write protection [13:13]
+  UINT8 COPY : 1;                 // Copy flag (OTP) [14:14]
+  UINT8 FILE_FORMAT_GRP : 1;      // File format group [15:15]
+  UINT16 RESERVED_2 : 5;          // Reserved [20:16]
+  UINT16 WRITE_BL_PARTIAL : 1;    // Partial blocks for write allowed [21:21]
+  UINT16 WRITE_BL_LEN : 4;        // Max. write data block length [25:22]
+  UINT16 R2W_FACTOR : 3;          // Write speed factor [28:26]
+  UINT16 RESERVED_3 : 2;          // Reserved [30:29]
+  UINT16 WP_GRP_ENABLE : 1;       // Write protect group enable [31:31]
+  UINT16 WP_GRP_SIZE : 7;         // Write protect group size [38:32]
+  UINT16 SECTOR_SIZE : 7;         // Erase sector size [45:39]
+  UINT16 ERASE_BLK_EN : 1;        // Erase single block enable [46:46]
+  UINT16 RESERVED_4 : 1;          // Reserved [47:47]
+  UINT32 C_SIZE : 22;             // Device size [63:62]
+  UINT32 RESERVED_5 : 6;          // Reserved [75:74]
+  UINT32 DSR_IMP : 1;             // DSR implemented [76:76]
+  UINT32 READ_BLK_MISALIGN : 1;   // Read block misalignment [77:77]
+  UINT32 WRITE_BLK_MISALIGN : 1;  // Write block misalignment [78:78]
+  UINT32 READ_BL_PARTIAL : 1;     // Partial blocks for read allowed [79:79]
+  UINT16 READ_BL_LEN : 4;         // Max. read data block length [83:80]
+  UINT16 CCC : 12;                // Card command classes [95:84]
+  UINT8 TRAN_SPEED;               // Max. bus clock frequency [103:96]
+  UINT8 NSAC;                     // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+  UINT8 TAAC;                     // Data read access-time 1 [119:112]
+  UINT8 RESERVED_6 : 6;           // Reserved [125:120]
+  UINT8 CSD_STRUCTURE : 2;        // CSD structure [127:126]
+} SD_CSD_2;
+
+typedef struct {
+  UINT8 ECC : 2;                  // ECC code [9:8]
+  UINT8 FILE_FORMAT : 2;          // File format [11:10]
+  UINT8 TMP_WRITE_PROTECT : 1;    // Temporary write protection [12:12]
+  UINT8 PERM_WRITE_PROTECT : 1;   // Permanent write protection [13:13]
+  UINT8 COPY : 1;                 // Copy flag (OTP) [14:14]
+  UINT8 FILE_FORMAT_GRP : 1;      // File format group [15:15]
+  UINT16 CONTENT_PROT_APP : 1;    // Content protection application [16:16]
+  UINT16 RESERVED_1 : 4;          // Reserved [20:17]
+  UINT16 WRITE_BL_PARTIAL : 1;    // Partial blocks for write allowed [21:21]
+  UINT16 WRITE_BL_LEN : 4;        // Max. write data block length [25:22]
+  UINT16 R2W_FACTOR : 3;          // Write speed factor [28:26]
+  UINT16 DEFAULT_ECC : 2;         // Manufacturer default ECC [30:29]
+  UINT16 WP_GRP_ENABLE : 1;       // Write protect group enable [31:31]
+  UINT32 WP_GRP_SIZE : 5;         // Write protect group size [36:32]
+  UINT32 ERASE_GRP_MULT : 5;      // Erase group size multiplier [41:37]
+  UINT32 ERASE_GRP_SIZE : 5;      // Erase sector size [46:42]
+  UINT32 C_SIZE_MULT : 3;         // Device size multiplier [49:47]
+  UINT32 VDD_W_CURR_MAX : 3;      // Max. write current @ VDD max [52:50]
+  UINT32 VDD_W_CURR_MIN : 3;      // Max. write current @ VDD min [55:53]
+  UINT32 VDD_R_CURR_MAX : 3;      // Max. read current @ VDD max [58:56]
+  UINT32 VDD_R_CURR_MIN : 3;      // Max. read current @ VDD min [61:59]
+  UINT32 C_SIZELow2 : 2;          // Device size [63:62]
+  UINT32 C_SIZEHigh10 : 10;       // Device size [73:64]
+  UINT32 RESERVED_4 : 2;          // Reserved [75:74]
+  UINT32 DSR_IMP : 1;             // DSR implemented [76:76]
+  UINT32 READ_BLK_MISALIGN : 1;   // Read block misalignment [77:77]
+  UINT32 WRITE_BLK_MISALIGN : 1;  // Write block misalignment [78:78]
+  UINT32 READ_BL_PARTIAL : 1;     // Partial blocks for read allowed [79:79]
+  UINT32 READ_BL_LEN : 4;         // Max. read data block length [83:80]
+  UINT32 CCC : 12;                // Card command classes [95:84]
+  UINT8 TRAN_SPEED;               // Max. bus clock frequency [103:96]
+  UINT8 NSAC;                     // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+  UINT8 TAAC;                     // Data read access-time 1 [119:112]
+  UINT8 RESERVED_5 : 2;           // Reserved [121:120]
+  UINT8 SPEC_VERS : 4;            // System specification version [125:122]
+  UINT8 CSD_STRUCTURE : 2;        // CSD structure [127:126]
+} MMC_CSD;
+
+// We support spec version 4.X and higher
+// If CSD.SPEC_VERS indicates a version 4.0 or higher, the card is a high speed card and supports
+// SWITCH and SEND_EXT_CSD commands. Otherwise the card is an old MMC card.
+#define MMC_MIN_SUPPORTED_SPEC_VERS     4
+
+typedef struct {
+
+  // Host modifiable modes
+
+  UINT8 Reserved26[134];
+  UINT8 BadBlockManagement;
+  UINT8 Reserved25;
+  UINT32 EnhancedUserDataStartAddress;
+  UINT8 EnhancedUserDataAreaSize[3];
+  UINT8 GpPartSizeMult[12];
+  UINT8 PartitioningSetting;
+  UINT8 PartitionsAttribute;
+  UINT8 MaxEnhancedAreaSize[3];
+  UINT8 PartitioningSupport;
+  UINT8 Reserved24;
+  UINT8 HwResetFunc;
+  UINT8 Reserved23[5];
+  UINT8 RpmbSizeMult;
+  UINT8 FwConfig;
+  UINT8 Reserved22;
+  UINT8 UserWriteProt;
+  UINT8 Reserved21;
+  UINT8 BootWriteProt;
+  UINT8 Reserved20;
+  UINT8 EraseGroupDef;
+  UINT8 Reserved19;
+  UINT8 BootBusWidth;
+  UINT8 BootConfigProt;
+  UINT8 PartitionConfig;
+  UINT8 Reserved18;
+  UINT8 ErasedMemContent;
+  UINT8 Reserved17;
+  UINT8 BusWidth;
+  UINT8 Reserved16;
+  UINT8 HighSpeedTiming;
+  UINT8 Reserved15;
+  UINT8 PowerClass;
+  UINT8 Reserved14;
+  UINT8 CmdSetRevision;
+  UINT8 Reserved13;
+  UINT8 CmdSet;
+
+  // Non-modifiable properties
+
+  UINT8 ExtendedCsdRevision;
+  UINT8 Reserved12;
+  UINT8 CsdStructureVersion;
+  UINT8 Reserved11;
+  UINT8 CardType;
+  UINT8 Reserved10[3];
+  UINT8 PowerClass52Mhz195V;
+  UINT8 PowerClass26Mhz195V;
+  UINT8 PowerClass52Mhz36V;
+  UINT8 PowerClass26Mhz36V;
+  UINT8 Reserved9;
+  UINT8 MinReadPerf4bit26Mhz;
+  UINT8 MinWritePerf4bit26Mhz;
+  UINT8 MinReadPerf8bit26Mhz;
+  UINT8 MinWritePerf8bit26Mhz;
+  UINT8 MinReadPerf8bit52Mhz;
+  UINT8 MinWritePerf8bit52Mhz;
+  UINT8 Reserved8;
+  UINT32 SectorCount;
+  UINT8 Reserved7;
+  UINT8 SleepAwakeTimeout;
+  UINT8 Reserved6;
+  UINT8 SleepCurrentVccq;
+  UINT8 SleepCurrentVcc;
+  UINT8 HighCapacityWriteProtectSize;
+  UINT8 ReliableWriteSectorCount;
+  UINT8 HighCapacityEraseTimeout;
+  UINT8 HighCapacityEraseSize;
+  UINT8 AccessSize;
+  UINT8 BootPartitionSize;
+  UINT8 Reserved5;
+  UINT8 BootInfo;
+  UINT8 SecureTrimMultiplier;
+  UINT8 SecureEraseMultiplier;
+  UINT8 SecureFeatureSupport;
+  UINT8 TrimMultiplier;
+  UINT8 Reserved4;
+  UINT8 MinReadPerf8bit52MhzDdr;
+  UINT8 MinWritePerf8bit52MhzDdr;
+  UINT16 Reserved3;
+  UINT8 PowerClass52MhzDdr36V;
+  UINT8 PowerClass52MhzDdr195V;
+  UINT8 Reserved2;
+  UINT8 InitTimeoutAfterPartitioning;
+  UINT8 Reserved1[262];
+  UINT8 SupportedCmdSets;
+  UINT8 Reserved[7];
+} MMC_EXT_CSD;
+
+typedef enum {
+  MmcExtCsdCardTypeNormalSpeed = 0x01,
+  MmcExtCsdCardTypeHighSpeed = 0x02,
+  MmcExtCsdCardTypeDdr1v8 = 0x04,
+  MmcExtCsdCardTypeDdr1v2 = 0x08
+} MmcExtCsdCardType;
+
+typedef enum {
+  MmcExtCsdBusWidth1Bit = 0,
+  MmcExtCsdBusWidth4Bit = 1,
+  MmcExtCsdBusWidth8Bit = 2
+} MmcExtCsdBusWidth;
+
+typedef enum {
+  MmcExtCsdPartitionAccessUserArea,
+  MmcExtCsdPartitionAccessBootPartition1,
+  MmcExtCsdPartitionAccessBootPartition2,
+  MmcExtCsdPartitionAccessRpmb,
+  MmcExtCsdPartitionAccessGpp1,
+  MmcExtCsdPartitionAccessGpp2,
+  MmcExtCsdPartitionAccessGpp3,
+  MmcExtCsdPartitionAccessGpp4,
+} MMC_EXT_CSD_PARTITION_ACCESS;
+
+typedef enum {
+  MmcExtCsdBootPartitionEnableNotBootEnabled,
+  MmcExtCsdBootPartitionBootPartition1BootEnabled,
+  MmcExtCsdBootPartitionBootPartition2BootEnabled,
+  MmcExtCsdBootPartitionUserAreaBootEnabled = 7,
+} MMC_EXT_CSD_BOOT_PARTITION_ENABLE;
+
+typedef union {
+  UINT8 AsUint8;
+  struct {
+    UINT8 PARTITION_ACCESS : 3;       // [2:0]
+    UINT8 BOOT_PARTITION_ENABLE : 3;  // [5:3]
+    UINT8 BOOT_ACK : 1;               // [6]
+    UINT8 RESERVED_1 : 1;             // [7]
+  } Fields;
+} MMC_EXT_CSD_PARTITION_CONFIG;
+
+typedef enum {
+  MmcExtCsdBitIndexPartitionConfig = 179,
+  MmcExtCsdBitIndexBusWidth = 183,
+  MmcExtCsdBitIndexHsTiming = 185
+} MMC_EXT_CSD_BIT_INDEX;
+
+typedef enum {
+  MmcSwitchCmdAccessTypeCommandSet,
+  MmcSwitchCmdAccessTypeSetBits,
+  MmcSwitchCmdAccessTypeClearBits,
+  MmcSwitchCmdAccessTypeWriteByte
+} MMC_SWITCH_CMD_ACCESS_TYPE;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CmdSet : 3;      // [2:0]
+    UINT32 RESERVED_1 : 5;  // Set to 0 [7:3]
+    UINT32 Value : 8;       // [15:8]
+    UINT32 Index : 8;       // [23:16]
+    UINT32 Access : 2;      // A value from MMC_SWITCH_CMD_ACCESS_TYPE [25:24]
+    UINT32 RESERVED_2 : 6;  // Set to 0 [31:26]
+  } Fields;
+} MMC_SWITCH_CMD_ARG;
+
+// Bits [3:0] code the current consumption for the 4 bit bus configuration
+#define MMC_EXT_CSD_POWER_CLASS_4BIT(X)         ((X) & 0xF)
+
+// Bits [7:4] code the current consumption for the 8 bit bus configuration
+#define MMC_EXT_CSD_POWER_CLASS_8BIT(X)         ((X) >> 4)
+
+typedef struct {
+  UINT32 RESERVED_1;
+  UINT32 CMD_SUPPORT : 2;
+  UINT32 RESERVED_2 : 9;
+  UINT32 EX_SECURITY : 4;
+  UINT32 SD_SPEC3 : 1;
+  UINT32 SD_BUS_WIDTH : 4;
+  UINT32 SD_SECURITY : 3;
+  UINT32 DATA_STAT_AFTER_ERASE : 1;
+  UINT32 SD_SPEC : 4;
+  UINT32 SCR_STRUCTURE : 4;
+} SD_SCR;
+
+typedef SD_OCR MMC_OCR;
+typedef SD_OCR MMC_SEND_OP_COND_ARG;
+
+typedef enum {
+  SdOcrAccessByteMode = 0,
+  SdOcrAccessSectorMode = 2
+} SD_OCR_ACCESS;
+
+// Voltage window that covers from 2.8V and up to 3.6V
+#define SD_OCR_HIGH_VOLTAGE_WINDOW        0x00FF8000
+
+typedef struct {
+  SD_OCR Ocr;
+  SD_CID Cid;
+  SD_CSD Csd;
+  SD_SCR Scr;
+} SD_REGISTERS;
+
+typedef struct {
+  MMC_OCR Ocr;
+  MMC_CID Cid;
+  MMC_CSD Csd;
+  MMC_EXT_CSD ExtCsd;
+} MMC_REGISTERS;
+
+typedef struct {
+  UINT32              RCA;
+  CARD_FUNCTION       CardFunction;
+  BOOLEAN             HasExtendedOcr;
+  BOOLEAN             HighCapacity;
+  UINT64              ByteCapacity;
+  CARD_SPEED_MODE     CurrentSpeedMode;
+
+  union {
+    SD_REGISTERS Sd;
+    MMC_REGISTERS Mmc;
+  } Registers;
+
+} CARD_INFO;
+
+#pragma pack()
+
+#endif // __SDMMCHW_H__
diff --git a/Platform/Microsoft/Include/Protocol/RpmbIo.h b/Platform/Microsoft/Include/Protocol/RpmbIo.h
new file mode 100644
index 000000000000..6087f99615d7
--- /dev/null
+++ b/Platform/Microsoft/Include/Protocol/RpmbIo.h
@@ -0,0 +1,268 @@
+/** @file
+*
+*  RPMB IO protocol is an interface implementation for the Replay Protected Memory
+*  Block (RPMB) as defined by JEDEC Standard for MultiMediaCard specs 4.41.
+*
+*  This protocol abstracts the RPMB operations to allow EFI boot services environment
+*  to perform eMMC RPMB operations without specific knowledge about the card type or
+*  the host controller.
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __RPMB_IO_H__
+#define __RPMB_IO_H__
+
+// Global ID for the RPMB IO Protocol {FBAEE5B2-08B0-41B8-B0B0-86B72EED1BB6}
+#define EFI_RPMB_IO_PROTOCOL_GUID \
+  { 0xfbaee5b2, 0x8b0, 0x41b8, { 0xb0, 0xb0, 0x86, 0xb7, 0x2e, 0xed, 0x1b, 0xb6 } };
+
+#define EFI_RPMB_IO_PROTOCOL_REVISION  0x00010000
+
+// RPMB Request Message Types
+
+#define EFI_RPMB_REQUEST_PROGRAM_KEY     0x0001  // Authentication key programming request
+#define EFI_RPMB_REQUEST_COUNTER_VALUE   0x0002  // Reading of the Write Counter value -request
+#define EFI_RPMB_REQUEST_AUTH_WRITE      0x0003  // Authenticated data write request
+#define EFI_RPMB_REQUEST_AUTH_READ       0x0004  // Authenticated data read request
+#define EFI_RPMB_REQUEST_RESULT_REQUEST  0x0005  // Result read request
+
+// RPMB Response Message Types
+
+#define EFI_RPMB_RESPONSE_PROGRAM_KEY    0x0100  // Authentication key programming response
+#define EFI_RPMB_RESPONSE_COUNTER_VALUE  0x0200  // Reading of the Write Counter value -response
+#define EFI_RPMB_RESPONSE_AUTH_WRITE     0x0300  // Authenticated data write response
+#define EFI_RPMB_RESPONSE_AUTH_READ      0x0400  // Authenticated data read response
+
+// RPMB Operation Results
+
+#define EFI_RPMB_OK                     0   // Operation OK
+#define EFI_RPMB_ERROR_GENERAL          1   // General failure
+#define EFI_RPMB_ERROR_AUTH             2   // Authentication failure (MAC comparison
+                                            //   not matching, MAC calculation failure)
+#define EFI_RPMB_ERROR_COUNTER          3   // Counter failure (counters not matching
+                                            //   in comparison, counter incrementing failure)
+#define EFI_RPMB_ERROR_ADDRESS          4   // Address failure (address out of range,
+                                            //   wrong address alignment)
+#define EFI_RPMB_ERROR_WRITE            5   // Write failure (data/counter/result write failure)
+#define EFI_RPMB_ERROR_READ             6   // Read failure (data/counter/result read failure)
+#define EFI_RPMB_ERROR_KEY              7   // Authentication Key not yet programmed
+
+#define EFI_RPMB_ERROR_MASK             0x7
+#define EFI_RPMB_ERROR_CNT_EXPIRED_BIT  0x80
+
+// RPMB Data Frame fields size in bytes.
+
+#define EFI_RPMB_PACKET_STUFF_SIZE       196
+#define EFI_RPMB_PACKET_KEY_MAC_SIZE     32
+#define EFI_RPMB_PACKET_DATA_SIZE        256
+#define EFI_RPMB_PACKET_NONCE_SIZE       16
+#define EFI_RPMB_PACKET_WCOUNTER_SIZE    4
+#define EFI_RPMB_PACKET_ADDRESS_SIZE     2
+#define EFI_RPMB_PACKET_BLOCKCOUNT_SIZE  2
+#define EFI_RPMB_PACKET_RESULT_SIZE      2
+#define EFI_RPMB_PACKET_TYPE_SIZE        2
+
+// Everything in the RPMB Data Frame is hashed except the Stuff and the MAC itself.
+#define EFI_RPMB_PACKET_DATA_HASH_SIZE ( \
+  sizeof(EFI_RPMB_DATA_PACKET) - \
+  offsetof(EFI_RPMB_DATA_PACKET, PacketData) \
+  )
+
+// CID register is 16 byte
+#define EFI_RPMB_CID_SIZE 16
+
+/** The data frame to access the replay protected memory area.
+
+  NOTE: Byte order of the RPMB data frame is MSB first, e.g. Write Counter MSB
+  [11] is storing the upmost byte of the counter value.
+**/
+#pragma pack(1)
+typedef struct {
+  UINT8  Stuff[EFI_RPMB_PACKET_STUFF_SIZE];
+  UINT8  KeyOrMAC[EFI_RPMB_PACKET_KEY_MAC_SIZE];  // The authentication key or
+                                                  // the message authentication code (MAC)
+                                                  // depending on the request/response
+                                                  // type. The MAC will be delivered
+                                                  // in the last (or the only) block of data
+  UINT8  PacketData[EFI_RPMB_PACKET_DATA_SIZE];   // Data to be written or read by signed access.
+  UINT8  Nonce[EFI_RPMB_PACKET_NONCE_SIZE];       // Random number generated by the host
+                                                  // for the Requests and copied to the
+                                                  // Response by the eMMC Replay Protected
+                                                  // Memory Block engine
+  UINT8  WriteCounter[EFI_RPMB_PACKET_WCOUNTER_SIZE];   // Counter value for the total amount
+                                                        // of the successful authenticated data
+                                                        // write requests made by the host
+  UINT8  Address[EFI_RPMB_PACKET_ADDRESS_SIZE];   // Address of the data to be programmed to
+                                                  // or read from the Replay Protected
+                                                  // Memory Block. Address is the serial number
+                                                  // of the accessed half sector (256B).
+                                                  // Address argument in CMD 18 and CMD 25
+                                                  // will be ignored
+  UINT8  BlockCount[EFI_RPMB_PACKET_BLOCKCOUNT_SIZE];   // Number of blocks (half sectors, 256B)
+                                                        // requested to be read/programmed. This
+                                                        // value is equal to the count value in
+                                                        // CMD23 argument
+  UINT8  OperationResult[EFI_RPMB_PACKET_RESULT_SIZE];  // Includes information about the status
+                                                        // of the write counter (valid, expired)
+                                                        // and successfulness of the access made
+                                                        // to the Replay Protected Memory Block
+  UINT8  RequestOrResponseType[EFI_RPMB_PACKET_TYPE_SIZE];  // Defines the type of request and
+                                                            // response to/from the memory.
+} EFI_RPMB_DATA_PACKET;
+#pragma pack()
+
+typedef struct {
+  EFI_RPMB_DATA_PACKET  *Packets;
+  UINTN                 PacketCount;  // The number of RPMB Frames/Packets which is
+                                      // also the number of half sectors (256Byte) to
+                                      // be read/programmed since each RPBM frame
+                                      // holds 256Bytes of data.
+} EFI_RPMB_DATA_BUFFER;
+
+typedef struct _EFI_RPMB_IO_PROTOCOL EFI_RPMB_IO_PROTOCOL;
+
+/** Authentication key programming request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ProgrammingRequest A data packet describing a key programming request.
+  @param[out] ResultResponse A caller allocated data packet which will receive the
+  key programming result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during key programming any other eMMC internal failure is reported
+  in the Result field of the returned response data packet.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_RPMB_PROGRAM_KEY) (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ProgrammingRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ResultResponse
+  );
+
+/** Reading of the write counter value request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ReadRequest A data packet describing a read counter value request.
+  @param[out] ReadResponse A caller allocated data packet which will receive
+  the counter value read response. If counter has expired bit 7 is set to 1 in
+  returned Result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during counter read or any other eMMC internal failure is reported
+  in the Result field of the returned response data packet.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_RPMB_READ_COUNTER) (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ReadRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ReadResponse
+  );
+
+/** Authenticated data write request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] WriteRequest A sequence of data packets describing data write
+  requests and holds the data to be written.
+  @param[out] ResultResponse A caller allocated data packet which will receive
+  the data write programming result.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during data programming or any other eMMC internal failure is reported
+  in the Result field of the returned data packet.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_RPMB_AUTHENTICATED_WRITE) (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_BUFFER   *WriteRequest,
+  OUT EFI_RPMB_DATA_PACKET  *ResultResponse
+  );
+
+/** Authenticated data read request.
+
+  @param[in] This Indicates a pointer to the calling context.
+  @param[in] ReadRequest A data packet that describes a data read request.
+  @param[out] ReadResponse A caller allocated data packets which will receive
+  the data read.
+
+  @retval EFI_SUCCESS RPMB communication sequence with the eMMC succeeded
+  according to specs, other values are returned in case of any protocol error.
+  Failure during data fetch from the eMMC or any other eMMC internal failure
+  is reported in the Result field of the returned data packet.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_RPMB_AUTHENTICATED_READ) (
+  IN EFI_RPMB_IO_PROTOCOL   *This,
+  IN EFI_RPMB_DATA_PACKET   *ReadRequest,
+  OUT EFI_RPMB_DATA_BUFFER  *ReadResponse
+  );
+
+struct _EFI_RPMB_IO_PROTOCOL {
+  UINT64  Revision;
+  UINT8   Cid[EFI_RPMB_CID_SIZE];   // MMC Card IDentification (CID) register.
+  UINT8   ReliableSectorCount;      // Reliable write sector count as defined by
+                                    // the REL_WR_SEC_C field of the
+                                    // MMC EXT_CSD register.
+  UINT8   RpmbSizeMult;             // RPMB sector size multiplier as defined by
+                                    // the RPMB_SIZE_MULT field of the
+                                    // MMC EXT_CSD register.
+                                    // The RPMB partition size is calculated from
+                                    // the register by using the
+                                    // following equation:
+                                    // RPMB partition size = 128kB x RPMB_SIZE_MULT
+
+  // Protocol Callbacks
+  EFI_RPMB_PROGRAM_KEY          ProgramKey;
+  EFI_RPMB_READ_COUNTER         ReadCounter;
+  EFI_RPMB_AUTHENTICATED_WRITE  AuthenticatedWrite;
+  EFI_RPMB_AUTHENTICATED_READ   AuthenticatedRead;
+};
+
+__inline__
+static
+CONST CHAR16*
+RpmbOperationResultToString (
+  UINT16 OperationResult
+  )
+{
+  switch (OperationResult) {
+    case EFI_RPMB_OK:
+      return L"Operation OK";
+    case EFI_RPMB_ERROR_GENERAL:
+      return L"General failure";
+    case EFI_RPMB_ERROR_AUTH:
+      return L"Authentication failure";
+    case EFI_RPMB_ERROR_COUNTER:
+      return L"Counter failure";
+    case EFI_RPMB_ERROR_ADDRESS:
+      return L"Address failure";
+    case EFI_RPMB_ERROR_WRITE:
+      return L"Write failure";
+    case EFI_RPMB_ERROR_READ:
+      return L"Read failure";
+    case EFI_RPMB_ERROR_KEY:
+      return L"Authentication key not yet programmed";
+    default:
+      return L"Undefined operation result";
+  }
+}
+
+extern EFI_GUID gEfiRpmbIoProtocolGuid;
+
+#endif // __RPMB_IO_H__
diff --git a/Platform/Microsoft/Include/Protocol/Sdhc.h b/Platform/Microsoft/Include/Protocol/Sdhc.h
new file mode 100644
index 000000000000..334036c6dc88
--- /dev/null
+++ b/Platform/Microsoft/Include/Protocol/Sdhc.h
@@ -0,0 +1,197 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __SDHC_H__
+#define __SDHC_H__
+
+//
+// Global ID for the SDHC Protocol {46055B0F-992A-4AD7-8F81-148186FFDF72}
+//
+#define EFI_SDHC_PROTOCOL_GUID \
+  { 0x46055b0f, 0x992a, 0x4ad7, { 0x8f, 0x81, 0x14, 0x81, 0x86, 0xff, 0xdf, 0x72 } };
+
+typedef UINT16 SD_COMMAND_INDEX;
+
+typedef enum {
+    SdCommandTypeUndefined = 0,
+    SdCommandTypeSuspend,
+    SdCommandTypeResume,
+    SdCommandTypeAbort
+} SD_COMMAND_TYPE;
+
+typedef enum {
+    SdCommandClassUndefined = 0,
+    SdCommandClassStandard,
+    SdCommandClassApp
+} SD_COMMAND_CLASS;
+
+typedef enum {
+    SdResponseTypeUndefined = 0,
+    SdResponseTypeNone,
+    SdResponseTypeR1,
+    SdResponseTypeR1B,
+    SdResponseTypeR2,
+    SdResponseTypeR3,
+    SdResponseTypeR4,
+    SdResponseTypeR5,
+    SdResponseTypeR5B,
+    SdResponseTypeR6
+} SD_RESPONSE_TYPE;
+
+typedef enum {
+    SdTransferTypeUndefined = 0,
+    SdTransferTypeNone,
+    SdTransferTypeSingleBlock,
+    SdTransferTypeMultiBlock,
+    SdTransferTypeMultiBlockNoStop
+} SD_TRANSFER_TYPE;
+
+typedef enum {
+    SdTransferDirectionUndefined = 0,
+    SdTransferDirectionRead,
+    SdTransferDirectionWrite
+} SD_TRANSFER_DIRECTION;
+
+typedef struct {
+    SD_COMMAND_INDEX Index;
+    SD_COMMAND_TYPE Type;
+    SD_COMMAND_CLASS Class;
+    SD_RESPONSE_TYPE ResponseType;
+    SD_TRANSFER_TYPE TransferType;
+    SD_TRANSFER_DIRECTION TransferDirection;
+} SD_COMMAND;
+
+typedef struct {
+    UINT32 BlockSize;
+    UINT32 BlockCount;
+    VOID* Buffer;
+} SD_COMMAND_XFR_INFO;
+
+typedef enum {
+    SdBusWidthUndefined = 0,
+    SdBusWidth1Bit = 1,
+    SdBusWidth4Bit = 4,
+    SdBusWidth8Bit = 8
+} SD_BUS_WIDTH;
+
+typedef enum {
+    SdhcResetTypeUndefined = 0,
+    SdhcResetTypeAll,
+    SdhcResetTypeCmd,
+    SdhcResetTypeData
+} SDHC_RESET_TYPE;
+
+typedef struct {
+  UINT32 MaximumBlockSize;
+  UINT32 MaximumBlockCount;
+} SDHC_CAPABILITIES;
+//
+// Forward declaration for EFI_SDHC_PROTOCOL
+//
+typedef struct _EFI_SDHC_PROTOCOL EFI_SDHC_PROTOCOL;
+
+typedef VOID (EFIAPI *SDHC_GET_CAPABILITIES) (
+  IN EFI_SDHC_PROTOCOL *This,
+  OUT SDHC_CAPABILITIES *Capabilities
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_SOFTWARERESET) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN SDHC_RESET_TYPE ResetType
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_SETCLOCK) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN UINT32 TargetFreqHz
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_SETBUSWIDTH) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN SD_BUS_WIDTH BusWidth
+  );
+
+typedef BOOLEAN (EFIAPI *SDHC_ISCARDPRESENT) (
+  IN EFI_SDHC_PROTOCOL *This
+  );
+
+typedef BOOLEAN (EFIAPI *SDHC_ISREADONLY) (
+  IN EFI_SDHC_PROTOCOL *This
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_SENDCOMMAND) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN const SD_COMMAND *Cmd,
+  IN UINT32 Argument,
+  IN OPTIONAL const SD_COMMAND_XFR_INFO *XfrInfo
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_RECEIVERESPONSE) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN const SD_COMMAND *Cmd,
+  OUT UINT32 *Buffer
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_READBLOCKDATA) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN UINTN LengthInBytes,
+  OUT UINT32 *Buffer
+  );
+
+typedef EFI_STATUS (EFIAPI *SDHC_WRITEBLOCKDATA) (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN UINTN LengthInBytes,
+  IN const UINT32 *Buffer
+  );
+
+typedef VOID (EFIAPI *SDHC_CLEANUP) (
+  IN EFI_SDHC_PROTOCOL *This
+  );
+
+struct _EFI_SDHC_PROTOCOL {
+  UINT32                   Revision;
+
+  //
+  // A unique ID that identify the SDHC device among other
+  // SDHC devices on the system
+  //
+  UINT32                   SdhcId;
+
+  //
+  // Context area allocated by the SDHC driver
+  //
+  VOID                     *PrivateContext;
+
+  //
+  // SDHHC Callbacks
+  //
+  SDHC_GET_CAPABILITIES    GetCapabilities;
+  SDHC_SOFTWARERESET       SoftwareReset;
+  SDHC_SETCLOCK            SetClock;
+  SDHC_SETBUSWIDTH         SetBusWidth;
+  SDHC_ISCARDPRESENT       IsCardPresent;
+  SDHC_ISREADONLY          IsReadOnly;
+  SDHC_SENDCOMMAND         SendCommand;
+  SDHC_RECEIVERESPONSE     ReceiveResponse;
+  SDHC_READBLOCKDATA       ReadBlockData;
+  SDHC_WRITEBLOCKDATA      WriteBlockData;
+  SDHC_CLEANUP             Cleanup;
+};
+
+#define SDHC_PROTOCOL_INTERFACE_REVISION    0x00010000    // 1.0
+
+extern EFI_GUID gEfiSdhcProtocolGuid;
+
+#endif // __SDHC_H__
+
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 03/27] Platform/Microsoft: Add MsPkg
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (2 preceding siblings ...)
  2018-09-21  8:25 ` [PATCH edk2-platforms 04/27] Silicon/NXP: Add iMXPlatformPkg dec Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-10-31 21:00   ` Leif Lindholm
  2018-09-21  8:25 ` [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms Chris Co
                   ` (23 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

MsPkg is a collection of libraries and drivers that are specific
to supporting Windows IoT Core but are not Platform/Silicon specific.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Platform/Microsoft/MsPkg.dec | 39 ++++++++++++++++++++
 Platform/Microsoft/MsPkg.dsc | 31 ++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/Platform/Microsoft/MsPkg.dec b/Platform/Microsoft/MsPkg.dec
new file mode 100644
index 000000000000..c19913603e4f
--- /dev/null
+++ b/Platform/Microsoft/MsPkg.dec
@@ -0,0 +1,39 @@
+#/** @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = MsPkg
+  PACKAGE_GUID                   = DC909FB7-F45E-4D7F-BF10-327BD9BFA21C
+  PACKAGE_VERSION                = 0.1
+
+[Includes.common]
+  Include                        # Root include for the package
+
+[LibraryClasses.common]
+
+[Guids.common]
+  gMsPkgTokenSpaceGuid = { 0x3ecb4bb9, 0xb80a, 0x4efd, { 0x92, 0xb8, 0x3a, 0x16, 0xe0, 0xc8, 0x19, 0xb } }
+
+[PcdsFixedAtBuild.common]
+  gMsPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|0x00
+
+  # The DevicePath to a partition on a writeable media used for logging and misc
+  # storage purposes. SD card DevicePath example:
+  # gMsPkgTokenSpaceGuid.PcdStorageMediaPartitionDevicePath|L"VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,03000000)/SD(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)"
+  gMsPkgTokenSpaceGuid.PcdStorageMediaPartitionDevicePath|L""|VOID*|0x03
+
+[Protocols.common]
+  gEfiRpmbIoProtocolGuid = { 0xfbaee5b2, 0x8b0, 0x41b8, { 0xb0, 0xb0, 0x86, 0xb7, 0x2e, 0xed, 0x1b, 0xb6 } }
+  gEfiSdhcProtocolGuid = { 0x46055b0f, 0x992a, 0x4ad7, { 0x8f, 0x81, 0x14, 0x81, 0x86, 0xff, 0xdf, 0x72 } }
diff --git a/Platform/Microsoft/MsPkg.dsc b/Platform/Microsoft/MsPkg.dsc
new file mode 100644
index 000000000000..fc92208673da
--- /dev/null
+++ b/Platform/Microsoft/MsPkg.dsc
@@ -0,0 +1,31 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#   This program and the accompanying materials
+#   are licensed and made available under the terms and conditions of the BSD License
+#   which accompanies this distribution. The full text of the license may be found at
+#   http://opensource.org/licenses/bsd-license.
+#
+#   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  PLATFORM_NAME                  = MsPkg
+  PLATFORM_GUID                  = 2F78367E-9C74-4FBE-82E7-1D2DAAF18CC6
+  PLATFORM_VERSION               = 0.01
+  DSC_SPECIFICATION              = 0x0001001A
+  OUTPUT_DIRECTORY               = Build/MsPkg
+  SUPPORTED_ARCHITECTURES        = ARM|AARCH64
+  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
+  SKUID_IDENTIFIER               = DEFAULT
+
+[PcdsFeatureFlag]
+
+[PcdsFixedAtBuild]
+
+[LibraryClasses]
+
+[Components]
+  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 04/27] Silicon/NXP: Add iMXPlatformPkg dec
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
  2018-09-21  8:25 ` [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec Chris Co
  2018-09-21  8:25 ` [PATCH edk2-platforms 02/27] Platform/Microsoft: Add SdMmc Dxe Driver Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-09-21  8:25 ` [PATCH edk2-platforms 03/27] Platform/Microsoft: Add MsPkg Chris Co
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

iMXPlatformPkg holds drivers, libraries, and include files that are common
across the NXP i.MX line of SoCs.  This commit defines iMXPlatform PCDs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec | 118 ++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec b/Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
new file mode 100644
index 000000000000..75e4362fb4ce
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
@@ -0,0 +1,118 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = iMXPlatformPkg
+  PACKAGE_GUID                   = 6eba6648-d853-4eb3-9761-528b82d5ab04
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+#  DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+  Include                        # Root include for the package
+
+[LibraryClasses]
+
+[Guids.common]
+  giMXPlatformTokenSpaceGuid = { 0x24b09abe, 0x4e47, 0x481c, { 0xa9, 0xad, 0xce, 0xf1, 0x2c, 0x39, 0x23, 0x27} }
+
+[PcdsFixedAtBuild.common]
+  #
+  # Default base address based that needs to be defined per platform
+  #
+  giMXPlatformTokenSpaceGuid.PcdSdhc1Base|0x02190000|UINT32|0x00
+  giMXPlatformTokenSpaceGuid.PcdSdhc2Base|0x02194000|UINT32|0x01
+  giMXPlatformTokenSpaceGuid.PcdSdhc3Base|0x02198000|UINT32|0x02
+  giMXPlatformTokenSpaceGuid.PcdSdhc4Base|0x0219C000|UINT32|0x03
+
+  #
+  # Enabled uSDHCx will be registered as a BlockIo device
+  #
+  giMXPlatformTokenSpaceGuid.PcdSdhc1Enable|FALSE|BOOLEAN|0x04
+  giMXPlatformTokenSpaceGuid.PcdSdhc2Enable|FALSE|BOOLEAN|0x05
+  giMXPlatformTokenSpaceGuid.PcdSdhc3Enable|FALSE|BOOLEAN|0x06
+  giMXPlatformTokenSpaceGuid.PcdSdhc4Enable|FALSE|BOOLEAN|0x07
+
+  #
+  # Slot CardDetect and WriteProtect signals source
+  #
+  # Legal values are as follows:
+  #
+  # [0x0000, 0xFEFF]
+  # Use a value in the range from 0x0 to 0xFEFF exclusive to indicate
+  # GPIO as signal source, use MSB byte as GPIO bank number, and LSB byte
+  # as IO number both in 1-based numbering fashion. e.g. 0x0201 means GPIO2_IO1
+  #
+  # 0xFF00  -USDHC_SIGNAL_OVERRIDE_PIN_LOW
+  # Override signal source to always read LOW
+  # NOTE: CD_B=0 means card present, while WP=0 means write enabled
+  #
+  # 0xFF01 - USDHC_SIGNAL_OVERRIDE_PIN_HIGH
+  # Override signal source to always read HIGH
+  # NOTE: CD_B=1 means card not present, while WP=1 means write protected
+  #
+  # 0xFFFF - USDHC_SIGNAL_INTERNAL_PIN
+  # Signal is connected directly to the SDHC block. Which means use th SDHC
+  # internal FSM for interpreting card detect CD_B and write protect WP signals
+  # from the slot
+  #
+  # Default signals to LOW to force card present and write enabled
+  #
+  giMXPlatformTokenSpaceGuid.PcdSdhc1CardDetectSignal|0xFF00|UINT16|0x08
+  giMXPlatformTokenSpaceGuid.PcdSdhc1WriteProtectSignal|0xFF01|UINT16|0x09
+
+  giMXPlatformTokenSpaceGuid.PcdSdhc2CardDetectSignal|0xFF00|UINT16|0x0A
+  giMXPlatformTokenSpaceGuid.PcdSdhc2WriteProtectSignal|0xFF01|UINT16|0x0B
+
+  giMXPlatformTokenSpaceGuid.PcdSdhc3CardDetectSignal|0xFF00|UINT16|0x0C
+  giMXPlatformTokenSpaceGuid.PcdSdhc3WriteProtectSignal|0xFF01|UINT16|0x0D
+
+  giMXPlatformTokenSpaceGuid.PcdSdhc4CardDetectSignal|0xFF00|UINT16|0x0E
+  giMXPlatformTokenSpaceGuid.PcdSdhc4WriteProtectSignal|0xFF01|UINT16|0x0F
+
+  #
+  # iMX UART configuration
+  #
+  # PcdSerialRegisterBase   - Define a base address of UEFI console UART
+  # PcdKdUartInstance - UART instance that should be used for Windows
+  #                     Kernel debugger. 1, 2, 3, 4, or 5
+  #
+  giMXPlatformTokenSpaceGuid.PcdKdUartInstance|1|UINT32|0x11
+  giMXPlatformTokenSpaceGuid.PcdSerialRegisterBase|0x00000000|UINT32|0x12
+
+  #
+  # Global data area
+  # The PcdGlobalDataBaseAddress and PcdGlobalDataSize have to be set by each
+  # platform based on the memory layout.
+  #
+  giMXPlatformTokenSpaceGuid.PcdGlobalDataBaseAddress|0x00000000|UINT32|0x13
+  giMXPlatformTokenSpaceGuid.PcdGlobalDataSize|0x1000|UINT32|0x14
+
+  #
+  # iMX GPIO configuration
+  #
+  # PcdGpioBankMemoryRange - The memory range for 1 GPIO bank register (default 16KB)
+  #
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange|16384|UINT32|0x15
+
+[PcdsFeatureFlag.common]
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (3 preceding siblings ...)
  2018-09-21  8:25 ` [PATCH edk2-platforms 03/27] Platform/Microsoft: Add MsPkg Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-11-01  8:59   ` Leif Lindholm
  2018-09-21  8:25 ` [PATCH edk2-platforms 06/27] Silicon/NXP: Add I2C " Chris Co
                   ` (22 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for interact with the UART controller on
NXP i.MX platforms.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h                               | 207 +++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c   | 243 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf |  41 ++++
 3 files changed, 491 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
new file mode 100644
index 000000000000..ddb61f59c656
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
@@ -0,0 +1,207 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMXUART_H_
+#define _IMXUART_H_
+
+// UART Receiver Register bit definitions
+enum MX6UART_RXD {
+  MX6UART_RXD_RX_DATA_MASK =      (0xff << 0),
+  MX6UART_RXD_PRERR =             (1 << 10),
+  MX6UART_RXD_BRK =               (1 << 11),
+  MX6UART_RXD_FRMERR =            (1 << 12),
+  MX6UART_RXD_OVRRUN =            (1 << 13),
+  MX6UART_RXD_ERR =               (1 << 14),
+  MX6UART_RXD_CHARRDY =           (1 << 15),
+};
+
+// UART Control Register 1 bit definitions
+enum MX6UART_UCR1 {
+  MX6UART_UCR1_UARTEN =           (1 << 0),
+  MX6UART_UCR1_DOZE =             (1 << 1),
+  MX6UART_UCR1_ATDMAEN =          (1 << 2),
+  MX6UART_UCR1_TXDMAEN =          (1 << 3),
+  MX6UART_UCR1_SNDBRK =           (1 << 4),
+  MX6UART_UCR1_RTSDEN =           (1 << 5),
+  MX6UART_UCR1_TXMPTYEN =         (1 << 6),
+  MX6UART_UCR1_IREN =             (1 << 7),
+  MX6UART_UCR1_RXDMAEN =          (1 << 8),
+  MX6UART_UCR1_RRDYEN =           (1 << 9),
+  MX6UART_UCR1_ICD_MASK =         (3 << 10),
+  MX6UART_UCR1_ICD_4 =            (0 << 10),
+  MX6UART_UCR1_ICD_8 =            (1 << 10),
+  MX6UART_UCR1_ICD_16 =           (2 << 10),
+  MX6UART_UCR1_ICD_32 =           (3 << 10),
+  MX6UART_UCR1_IDEN =             (1 << 12),
+  MX6UART_UCR1_TRDYEN =           (1 << 13),
+  MX6UART_UCR1_ADBR =             (1 << 14),
+  MX6UART_UCR1_ADEN =             (1 << 15),
+};
+
+// UART Control Register 2 bit definitions
+enum MX6UART_UCR2 {
+  MX6UART_UCR2_SRST =             (1 << 0),
+  MX6UART_UCR2_RXEN =             (1 << 1),
+  MX6UART_UCR2_TXEN =             (1 << 2),
+  MX6UART_UCR2_ATEN =             (1 << 3),
+  MX6UART_UCR2_RTSEN =            (1 << 4),
+  MX6UART_UCR2_WS =               (1 << 5),
+  MX6UART_UCR2_STPB =             (1 << 6),
+  MX6UART_UCR2_PROE =             (1 << 7),
+  MX6UART_UCR2_PREN =             (1 << 8),
+  MX6UART_UCR2_RTEC_MASK =        (3 << 9),
+  MX6UART_UCR2_RTEC_RISING =      (0 << 9),
+  MX6UART_UCR2_RTEC_FALLING =     (1 << 9),
+  MX6UART_UCR2_RTEC_BOTH =        (2 << 9),
+  MX6UART_UCR2_ESCEN =            (1 << 11),
+  MX6UART_UCR2_CTS =              (1 << 12),
+  MX6UART_UCR2_CTSC =             (1 << 13),
+  MX6UART_UCR2_IRTS =             (1 << 14),
+  MX6UART_UCR2_ESCI =             (1 << 15),
+};
+
+// UART Control Register 3 bit definitions
+enum MX6UART_UCR3 {
+  MX6UART_UCR3_ACIEN =            (1 << 0),
+  MX6UART_UCR3_INVT =             (1 << 1),
+  MX6UART_UCR3_RXDMUXSEL =        (1 << 2),
+  MX6UART_UCR3_DTRDEN =           (1 << 3),
+  MX6UART_UCR3_AWAKEN =           (1 << 4),
+  MX6UART_UCR3_AIRINTEN =         (1 << 5),
+  MX6UART_UCR3_RXDSEN =           (1 << 6),
+  MX6UART_UCR3_ADNIMP =           (1 << 7),
+  MX6UART_UCR3_RI =               (1 << 8),
+  MX6UART_UCR3_DCD =              (1 << 9),
+  MX6UART_UCR3_DSR =              (1 << 10),
+  MX6UART_UCR3_FRAERREN =         (1 << 11),
+  MX6UART_UCR3_PARERREN =         (1 << 12),
+  MX6UART_UCR3_DTREN =            (1 << 13),
+  MX6UART_UCR3_DPEC_MASK =        (3 << 14),
+  MX6UART_UCR3_DPEC_RISING =      (0 << 14),
+  MX6UART_UCR3_DPEC_FALLING =     (1 << 14),
+  MX6UART_UCR3_DPEC_BOTH =        (2 << 14),
+};
+
+// UART Control Register 4 bit definitions
+enum MX6UART_UCR4 {
+  MX6UART_UCR4_DREN =             (1 << 0),
+  MX6UART_UCR4_OREN =             (1 << 1),
+  MX6UART_UCR4_BKEN =             (1 << 2),
+  MX6UART_UCR4_TCEN =             (1 << 3),
+  MX6UART_UCR4_LPBYP =            (1 << 4),
+  MX6UART_UCR4_IRSC =             (1 << 5),
+  MX6UART_UCR4_IDDMAEN =          (1 << 6),
+  MX6UART_UCR4_WKEN =             (1 << 7),
+  MX6UART_UCR4_ENIRI =            (1 << 8),
+  MX6UART_UCR4_INVR =             (1 << 9),
+  MX6UART_UCR4_CTSTL_MASK =       (0x3f << 10),
+  MX6UART_UCR4_CTSTL_SHIFT =      10,
+};
+
+// UART FIFO Control Register bit definitions
+enum MX6UART_UFCR {
+  MX6UART_UFCR_RXTL_MASK =        (0x3f << 0),
+  MX6UART_UFCR_RXTL_SHIFT =       0,
+  MX6UART_UFCR_DCEDTE =           (1 << 6),
+  MX6UART_UFCR_RFDIV_MASK =       (7 << 7),
+  MX6UART_UFCR_RFDIV_6 =          (0 << 7),
+  MX6UART_UFCR_RFDIV_5 =          (1 << 7),
+  MX6UART_UFCR_RFDIV_4 =          (2 << 7),
+  MX6UART_UFCR_RFDIV_3 =          (3 << 7),
+  MX6UART_UFCR_RFDIV_2 =          (4 << 7),
+  MX6UART_UFCR_RFDIV_1 =          (5 << 7),
+  MX6UART_UFCR_RFDIV_7 =          (6 << 7),
+  MX6UART_UFCR_TXTL_MASK =        (0x3f << 10),
+  MX6UART_UFCR_TXTL_SHIFT =       10,
+};
+
+// UART Status Register 1 bit definitions
+enum MX6UART_USR1 {
+  MX6UART_USR1_SAD =              (1 << 3),
+  MX6UART_USR1_AWAKE =            (1 << 4),
+  MX6UART_USR1_AIRINT =           (1 << 5),
+  MX6UART_USR1_RXDS =             (1 << 6),
+  MX6UART_USR1_DTRD =             (1 << 7),
+  MX6UART_USR1_AGTIM =            (1 << 8),
+  MX6UART_USR1_RRDY =             (1 << 9),
+  MX6UART_USR1_FRAMERR =          (1 << 10),
+  MX6UART_USR1_ESCF =             (1 << 11),
+  MX6UART_USR1_RTSD =             (1 << 12),
+  MX6UART_USR1_TRDY =             (1 << 13),
+  MX6UART_USR1_RTSS =             (1 << 14),
+  MX6UART_USR1_PARITYERR =        (1 << 15),
+};
+
+// UART Status Register 2 bit definitions
+enum MX6UART_USR2 {
+  MX6UART_USR2_RDR =              (1 << 0),
+  MX6UART_USR2_ORE =              (1 << 1),
+  MX6UART_USR2_BRCD =             (1 << 2),
+  MX6UART_USR2_TXDC =             (1 << 3),
+  MX6UART_USR2_RTSF =             (1 << 4),
+  MX6UART_USR2_DCDIN =            (1 << 5),
+  MX6UART_USR2_DCDDELT =          (1 << 6),
+  MX6UART_USR2_WAKE =             (1 << 7),
+  MX6UART_USR2_IRINT =            (1 << 8),
+  MX6UART_USR2_RIIN =             (1 << 9),
+  MX6UART_USR2_RIDLET =           (1 << 10),
+  MX6UART_USR2_ACST =             (1 << 11),
+  MX6UART_USR2_IDLE =             (1 << 12),
+  MX6UART_USR2_DTRF =             (1 << 13),
+  MX6UART_USR2_TXFE =             (1 << 14),
+  MX6UART_USR2_ADET =             (1 << 15),
+};
+
+// UART Test Register bit definitions
+enum MX6UART_UTS {
+  MX6UART_UTS_SOFTRST =           (1 << 0),
+  MX6UART_UTS_RXFULL =            (1 << 3),
+  MX6UART_UTS_TXFULL =            (1 << 4),
+  MX6UART_UTS_RXEMPTY =           (1 << 5),
+  MX6UART_UTS_TXEMPTY =           (1 << 6),
+  MX6UART_UTS_RXDBG =             (1 << 9),
+  MX6UART_UTS_LOOPIR =            (1 << 10),
+  MX6UART_UTS_DBGEN =             (1 << 11),
+  MX6UART_UTS_LOOP =              (1 << 12),
+  MX6UART_UTS_FRCPERR =           (1 << 13),
+};
+
+// Size of RX and TX FIFOs
+enum {
+  MX6UART_FIFO_COUNT = 32
+};
+
+typedef struct _MX6UART_REGISTERS {
+  UINT32 Rxd;                  // 0x00: UART Receiver Register
+  UINT32 reserved1[15];
+  UINT32 Txd;                  // 0x40: UART Transmitter Register
+  UINT32 reserved2[15];
+  UINT32 Ucr1;                 // 0x80: UART Control Register 1
+  UINT32 Ucr2;                 // 0x84: UART Control Register 2
+  UINT32 Ucr3;                 // 0x88: UART Control Register 3
+  UINT32 Ucr4;                 // 0x8C: UART Control Register 4
+  UINT32 Ufcr;                 // 0x90: UART FIFO Control Register
+  UINT32 Usr1;                 // 0x94: UART Status Register 1
+  UINT32 Usr2;                 // 0x98: UART Status Register 2
+  UINT32 Uesc;                 // 0x9C: UART Escape Character Register
+  UINT32 Utim;                 // 0xA0: UART Escape Timer Register
+  UINT32 Ubir;                 // 0xA4: UART BRM Incremental Register
+  UINT32 Ubmr;                 // 0xA8: UART BRM Modulator Register (UART1_UBMR)
+  UINT32 Ubrc;                 // 0xAC: UART Baud Rate Count Register
+  UINT32 Onems;                // 0xB0: UART One Millisecond Register
+  UINT32 Uts;                  // 0xB4: UART Test Register
+  UINT32 Umcr;                 // 0xB8: UART RS-485 Mode Control Register
+} MX6UART_REGISTERS;
+
+#endif // _IMXUART_H_
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
new file mode 100644
index 000000000000..fbe24d98c6aa
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
@@ -0,0 +1,243 @@
+/** @file
+
+  Copyright (c) 2006 - 2008, Intel Corporation
+  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+
+  All rights reserved. This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/SerialPortLib.h>
+#include <iMXUart.h>
+
+
+/**
+  Initialize the serial device hardware.
+
+  If no initialization is required, then return RETURN_SUCCESS.
+  If the serial device was successfully initialized, then return RETURN_SUCCESS.
+  If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+  VOID
+  )
+{
+  MX6UART_REGISTERS   *UartBase;
+  UINT32              Ucr1;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+
+  Ucr1 = MmioRead32 ((UINTN)&UartBase->Ucr1);
+  if ((Ucr1 & MX6UART_UCR1_UARTEN) == 0) {
+    // UART should have been initialized by previous boot stage
+    return RETURN_DEVICE_ERROR;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Write data from buffer to serial device.
+
+  Writes NumberOfBytes data bytes from Buffer to the serial device.
+  The number of bytes actually written to the serial device is returned.
+  If the return value is less than NumberOfBytes, then the write operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to be written.
+  @param  NumberOfBytes    Number of bytes to written to the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes written to the serial device.
+                           If this value is less than NumberOfBytes, then the
+                           read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+  IN  UINT8   *Buffer,
+  IN  UINTN   NumberOfBytes
+  )
+{
+  MX6UART_REGISTERS   *UartBase;
+  UINTN               BytesSent;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+  BytesSent = 0;
+  while (BytesSent < NumberOfBytes) {
+    // Check if FIFO is full and wait if it is.
+    while ((MmioRead32 ((UINTN)&UartBase->Uts) & MX6UART_UTS_TXFULL) != 0);
+    MmioWrite32 ((UINTN)&UartBase->Txd, Buffer[BytesSent]);
+    BytesSent++;
+  }
+
+  return BytesSent;
+}
+
+/**
+  Read data from serial device and save the datas in buffer.
+
+  Reads NumberOfBytes data bytes from a serial device into the buffer
+  specified by Buffer. The number of bytes actually read is returned.
+  If the return value is less than NumberOfBytes, then the rest operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer            Pointer to the data buffer to store the data read
+                            from the serial device.
+  @param  NumberOfBytes     Number of bytes which will be read.
+
+  @retval 0                 Read data failed, No data is to be read.
+  @retval >0                Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+  OUT UINT8   *Buffer,
+  IN  UINTN   NumberOfBytes
+  )
+{
+  MX6UART_REGISTERS   *UartBase;
+  UINTN               BytesRead;
+  UINT32              Rxd;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+  BytesRead = 0;
+  while (BytesRead < NumberOfBytes) {
+    Rxd = MmioRead32 ((UINTN)&UartBase->Rxd);
+    if ((Rxd & MX6UART_RXD_CHARRDY) == 0) {
+      break;
+    }
+
+    Buffer[BytesRead] = (UINT8) (Rxd & MX6UART_RXD_RX_DATA_MASK);
+    BytesRead++;
+  }
+
+  return BytesRead;
+}
+
+/**
+  Polls a serial device to see if there is any data waiting to be read.
+
+  Polls a serial device to see if there is any data waiting to be read.
+  If there is data waiting to be read from the serial device, then TRUE is
+  returned.
+  If there is no data waiting to be read from the serial device, then FALSE is
+  returned.
+
+  @retval TRUE          Data is waiting to be read from the serial device.
+  @retval FALSE         There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+  VOID
+  )
+{
+  MX6UART_REGISTERS *UartBase;
+  UINT32 Usr2;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+  Usr2 = MmioRead32 ((UINTN)&UartBase->Usr2);
+  return (Usr2 & MX6UART_USR2_RDR) != 0;
+}
+
+/**
+  Sets the control bits on a serial device.
+
+  @param Control                Sets the bits of Control that are settable.
+
+  @retval RETURN_UNSUPPORTED    The serial device does not support this operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+  IN UINT32   Control
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Retrieve the status of the control bits on a serial device.
+
+  @param Control                A pointer to return the current control signals
+                                from the serial device.
+
+  @retval RETURN_UNSUPPORTED    The serial device does not support this operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+  OUT UINT32  *Control
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
+  data bits, and stop bits on a serial device.
+
+  @param BaudRate           The requested baud rate. A BaudRate value of 0 will
+                            use the device's default interface speed.
+                            On output, the value actually set.
+  @param ReveiveFifoDepth   The requested depth of the FIFO on the receive side
+                            of the serial interface. A ReceiveFifoDepth value
+                            of 0 will use the device's default FIFO depth.
+                            On output, the value actually set.
+  @param Timeout            The requested time out for a single character in
+                            microseconds. This timeout applies to both the
+                            transmit and receive side of the interface. A
+                            Timeout value of 0 will use the device's default
+                            timeout value.
+                            On output, the value actually set.
+  @param Parity             The type of parity to use on this serial device. A
+                            Parity value of DefaultParity will use the device's
+                            default parity value.
+                            On output, the value actually set.
+  @param DataBits           The number of data bits to use on the serial device.
+                            A DataBits value of 0 will use the device's default
+                            data bit setting.
+                            On output, the value actually set.
+  @param StopBits           The number of stop bits to use on this serial device.
+                            A StopBits value of DefaultStopBits will use the
+                            device's default number of stop bits.
+                            On output, the value actually set.
+
+  @retval RETURN_UNSUPPORTED        The serial device does not support this operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetAttributes (
+  IN OUT UINT64             *BaudRate,
+  IN OUT UINT32             *ReceiveFifoDepth,
+  IN OUT UINT32             *Timeout,
+  IN OUT EFI_PARITY_TYPE    *Parity,
+  IN OUT UINT8              *DataBits,
+  IN OUT EFI_STOP_BITS_TYPE *StopBits
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
new file mode 100644
index 000000000000..9f381b199f38
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
@@ -0,0 +1,41 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = SerialPortLib
+  FILE_GUID                      = C22D85E6-8B3E-4c05-AA5B-5732F3ACD055
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SerialPortLib
+
+[Sources.common]
+  UartSerialPortLib.c
+
+[LibraryClasses]
+  ArmLib
+  BaseMemoryLib
+  CacheMaintenanceLib
+  IoLib
+  PcdLib
+  TimerLib
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdSerialRegisterBase
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 06/27] Silicon/NXP: Add I2C library support for i.MX platforms
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (4 preceding siblings ...)
  2018-09-21  8:25 ` [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-11-01 17:53   ` Leif Lindholm
  2018-09-21  8:25 ` [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support Chris Co
                   ` (21 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for I2C controller on NXP i.MX platforms.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h             | 162 +++++++
 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c   | 487 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf |  35 ++
 3 files changed, 684 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
new file mode 100644
index 000000000000..de8a1616fe1b
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
@@ -0,0 +1,162 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX_I2C_H_
+#define _IMX_I2C_H_
+
+#pragma pack(push, 1)
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 Reserved0 : 1;
+    UINT16 ADR : 7;
+    UINT16 Reserved1 : 8;
+  };
+} IMX_I2C_IADR_REG;
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 IC : 6;
+    UINT16 Reserved0 : 10;
+  };
+} IMX_I2C_IFDR_REG;
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 Reserved0 : 2;
+    UINT16 RSTA : 1;
+    UINT16 TXAK : 1;
+    UINT16 MTX : 1;
+    UINT16 MSTA : 1;
+    UINT16 IIEN : 1;
+    UINT16 IEN : 1;
+    UINT16 Reserved1 : 8;
+  };
+} IMX_I2C_I2CR_REG;
+
+#define IMX_I2C_I2SR_RXAK        0x0001
+#define IMX_I2C_I2SR_IIF         0x0002
+#define IMX_I2C_I2SR_SRW         0x0004
+#define IMX_I2C_I2SR_IAL         0x0010
+#define IMX_I2C_I2SR_IBB         0x0020
+#define IMX_I2C_I2SR_IAAS        0x0040
+#define IMX_I2C_I2SR_ICF         0x0080
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 RXAK : 1;
+    UINT16 IIF : 1;
+    UINT16 SRW : 1;
+    UINT16 Reserved0 : 1;
+    UINT16 IAL : 1;
+    UINT16 IBB : 1;
+    UINT16 IAAS : 1;
+    UINT16 ICF : 1;
+    UINT16 Reserved1 : 8;
+  };
+} IMX_I2C_I2SR_REG;
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 DATA : 8;
+    UINT16 Reserved0 : 8;
+  };
+} IMX_I2C_I2DR_REG;
+
+typedef struct {
+  IMX_I2C_IADR_REG IADR;
+  UINT16 Pad0;
+  IMX_I2C_IFDR_REG IFDR;
+  UINT16 Pad1;
+  IMX_I2C_I2CR_REG I2CR;
+  UINT16 Pad2;
+  IMX_I2C_I2DR_REG I2SR;
+  UINT16 Pad3;
+  IMX_I2C_I2DR_REG I2DR;
+  UINT16 Pad4;
+} IMX_I2C_REGS;
+
+#pragma pack(pop)
+
+typedef struct {
+  UINT32 ControllerAddress;
+  UINT32 ControllerSlaveAddress;
+  UINT32 ReferenceFreq;
+  UINT32 TargetFreq;
+  UINT32 SlaveAddress;
+  UINT32 TimeoutInUs;
+} IMX_I2C_CONFIG;
+
+typedef struct {
+  UINT32 Divider;
+  UINT32 IC;
+} IMX_I2C_DIVIDER;
+
+/**
+  Perform I2C read operation.
+
+  The iMXI2cRead perform I2C read operation by programming the I2C controller.
+  The caller is responsible to provide I2C controller configuration.
+
+  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
+                                  I2C controller to be used for I2C operation.
+  @param[in]    RegisterAddress   Targeted device register address to start read.
+  @param[out]   ReadBufferPtr     Caller supplied buffer that would be written
+                                  into with data from the read operation.
+  @param[in]    ReadBufferSize    Size of caller supplied buffer.
+
+  @retval   RETURN_SUCCESS        I2C Read operation succeeded.
+  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
+
+**/
+RETURN_STATUS
+iMXI2cRead (
+  IN IMX_I2C_CONFIG  *I2cConfigPtr,
+  IN UINT8            RegisterAddress,
+  OUT UINT8          *ReadBufferPtr,
+  IN UINT32           ReadBufferSize
+  );
+
+/**
+  Perform I2C write operation.
+
+  The iMXI2cWrite perform I2C write operation by programming the I2C
+  controller. The caller is responsible to provide I2C controller
+  configuration.
+
+  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
+                                  I2C controller to be used for I2C operation.
+  @param[in]    RegisterAddress   Targeted device register address to start write.
+  @param[out]   WriteBufferPtr    Caller supplied buffer that contained data that
+                                  would be read from for I2C write operation.
+  @param[in]    WriteBufferSize   Size of caller supplied buffer.
+
+  @retval   RETURN_SUCCESS        I2C Write operation succeeded.
+  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
+
+**/
+RETURN_STATUS
+iMXI2cWrite (
+  IN IMX_I2C_CONFIG  *I2cConfigPtr,
+  IN UINT8            RegisterAddress,
+  IN UINT8           *WriteBufferPtr,
+  IN UINT32           WriteBufferSize
+  );
+
+#endif
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
new file mode 100644
index 000000000000..6cfe04dba571
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
@@ -0,0 +1,487 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+
+#include <iMXI2cLib.h>
+
+IMX_I2C_DIVIDER DividerValue[] = {
+  { 22, 0x20, },
+  { 24, 0x21, },
+  { 26, 0x22, },
+  { 28, 0x23, },
+  { 30, 0x00, },
+  { 32, 0x24, },
+  { 36, 0x25, },
+  { 40, 0x26, },
+  { 42, 0x03, },
+  { 44, 0x27, },
+  { 48, 0x28, },
+  { 52, 0x05, },
+  { 56, 0x29, },
+  { 60, 0x06, },
+  { 64, 0x2A, },
+  { 72, 0x2B, },
+  { 80, 0x2C, },
+  { 88, 0x09, },
+  { 96, 0x2D, },
+  { 104, 0x0A, },
+  { 112, 0x2E, },
+  { 128, 0x2F, },
+  { 144, 0x0C, },
+  { 160, 0x30, },
+  { 192, 0x31, },
+  { 224, 0x32, },
+  { 240, 0x0F, },
+  { 256, 0x33, },
+  { 288, 0x10, },
+  { 320, 0x34, },
+  { 384, 0x35, },
+  { 448, 0x36, },
+  { 480, 0x13, },
+  { 512, 0x37, },
+  { 576, 0x14, },
+  { 640, 0x38, },
+  { 768, 0x39, },
+  { 896, 0x3A, },
+  { 960, 0x17, },
+  { 1024, 0x3B, },
+  { 1152, 0x18, },
+  { 1280, 0x3C, },
+  { 1536, 0x3D, },
+  { 1792, 0x3E, },
+  { 1920, 0x1B, },
+  { 2048, 0x3F, },
+  { 2304, 0x1C, },
+  { 2560, 0x1D, },
+  { 3072, 0x1E, },
+  { 3840, 0x1F, },
+};
+
+#define DIVIDER_VALUE_TOTAL (sizeof(DividerValue) / sizeof(DividerValue[0]))
+
+BOOLEAN
+iMXI2cWaitStatusSet (
+  IN  IMX_I2C_CONFIG   *I2cConfigPtr,
+  IN  UINT16           StatusBits
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  UINT32            Counter;
+  IMX_I2C_I2SR_REG  I2srReg;
+
+  Counter = I2cConfigPtr->TimeoutInUs;
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+  while (Counter) {
+    I2srReg = (IMX_I2C_I2SR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2SR);
+    if ((I2srReg.AsUint16 & StatusBits) == StatusBits) {
+      return TRUE;
+    }
+    MicroSecondDelay (1);
+    --Counter;
+  }
+
+  return FALSE;
+}
+
+BOOLEAN
+iMXI2cWaitStatusUnSet (
+  IN  IMX_I2C_CONFIG   *I2cConfigPtr,
+  IN  UINT16           StatusBits
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  UINT32            Counter;
+  IMX_I2C_I2SR_REG  I2srReg;
+
+  Counter = I2cConfigPtr->TimeoutInUs;
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+  while (Counter) {
+    I2srReg = (IMX_I2C_I2SR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2SR);
+    if ((I2srReg.AsUint16 & StatusBits) == 0) {
+      return TRUE;
+    }
+    MicroSecondDelay (1);
+    --Counter;
+  }
+
+  return FALSE;
+}
+
+BOOLEAN
+iMXI2cSendByte (
+  IN  IMX_I2C_CONFIG  *I2cConfigPtr,
+  IN  UINT8           Data
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  UINT32            Counter;
+  IMX_I2C_I2SR_REG  I2srReg;
+  UINT16            SendData;
+
+  SendData = Data;
+  Counter = I2cConfigPtr->TimeoutInUs;
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+
+  // Clear status and transfer byte
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2DR, SendData);
+
+  while (Counter) {
+    I2srReg = (IMX_I2C_I2SR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2SR);
+    if (I2srReg.IIF == 1) {
+      return TRUE;
+    } else if (I2srReg.IAL == 1) {
+      DEBUG ((DEBUG_ERROR, "iMXI2cSendByte: fail 0x%04x\n", I2srReg.AsUint16));
+      return FALSE;
+    }
+    MicroSecondDelay (1);
+    --Counter;
+  }
+
+  DEBUG ((DEBUG_ERROR, "iMXI2cSendByte: Fail timeout\n"));
+  return FALSE;
+}
+
+RETURN_STATUS
+iMXI2cSetupController (
+  IN  IMX_I2C_CONFIG *I2cConfigPtr
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  UINT32            Divider;
+  UINT32            DividerCount;
+  UINT32            IfdrDiv;
+  IMX_I2C_I2CR_REG  I2crReg;
+
+  I2cRegsPtr = (IMX_I2C_REGS *)I2cConfigPtr->ControllerAddress;
+
+  // Disable controller and clear any pending interrupt
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, 0);
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
+
+  // Setup Divider if reference freq is provided. If no, use value setup by
+  // 1st boot loader
+  if (I2cConfigPtr->ReferenceFreq != 0) {
+    IfdrDiv = 0;
+    Divider = I2cConfigPtr->ReferenceFreq / I2cConfigPtr->TargetFreq;
+
+    for (DividerCount = 0; DividerCount < DIVIDER_VALUE_TOTAL; ++DividerCount) {
+      if (DividerValue[DividerCount].Divider >= Divider) {
+        DEBUG ((
+                 DEBUG_INFO,
+                 "iMXI2cSetupController: Divider %d IC 0x%02x\n",
+                 DividerValue[DividerCount].Divider,
+                 DividerValue[DividerCount].IC));
+        IfdrDiv = DividerValue[DividerCount].IC;
+        break;
+      }
+    }
+
+    if (IfdrDiv == 0) {
+      DEBUG ((
+               DEBUG_ERROR,
+               "iMXI2cSetupController: could not find Divider for %d\n",
+               Divider));
+      return RETURN_INVALID_PARAMETER;
+    }
+
+    MmioWrite16 ((UINTN)&I2cRegsPtr->IFDR, IfdrDiv);
+  }
+
+  // Setup slave address
+  MmioWrite16 ((UINTN)&I2cRegsPtr->IADR,
+               (I2cConfigPtr->ControllerSlaveAddress << 1));
+
+  // Enable controller and set to master mode.
+  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
+
+  // This bit must be set before any other I2C_I2CR bits have an effect
+  I2crReg.IEN = 1;
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+  MicroSecondDelay (100);
+
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
+
+  // Wait for bus to be idle
+  if (iMXI2cWaitStatusUnSet (I2cConfigPtr, IMX_I2C_I2SR_IBB) == FALSE) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStart: Controller remains busy\n"));
+    return RETURN_DEVICE_ERROR;
+  }
+
+  I2crReg.MSTA = 1;
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+
+  // Now wait for bus to be busy
+  if (iMXI2cWaitStatusSet (I2cConfigPtr, IMX_I2C_I2SR_IBB) == FALSE) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStart: Controller remains idle\n"));
+    return RETURN_DEVICE_ERROR;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+iMXI2cGenerateStart (
+  IN  IMX_I2C_CONFIG  *I2cConfigPtr,
+  IN  UINT8           RegisterAddress
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  IMX_I2C_I2CR_REG  I2crReg;
+  BOOLEAN           Result;
+  RETURN_STATUS     Status;
+
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+  Status = iMXI2cSetupController (I2cConfigPtr);
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStart: Fail to setup controller %r\n",
+            Status));
+    return Status;
+  }
+
+  // Set controller to transmit mode
+  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
+  I2crReg.MTX = 1;
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+
+  Result = iMXI2cSendByte (I2cConfigPtr, (I2cConfigPtr->SlaveAddress << 1));
+  if (Result == FALSE) {
+    DEBUG ((
+             DEBUG_ERROR,
+             "iMXI2cGenerateStart: Slave address transfer fail 0x%04x\n",
+             MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
+    return RETURN_DEVICE_ERROR;
+  }
+
+  // Send slave register address
+  Result = iMXI2cSendByte (I2cConfigPtr, RegisterAddress);
+  if (Result == FALSE) {
+    DEBUG ((
+             DEBUG_ERROR,
+             "iMXI2cGenerateStart: Slave register address transfer fail 0x%04x\n",
+             MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
+    return RETURN_DEVICE_ERROR;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+iMXI2cGenerateStop (
+  IN  IMX_I2C_CONFIG *I2cConfigPtr
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  IMX_I2C_I2CR_REG  I2crReg;
+
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
+  I2crReg.MSTA = 0;
+  I2crReg.MTX = 0;
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+
+  // Bus should go idle
+  if (iMXI2cWaitStatusUnSet (I2cConfigPtr, IMX_I2C_I2SR_IBB) == FALSE) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStop: Controller remains busy\n"));
+    return RETURN_DEVICE_ERROR;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Perform I2C read operation.
+
+  The iMXI2cRead perform I2C read operation by programming the I2C controller.
+  The caller is responsible to provide I2C controller configuration.
+
+  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
+                                  I2C controller to be used for I2C operation.
+  @param[in]    RegisterAddress   Targeted device register address to start read.
+  @param[out]   ReadBufferPtr     Caller supplied buffer that would be written
+                                  into with data from the read operation.
+  @param[in]    ReadBufferSize    Size of caller supplied buffer.
+
+  @retval   RETURN_SUCCESS        I2C Read operation succeeded.
+  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
+
+**/
+RETURN_STATUS
+iMXI2cRead (
+  IN IMX_I2C_CONFIG  *I2cConfigPtr,
+  IN UINT8            RegisterAddress,
+  OUT UINT8          *ReadBufferPtr,
+  IN UINT32           ReadBufferSize
+  )
+{
+  IMX_I2C_REGS      *I2cRegsPtr;
+  IMX_I2C_I2CR_REG  I2crReg;
+  BOOLEAN           Result;
+  RETURN_STATUS     Status;
+
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+  Status = iMXI2cGenerateStart (I2cConfigPtr, RegisterAddress);
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cRead: iMXI2cGenerateStart failed %r\n", Status));
+    goto Exit;
+  }
+
+  // Send slave address again to begin read
+  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
+  I2crReg.RSTA = 1; // Repeated start
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+  Result = iMXI2cSendByte (
+              I2cConfigPtr,
+              (I2cConfigPtr->SlaveAddress << 1 | 1));
+  if (Result == FALSE) {
+    DEBUG ((
+              DEBUG_ERROR,
+              "iMXI2cRead: 2nd Slave address transfer failed 0x%04x\n",
+              MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
+    Status = RETURN_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Disable master mode
+  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
+
+  // NXP application note AN4481 - Only one byte so do not send acknowledge
+  if (ReadBufferSize == 1) {
+    I2crReg.TXAK = 1;
+  } else {
+    I2crReg.TXAK = 0;
+  }
+
+  I2crReg.MTX = 0;
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+
+  // A data transfer can now be initiated by a read from I2C_I2DR in Slave
+  // Receive mode.
+  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
+  MmioRead16 ((UINTN)&I2cRegsPtr->I2DR);
+
+  do {
+    // Wait for transfer to complete
+    if (iMXI2cWaitStatusSet (I2cConfigPtr, IMX_I2C_I2SR_IIF) == FALSE) {
+      DEBUG ((DEBUG_ERROR, "iMXI2cRead: waiting for read fail\n"));
+      Status = RETURN_DEVICE_ERROR;
+      goto Exit;
+    }
+
+    if (iMXI2cWaitStatusSet (I2cConfigPtr, IMX_I2C_I2SR_ICF) == FALSE) {
+      DEBUG ((DEBUG_ERROR, "iMXI2cRead: waiting for read fail\n"));
+      Status = RETURN_DEVICE_ERROR;
+      goto Exit;
+    }
+
+    // Before the last byte is read, a Stop signal must be generated
+    if (ReadBufferSize == 1) {
+      Status = iMXI2cGenerateStop (
+                 I2cConfigPtr);
+      if (RETURN_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "iMXI2cRead: iMXI2cGenerateStop fail %r\n", Status));
+        goto Exit;
+      }
+    }
+
+    if (ReadBufferSize == 2) {
+      I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
+      I2crReg.TXAK = 1;
+      MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
+    }
+
+    MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
+
+    *ReadBufferPtr = MmioRead8 ((UINTN)&I2cRegsPtr->I2DR);
+    ++ReadBufferPtr;
+    --ReadBufferSize;
+  } while (ReadBufferSize > 0);
+
+Exit:
+  Status = iMXI2cGenerateStop (I2cConfigPtr);
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cRead: Final iMXI2cGenerateStop fail %r\n", Status));
+  }
+
+  return Status;
+}
+
+/**
+  Perform I2C write operation.
+
+  The iMXI2cWrite perform I2C write operation by programming the I2C
+  controller. The caller is responsible to provide I2C controller
+  configuration.
+
+  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
+                                  I2C controller to be used for I2C operation.
+  @param[in]    RegisterAddress   Targeted device register address to start write.
+  @param[out]   WriteBufferPtr    Caller supplied buffer that contained data that
+                                  would be read from for I2C write operation.
+  @param[in]    WriteBufferSize   Size of caller supplied buffer.
+
+  @retval   RETURN_SUCCESS        I2C Write operation succeeded.
+  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
+
+**/
+RETURN_STATUS
+iMXI2cWrite (
+  IN IMX_I2C_CONFIG  *I2cConfigPtr,
+  IN UINT8            RegisterAddress,
+  IN UINT8           *WriteBufferPtr,
+  IN UINT32           WriteBufferSize
+  )
+{
+  IMX_I2C_REGS    *I2cRegsPtr;
+  BOOLEAN         Result;
+  RETURN_STATUS   Status;
+
+  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
+  Status = iMXI2cGenerateStart (I2cConfigPtr, RegisterAddress);
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cWrite: iMXI2cGenerateStart fail %r\n", Status));
+    goto Exit;
+  }
+
+  while (WriteBufferSize > 0) {
+    Result = iMXI2cSendByte (I2cConfigPtr, *WriteBufferPtr);
+    if (Result == FALSE) {
+      DEBUG ((
+               DEBUG_ERROR,
+               "iMXI2cWrite: Slave address transfer fail 0x%04x\n",
+               MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
+      Status = RETURN_DEVICE_ERROR;
+      goto Exit;
+    }
+
+    ++WriteBufferPtr;
+    --WriteBufferSize;
+  }
+
+Exit:
+  Status = iMXI2cGenerateStop (I2cConfigPtr);
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "iMXI2cWrite: iMXI2cGenerateStop fail %r\n", Status));
+  }
+
+  return Status;
+}
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
new file mode 100644
index 000000000000..ad968e88b1da
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
@@ -0,0 +1,35 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMXI2cLib
+  FILE_GUID                      = C4E4A003-8AEB-4C9B-8E72-D2BAD2134BDE
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = iMXI2cLib
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  TimerLib
+
+[Sources.common]
+  iMXI2cLib.c
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (5 preceding siblings ...)
  2018-09-21  8:25 ` [PATCH edk2-platforms 06/27] Silicon/NXP: Add I2C " Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-11-01 18:05   ` Leif Lindholm
  2018-09-21  8:25 ` [PATCH edk2-platforms 08/27] Silicon/NXP: Add Virtual RTC support for i.MX platform Chris Co
                   ` (20 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for processing EDID data on NXP i.MX platforms.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h                    | 114 +++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c   | 152 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf |  31 ++++
 3 files changed, 297 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
new file mode 100644
index 000000000000..70ef8d0af97f
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
@@ -0,0 +1,114 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX_DISPLAY_H__
+#define __IMX_DISPLAY_H__
+
+#define EDID_MIN_SIZE       128
+#define EDID_I2C_ADDRESS    0x50
+
+// The first DTD is the preferred timing, refer to 3.1 VESA EDID spec.
+#define EDID_DTD_1_OFFSET   0x36
+#define EDID_DTD_2_OFFSET   0x48
+#define EDID_DTD_3_OFFSET   0x5A
+#define EDID_DTD_4_OFFSET   0x6C
+
+typedef enum {
+  PIXEL_FORMAT_ARGB32,
+  PIXEL_FORMAT_BGRA32,
+} PIXEL_FORMAT;
+
+typedef struct _DISPLAY_TIMING {
+  UINT32 PixelClock;
+  UINT32 HActive;
+  UINT32 HBlank;
+  UINT32 VActive;
+  UINT32 VBlank;
+  UINT32 HSync;
+  UINT32 VSync;
+  UINT32 HSyncOffset;
+  UINT32 VSyncOffset;
+  UINT32 HImageSize;
+  UINT32 VImageSize;
+  UINT32 HBorder;
+  UINT32 VBorder;
+  UINT32 EdidFlags;
+  UINT32 Flags;
+  UINT32 PixelRepetition;
+  UINT32 Bpp;
+  PIXEL_FORMAT PixelFormat;
+} DISPLAY_TIMING, *PDISPLAY_TIMING, DTD;
+
+typedef struct _DETAILED_TIMING_DESCRIPTOR {
+  UINT8 PixelClock[2];
+  UINT8 HActive;
+  UINT8 HBlank;
+  UINT8 HActiveBlank;
+  UINT8 VActive;
+  UINT8 VBlank;
+  UINT8 VActiveBlank;
+  UINT8 HSyncOffset;
+  UINT8 HSyncWidth;
+  UINT8 VSyncOffsetWidth;
+  UINT8 HVOffsetWidth;
+  UINT8 HImageSize;
+  UINT8 VImageSize;
+  UINT8 HVImageSize;
+  UINT8 HBorder;
+  UINT8 VBorder;
+  UINT8 EdidFlags;
+} DETAILED_TIMING_DESCRIPTOR, *PDETAILED_TIMING_DESCRIPTOR;
+
+/**
+  Convert detailed timing descriptor to display timing format
+
+  @param[in]    DTDPtr            Pointer to detailed timing descriptor.
+  @param[out]   DisplayTimingPtr  Pointer to display timing structure.
+
+  @retval   EFI_SUCCESS   Detailed timing descriptor data was converted.
+
+**/
+EFI_STATUS
+ConvertDTDToDisplayTiming (
+  IN DETAILED_TIMING_DESCRIPTOR   *DTDPtr,
+  OUT DISPLAY_TIMING              *DisplayTimingPtr
+  );
+
+/**
+  Debug dump of Display Timing structure
+
+  @param[in]    DisplayTimingNamePtr  Name of display timing structure.
+  @param[in]    DisplayTimingPtr      Pointer to display timing structure.
+**/
+VOID
+PrintDisplayTiming (
+  IN CHAR8            *DisplayTimingNamePtr,
+  IN DISPLAY_TIMING   *DisplayTimingPtr
+  );
+
+/**
+  Check if EDID is valid
+
+  @param[in]    EdidDataPtr  Pointer to EDID data.
+
+  @retval   EFI_SUCCESS             EDID data is a valid EDID.
+  @retval   EFI_INVALID_PARAMETER   EDID data is invalid.
+
+**/
+EFI_STATUS
+ValidateEdidData (
+  IN UINT8 *EdidDataPtr
+  );
+
+#endif // __IMX_DISPLAY_H__
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
new file mode 100644
index 000000000000..9e90ece96260
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
@@ -0,0 +1,152 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+
+#include <iMXDisplay.h>
+
+/**
+  Convert detailed timing descriptor to display timing format
+
+  @param[in]    DTDPtr            Pointer to detailed timing descriptor.
+  @param[out]   DisplayTimingPtr  Pointer to display timing structure.
+
+  @retval   EFI_SUCCESS   Detailed timing descriptor data was converted.
+
+**/
+EFI_STATUS
+ConvertDTDToDisplayTiming (
+  IN DETAILED_TIMING_DESCRIPTOR   *DTDPtr,
+  OUT DISPLAY_TIMING              *DisplayTimingPtr
+  )
+{
+  UINT32  edidPixelClock;
+
+  DEBUG ((DEBUG_INFO, "++ConvertDTDToDisplayTiming()\r\n"));
+  // Refer to 3.10.2 VESA EDID spec
+  edidPixelClock = (DTDPtr->PixelClock[0] | (DTDPtr->PixelClock[1] << 8));
+  DisplayTimingPtr->PixelClock = edidPixelClock * 10000;
+  DisplayTimingPtr->HActive = (DTDPtr->HActiveBlank & 0xF0);
+  DisplayTimingPtr->HActive = (DisplayTimingPtr->HActive << 4) | DTDPtr->HActive;
+  DisplayTimingPtr->HBlank = (DTDPtr->HActiveBlank & 0x0F);
+  DisplayTimingPtr->HBlank = (DisplayTimingPtr->HBlank << 8) | DTDPtr->HBlank;
+  DisplayTimingPtr->VActive = (DTDPtr->VActiveBlank & 0xF0);
+  DisplayTimingPtr->VActive = (DisplayTimingPtr->VActive << 4) | DTDPtr->VActive;
+  DisplayTimingPtr->VBlank = (DTDPtr->VActiveBlank & 0x0F);
+  DisplayTimingPtr->VBlank = (DisplayTimingPtr->VBlank << 8) | DTDPtr->VBlank;
+  DisplayTimingPtr->HSyncOffset = (DTDPtr->HVOffsetWidth & 0xC0);
+  DisplayTimingPtr->HSyncOffset = (DisplayTimingPtr->HSyncOffset << 2) |
+                                  DTDPtr->HSyncOffset;
+  DisplayTimingPtr->VSyncOffset = (DTDPtr->HVOffsetWidth & 0x0C);
+  DisplayTimingPtr->VSyncOffset = (DisplayTimingPtr->VSyncOffset << 2) |
+                                  ((DTDPtr->VSyncOffsetWidth & 0xF0) >> 4);
+  DisplayTimingPtr->HSync = (DTDPtr->HVOffsetWidth & 0x30);
+  DisplayTimingPtr->HSync = (DisplayTimingPtr->HSync << 4) | DTDPtr->HSyncWidth;
+  DisplayTimingPtr->VSync = (DTDPtr->HVOffsetWidth & 0x03);
+  DisplayTimingPtr->VSync = (DisplayTimingPtr->VSync << 4) |
+                            (DTDPtr->VSyncOffsetWidth & 0x0F);
+  DisplayTimingPtr->HImageSize = ((DTDPtr->HVImageSize & 0xF0) << 4) |
+                                 DTDPtr->HImageSize;
+  DisplayTimingPtr->VImageSize = ((DTDPtr->HVImageSize & 0x0F) << 8) |
+                                 DTDPtr->VImageSize;
+  DisplayTimingPtr->HBorder = DTDPtr->HBorder;
+  DisplayTimingPtr->VBorder = DTDPtr->VBorder;
+  DisplayTimingPtr->EdidFlags = DTDPtr->EdidFlags;
+  DisplayTimingPtr->Flags = 0;
+
+  DEBUG ((DEBUG_INFO, "--ConvertDTDToDisplayTiming()=ok\r\n"));
+  return EFI_SUCCESS;
+}
+
+/**
+  Debug dump of Display Timing structure
+
+  @param[in]    DisplayTimingNamePtr  Name of display timing structure.
+  @param[in]    DisplayTimingPtr      Pointer to display timing structure.
+**/
+VOID
+PrintDisplayTiming (
+  IN CHAR8            *DisplayTimingNamePtr,
+  IN DISPLAY_TIMING   *DisplayTimingPtr
+  )
+{
+  DEBUG ((DEBUG_INFO, "**********************\n"));
+  DEBUG ((DEBUG_INFO, "%a\n", DisplayTimingNamePtr));
+  DEBUG ((DEBUG_INFO, "**********************\n"));
+  DEBUG ((DEBUG_INFO, "PixelClock %d\n", DisplayTimingPtr->PixelClock));
+  DEBUG ((DEBUG_INFO, "HActive %d\n", DisplayTimingPtr->HActive));
+  DEBUG ((DEBUG_INFO, "HBlank %d\n", DisplayTimingPtr->HBlank));
+  DEBUG ((DEBUG_INFO, "VActive %d\n", DisplayTimingPtr->VActive));
+  DEBUG ((DEBUG_INFO, "VBlank %d\n", DisplayTimingPtr->VBlank));
+  DEBUG ((DEBUG_INFO, "HSync %d\n", DisplayTimingPtr->HSync));
+  DEBUG ((DEBUG_INFO, "VSync %d\n", DisplayTimingPtr->VSync));
+  DEBUG ((DEBUG_INFO, "HSyncOffset %d\n", DisplayTimingPtr->HSyncOffset));
+  DEBUG ((DEBUG_INFO, "VSyncOffset %d\n", DisplayTimingPtr->VSyncOffset));
+  DEBUG ((DEBUG_INFO, "HBorder %d\n", DisplayTimingPtr->HBorder));
+  DEBUG ((DEBUG_INFO, "VBorder %d\n", DisplayTimingPtr->VBorder));
+  DEBUG ((DEBUG_INFO, "EdidFlags %d\n", DisplayTimingPtr->EdidFlags));
+  DEBUG ((DEBUG_INFO, "Flags %d\n", DisplayTimingPtr->Flags));
+  DEBUG ((DEBUG_INFO, "PixelRepetition %d\n", DisplayTimingPtr->PixelRepetition));
+  DEBUG ((DEBUG_INFO, "BPP %d\n", DisplayTimingPtr->Bpp));
+  DEBUG ((DEBUG_INFO, "PixelFormat %d\n", DisplayTimingPtr->PixelFormat));
+  DEBUG ((DEBUG_INFO, "**********************\n"));
+}
+
+/**
+  Check if EDID is valid
+
+  @param[in]    EdidDataPtr  Pointer to EDID data.
+
+  @retval   EFI_SUCCESS             EDID data is a valid EDID.
+  @retval   EFI_INVALID_PARAMETER   EDID data is invalid.
+
+**/
+EFI_STATUS
+ValidateEdidData (
+  IN UINT8 *EdidDataPtr
+  )
+{
+  UINT8   Checksum;
+  UINT8   Index;
+
+  DEBUG ((DEBUG_INFO, "++ValidateEdidData()\r\n"));
+
+  if (EdidDataPtr[0] != 0x00 ||
+      EdidDataPtr[1] != 0xFF ||
+      EdidDataPtr[2] != 0xFF ||
+      EdidDataPtr[3] != 0xFF ||
+      EdidDataPtr[4] != 0xFF ||
+      EdidDataPtr[5] != 0xFF ||
+      EdidDataPtr[6] != 0xFF ||
+      EdidDataPtr[7] != 0x00) {
+    DEBUG ((DEBUG_ERROR, "Invalid EDID header\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Validate EDID checksum
+  Checksum = 0;
+  for (Index = 0; Index < EDID_MIN_SIZE; Index++) {
+    Checksum += EdidDataPtr[Index];
+  }
+
+  if (Checksum != 0) {
+    DEBUG ((DEBUG_ERROR, "Invalid EDID checksum\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "--ValidateEdidData()=ok\r\n"));
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
new file mode 100644
index 000000000000..bd77d4159639
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
@@ -0,0 +1,31 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMXDisplayLib
+  FILE_GUID                      = C0408490-F09B-4CFA-9A2F-5159F2705323
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = iMXDisplayLib
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+
+[Sources.common]
+  iMXDisplayLib.c
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 08/27] Silicon/NXP: Add Virtual RTC support for i.MX platform
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (6 preceding siblings ...)
  2018-09-21  8:25 ` [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support Chris Co
@ 2018-09-21  8:25 ` Chris Co
  2018-12-15 13:26   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 10/27] Silicon/NXP: Add iMX6Pkg dec Chris Co
                   ` (19 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:25 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds a virtual RTC library that implements EFI RTC runtime services
based on the ARM performance counter.  It should only be used for relative
time measurement, such as for Windows Boot Manager.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c   | 227 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf |  37 ++++
 2 files changed, 264 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
new file mode 100644
index 000000000000..771c1d7a8f9c
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
@@ -0,0 +1,227 @@
+/** @file
+*
+*  Implement EFI RealTimeClock runtime services based on ARM Performance Counter.
+*
+*  Currently this driver does not support time setting, alarms, or runtime calls.
+*  This special library is NOT meant to replace a HW RTC implementation to
+*  measure date/time. Use this library ONLY to measure relative time between
+*  two EFI_GET_TIME readings.
+*  The performance counter will wrap-around eventually after a long time, make
+*  sure to consider this limitation if you are depending on this library for
+*  relative time measurement. e.g. For the ARM 64-bit counter with 19.2MHz
+*  frequency, the counter will wrap-around after approximately 30465 year.
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/RealTimeClockLib.h>
+#include <Library/TimerLib.h>
+
+#define LOG_FMT_HELPER(FMT, ...) \
+    "VirtualRealTimeClock:" FMT "%a\n", __VA_ARGS__
+
+#define LOG_TRACE(...) \
+    DEBUG((DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
+
+/**
+  Returns the current time and date information, and the time-keeping capabilities
+  of the virtual RTC.
+
+  For simplicity, this LibGetTime does not report Years/Months, instead it will
+  only report current Day, Hours, Minutes and Seconds starting from the beginning
+  of CPU up-time. Otherwise, a more complex logic will be required to account
+  for leap years and days/month differences.
+
+  @param  Time                  A pointer to storage to receive a snapshot of
+                                the current time.
+  @param  Capabilities          An optional pointer to a buffer to receive the
+                                real time clock device's capabilities.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER Time is NULL.
+  @retval EFI_DEVICE_ERROR      The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+  OUT EFI_TIME *Time,
+  OUT EFI_TIME_CAPABILITIES *Capabilities
+  )
+{
+  UINT64 ElapsedSeconds;
+  UINT64 TimerFreq;
+
+  if (Time == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Depend on ARM ARCH Timer (i.e. performance counter) to report date/time
+  // relative to the start of CPU timer counting where date and time will always
+  // be relative to the date/time 1/1/1900 00H:00M:00S
+  if (PcdGet32 (PcdArmArchTimerFreqInHz) > 0) {
+    TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz);
+  } else {
+    TimerFreq = GetPerformanceCounterProperties (NULL, NULL);
+  }
+
+  ASSERT (TimerFreq > 0);
+  if (TimerFreq == 0) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (Capabilities) {
+    Capabilities->Accuracy = 0;
+    Capabilities->Resolution = TimerFreq;
+    Capabilities->SetsToZero = FALSE;
+  }
+
+  ElapsedSeconds = GetPerformanceCounter () / TimerFreq;
+
+  // Don't report Year/Month since Leap Year logic is not implemented. This should
+  // be fine since the sole purpose of this special implementation is to be
+  // used for relative time measurement. e.g. Windows Boot Manager.
+  Time->Year = 0;
+  Time->Month = 0;
+
+  CONST UINT64 SECONDS_PER_DAY = 24 * 60 * 60;
+  Time->Day = (ElapsedSeconds / SECONDS_PER_DAY);
+  ElapsedSeconds %= SECONDS_PER_DAY;
+
+  CONST UINT64 SECONDS_PER_HOUR = 60 * 60;
+  Time->Hour = (ElapsedSeconds / SECONDS_PER_HOUR);
+  ElapsedSeconds %= SECONDS_PER_HOUR;
+
+  CONST UINT64 SECONDS_PER_MINUTE = 60;
+  Time->Minute = (ElapsedSeconds / SECONDS_PER_MINUTE);
+  ElapsedSeconds %= SECONDS_PER_MINUTE;
+
+  Time->Second = ElapsedSeconds;
+  Time->Nanosecond = 0;
+  Time->TimeZone = 0;
+  Time->Daylight = 0;
+
+  LOG_TRACE (
+    "Time Elapsed Since Power-On: Day%d %dh:%dm:%ds",
+    (UINT32)Time->Day,
+    (UINT32)Time->Hour,
+    (UINT32)Time->Minute,
+    (UINT32)Time->Second);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets the current local time and date information.
+
+  @param  Time                  A pointer to the current time.
+
+  @retval EFI_UNSUPPORTED      This operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+  IN EFI_TIME *Time
+  )
+{
+  // The virtual clock is read-only.
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Returns the current wakeup alarm clock setting.
+
+  @param  Enabled               Indicates if the alarm is currently enabled or
+                                disabled.
+  @param  Pending               Indicates if the alarm signal is pending and
+                                requires acknowledgement.
+  @param  Time                  The current alarm setting.
+
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+  OUT BOOLEAN *Enabled,
+  OUT BOOLEAN *Pending,
+  OUT EFI_TIME *Time
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Sets the system wakeup alarm clock time.
+
+  @param  Enabled               Enable or disable the wakeup alarm.
+  @param  Time                  If Enable is TRUE, the time to set the wakeup alarm for.
+
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+  IN BOOLEAN Enabled,
+  OUT EFI_TIME *Time
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This can be the entry point
+  to an application written to this specification, an EFI boot service driver,
+  or an EFI runtime driver.
+
+  @param  ImageHandle           Handle that identifies the loaded image.
+  @param  SystemTable           System Table for this image.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+  IN EFI_HANDLE ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  // ARM ARCH Timer is already initialized in the SEC/PEI phase.
+  return EFI_SUCCESS;
+}
+
+/**
+  Fixup internal data so that EFI can be call in virtual mode.
+  Call the passed in Child Notify event and convert any pointers in
+  lib to virtual mode.
+
+  @param[in]    Event   The Event that is being processed
+  @param[in]    Context Event Context
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+  IN EFI_EVENT Event,
+  IN VOID *Context
+  )
+{
+  // Not supporting OS calling RTC functions in virtual mode.
+  return;
+}
diff --git a/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
new file mode 100644
index 000000000000..54aacde8c741
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
@@ -0,0 +1,37 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = VirtualRealTimeClockLib
+  FILE_GUID                      = 1E27D461-78F3-4F7D-B1C2-F72384F13A6E
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = RealTimeClockLib
+
+[Sources.common]
+  VirtualRealTimeClockLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  DebugLib
+  IoLib
+  TimerLib
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (8 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 10/27] Silicon/NXP: Add iMX6Pkg dec Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-11-01 18:20   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 11/27] Silicon/NXP: Add i.MX6 SoC header files Chris Co
                   ` (17 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds common headers for other NXP i.MX SoC packages.
More specifically, this adds i.MX-generic GPIO, IoMux, and
Platform definitions.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/Include/Platform.h | 67 ++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h  | 92 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h | 24 +++++
 3 files changed, 183 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Include/Platform.h b/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
new file mode 100644
index 000000000000..8a1e828f68ea
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
@@ -0,0 +1,67 @@
+/** @file
+*
+*  i.MX Platform specific defines for constructing ACPI tables
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _PLATFORM_IMX_H_
+#define _PLATFORM_IMX_H_
+
+#include <IndustryStandard/Acpi50.h>
+
+#define EFI_ACPI_OEM_ID               {'M','C','R','S','F','T'} // OEMID 6 bytes
+#define EFI_ACPI_VENDOR_ID            SIGNATURE_32('N','X','P','I')
+#define EFI_ACPI_CSRT_REVISION        0x00000005
+#define EFI_ACPI_5_0_CSRT_REVISION    0x00000000
+
+// Resource Descriptor Types
+#define EFI_ACPI_CSRT_RD_TYPE_INTERRUPT 1
+#define EFI_ACPI_CSRT_RD_TYPE_TIMER 2
+#define EFI_ACPI_CSRT_RD_TYPE_DMA 3
+#define EFI_ACPI_CSRT_RD_TYPE_CACHE 4
+
+// Resource Descriptor Subtypes
+#define EFI_ACPI_CSRT_RD_SUBTYPE_INTERRUPT_LINES 0
+#define EFI_ACPI_CSRT_RD_SUBTYPE_INTERRUPT_CONTROLLER 1
+#define EFI_ACPI_CSRT_RD_SUBTYPE_TIMER 0
+#define EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CHANNEL 0
+#define EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CONTROLLER 1
+#define EFI_ACPI_CSRT_RD_SUBTYPE_CACHE 0
+
+#pragma pack(push, 1)
+//------------------------------------------------------------------------
+// CSRT Resource Group header 24 bytes long
+//------------------------------------------------------------------------
+typedef struct {
+  UINT32 Length;
+  UINT32 VendorID;
+  UINT32 SubVendorId;
+  UINT16 DeviceId;
+  UINT16 SubdeviceId;
+  UINT16 Revision;
+  UINT16 Reserved;
+  UINT32 SharedInfoLength;
+} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER;
+
+//------------------------------------------------------------------------
+// CSRT Resource Descriptor 12 bytes total
+//------------------------------------------------------------------------
+typedef struct {
+  UINT32 Length;
+  UINT16 ResourceType;
+  UINT16 ResourceSubType;
+  UINT32 UID;
+} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER;
+#pragma pack (pop)
+
+#endif // !_PLATFORM_IMX_H_
diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
new file mode 100644
index 000000000000..dce01f789058
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
@@ -0,0 +1,92 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX_GPIO_H_
+#define _IMX_GPIO_H_
+
+#include <Library/PcdLib.h>
+
+typedef enum {
+  IMX_GPIO_LOW = 0,
+  IMX_GPIO_HIGH = 1
+} IMX_GPIO_VALUE;
+
+typedef enum {
+  IMX_GPIO_DIR_INPUT,
+  IMX_GPIO_DIR_OUTPUT
+} IMX_GPIO_DIR;
+
+typedef enum {
+  IMX_GPIO_BANK1 = 1,
+  IMX_GPIO_BANK2,
+  IMX_GPIO_BANK3,
+  IMX_GPIO_BANK4,
+  IMX_GPIO_BANK5,
+  IMX_GPIO_BANK6,
+  IMX_GPIO_BANK7,
+} IMX_GPIO_BANK;
+
+#pragma pack(push, 1)
+
+#define GPIO_RESERVED_SIZE \
+    ((FixedPcdGet32(PcdGpioBankMemoryRange) / 4) - 8)
+
+typedef struct {
+  UINT32 DR;                            // 0x00 GPIO data register (GPIO1_DR)
+  UINT32 GDIR;                          // 0x04 GPIO direction register (GPIO1_GDIR)
+  UINT32 PSR;                           // 0x08 GPIO pad status register (GPIO1_PSR)
+  UINT32 ICR1;                          // 0x0C GPIO interrupt configuration register1 (GPIO1_ICR1)
+  UINT32 ICR2;                          // 0x10 GPIO interrupt configuration register2 (GPIO1_ICR2)
+  UINT32 IMR;                           // 0x14 GPIO interrupt mask register (GPIO1_IMR)
+  UINT32 ISR;                           // 0x18 GPIO interrupt status register (GPIO1_ISR)
+  UINT32 EDGE_SEL;                      // 0x1C GPIO edge select register (GPIO1_EDGE_SEL)
+  UINT32 reserved[GPIO_RESERVED_SIZE];
+} IMX_GPIO_BANK_REGISTERS;
+
+#pragma pack(pop)
+
+typedef struct {
+  IMX_GPIO_BANK_REGISTERS Banks[7];
+} IMX_GPIO_REGISTERS;
+
+/**
+    Set the specified GPIO to the specified direction.
+**/
+VOID
+ImxGpioDirection (
+  IMX_GPIO_BANK Bank,
+  UINT32 IoNumber,
+  IMX_GPIO_DIR Direction
+  );
+
+/**
+    Write a value to a GPIO pin.
+**/
+VOID
+ImxGpioWrite (
+  IMX_GPIO_BANK Bank,
+  UINT32 IoNumber,
+  IMX_GPIO_VALUE Value
+  );
+
+/**
+    Read a GPIO pin input value.
+**/
+IMX_GPIO_VALUE
+ImxGpioRead (
+  IMX_GPIO_BANK Bank,
+  UINT32 IoNumber
+  );
+
+#endif
diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
new file mode 100644
index 000000000000..7696af57d7ea
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
@@ -0,0 +1,24 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX_IO_MUX_H_
+#define _IMX_IO_MUX_H_
+
+#define _IMX_PAD(CtlRegOffset, MuxRegOffset) \
+  ((((CtlRegOffset) & 0xffff) << 16) | ((MuxRegOffset) & 0xffff))
+
+#define _IMX_PAD_CTL_OFFSET(ImxPadVal) ((ImxPadVal) >> 16)
+#define _IMX_PAD_MUX_OFFSET(ImxPadVal) ((ImxPadVal) & 0xffff)
+
+#endif // _IMX_IO_MUX_H_
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 10/27] Silicon/NXP: Add iMX6Pkg dec
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (7 preceding siblings ...)
  2018-09-21  8:25 ` [PATCH edk2-platforms 08/27] Silicon/NXP: Add Virtual RTC support for i.MX platform Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-11-01 18:25   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use Chris Co
                   ` (18 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds PCD declarations common across NXP i.MX6 SoCs

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/iMX6Pkg.dec | 143 ++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/iMX6Pkg.dec b/Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
new file mode 100644
index 000000000000..99e1c7e6a4b8
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
@@ -0,0 +1,143 @@
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = iMX6Pkg
+  PACKAGE_GUID                   = 6eba6648-d853-4eb3-9761-528b82d5ab04
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+#  DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+  Include                        # Root include for the package
+  Silicon/NXP/iMXPlatformPkg/Include      # Root include for the iMXPlatform package
+
+[LibraryClasses]
+  iMXIoMuxLib|Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
+  iMX6ClkPwrLib|Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
+  iMX6UsbPhyLib|Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
+
+[Protocols.common]
+  gEfiSdhcProtocolGuid = { 0x46055b0f, 0x992a, 0x4ad7, { 0x8f, 0x81, 0x14, 0x81, 0x86, 0xff, 0xdf, 0x72 } }
+
+[Guids.common]
+  giMX6TokenSpaceGuid = { 0x24b09abe, 0x4e47, 0x481c, { 0xa9, 0xad, 0xce, 0xf1, 0x2c, 0x39, 0x23, 0x27} }
+
+[PcdsFixedAtBuild.common]
+  #
+  # Frame buffer is set to the first addressable memory on the i.MX6
+  # Sabre board for convenience.
+  # Keep in mind that this chunk of memory is the only one that remains fixed
+  # through the various boot stages (primary boot->UEFI->Windows.
+  #
+  giMX6TokenSpaceGuid.PcdFrameBufferBase|0x10000000|UINT32|0x0000000A
+  giMX6TokenSpaceGuid.PcdFrameBufferSize|0x00800000|UINT32|0x0000000B
+
+  #
+  # Performance counter
+  #
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterFrequencyInHz|1000000|UINT32 |0xC
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|1000|UINT32 |0xD
+
+  #
+  # USB EHCI Controller
+  #
+  giMX6TokenSpaceGuid.PcdEHCIBase|0x02184000|UINT32|0xE
+  giMX6TokenSpaceGuid.PcdEHCILength|0x4000|UINT32|0xF
+  giMX6TokenSpaceGuid.PcdIsUsbPortOTG|TRUE|BOOLEAN|0x10
+  giMX6TokenSpaceGuid.PcdUSBOTGBase|0x02184000|UINT32|0x11
+
+  #
+  # ARM System Reset Controller (SRC)
+  #
+  giMX6TokenSpaceGuid.PcdSrcBase|0x020D8000|UINT32|0x2B
+
+  #
+  # PCIE
+  #
+  # PCI Host config space is fixed at 0x01FFC000. The memory range from
+  # 0x01000000 - 0x01FFBFFF is assigned for PCIe. The memory layout defined
+  # by the boot loader is as below
+  #
+  # PCIe Device Config Space : 0x01F00000 - 0x01F80000
+  # PCIe IO (unsupported) : 0x01100000 - 0x011FFFFF
+  # PCIe Memory : 0x01200000 - 0x012FFFFF
+  #
+  giMX6TokenSpaceGuid.PcdPcieDeviceConfigBase|0x01F00000|UINT32|0x2C
+  giMX6TokenSpaceGuid.PcdPcieDeviceConfigSize|0x00080000|UINT32|0x2D
+  giMX6TokenSpaceGuid.PcdPcieHostConfigBase|0x01FFC000|UINT32|0x2E
+  giMX6TokenSpaceGuid.PcdPcieIOBase|0x00000000|UINT32|0x2F
+  giMX6TokenSpaceGuid.PcdPcieIOSize|0x00000000|UINT32|0x30
+  giMX6TokenSpaceGuid.PcdPciMemoryBase|0x01100000|UINT32|0x31
+  giMX6TokenSpaceGuid.PcdPciMemorySize|0x00D00000|UINT32|0x32
+  giMX6TokenSpaceGuid.PcdPciPrefetchMemoryBase|0x00000000|UINT32|0x33
+  giMX6TokenSpaceGuid.PcdPciPrefetchMemorySize|0x00000000|UINT32|0x34
+  giMX6TokenSpaceGuid.PcdPcieResetGpio|FALSE|BOOLEAN|0x35
+  giMX6TokenSpaceGuid.PcdPcieResetGpioBankNumber|0|UINT32|0x36
+  giMX6TokenSpaceGuid.PcdPcieResetGpioIoNumber|0|UINT32|0x37
+
+  #
+  # SMBIOS Type1
+  #
+  giMX6TokenSpaceGuid.PcdSystemFamily|L""|VOID*|0x38
+  giMX6TokenSpaceGuid.PcdSystemManufacturer|L""|VOID*|0x39
+  giMX6TokenSpaceGuid.PcdSystemProductName|L""|VOID*|0x3A
+  giMX6TokenSpaceGuid.PcdSystemSkuNumber|L""|VOID*|0x3B
+  giMX6TokenSpaceGuid.PcdSystemVersionNumber|L""|VOID*|0x3C
+  giMX6TokenSpaceGuid.PcdSystemUuid|{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}|VOID*|0x3D
+
+  #
+  # SMBIOS Type2
+  #
+  giMX6TokenSpaceGuid.PcdBoardAssetTag|L""|VOID*|0x3E
+  giMX6TokenSpaceGuid.PcdBoardLocationInChassis|L""|VOID*|0x3F
+  giMX6TokenSpaceGuid.PcdBoardManufacturer|L""|VOID*|0x40
+  giMX6TokenSpaceGuid.PcdBoardProductName|L""|VOID*|0x41
+  giMX6TokenSpaceGuid.PcdBoardVersionNumber|L""|VOID*|0x42
+
+  #
+  # SMBIOS Type3
+  #
+  giMX6TokenSpaceGuid.PcdChassisAssetTag|L""|VOID*|0x43
+  giMX6TokenSpaceGuid.PcdChassisManufacturer|L""|VOID*|0x44
+  giMX6TokenSpaceGuid.PcdChassisVersionNumber|L""|VOID*|0x45
+
+  # SMBIOS Type4
+  giMX6TokenSpaceGuid.PcdProcessorAssetTag|L""|VOID*|0x46
+  giMX6TokenSpaceGuid.PcdProcessorManufacturer|L""|VOID*|0x47
+  giMX6TokenSpaceGuid.PcdProcessorPartNumber|L""|VOID*|0x48
+  giMX6TokenSpaceGuid.PcdProcessorSocketDesignation|L""|VOID*|0x49
+  giMX6TokenSpaceGuid.PcdProcessorVersionNumber|L""|VOID*|0x4A
+
+  # SMBIOS Type16
+  giMX6TokenSpaceGuid.PcdPhysicalMemoryMaximumCapacity|0x0|UINT32|0x4B
+
+  # SMBIOS Type17
+  giMX6TokenSpaceGuid.PcdMemoryBankLocation|L""|VOID*|0x4C
+  giMX6TokenSpaceGuid.PcdMemoryDeviceLocation|L""|VOID*|0x4D
+
+  # SMBIOS Type19
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x0|UINT32|0x4E
+  giMX6TokenSpaceGuid.PcdMemoryStartAddress|0x0|UINT32|0x4F
+
+[PcdsFeatureFlag.common]
+  giMX6TokenSpaceGuid.PcdGpuEnable|FALSE|BOOLEAN|0x00001000
+  giMX6TokenSpaceGuid.PcdLvdsEnable|FALSE|BOOLEAN|0x00001001
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 11/27] Silicon/NXP: Add i.MX6 SoC header files
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (9 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-13 17:11   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library Chris Co
                   ` (16 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds includes for NXP i.MX6 SoC family, specifically Dual/Quad,
Solo/DualLite, SoloX, DualPlus/QuadPlus families.
These are the header files for managing clocks, IoMux, and general
SoC register layout information.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Include/iMX6.h           |   39 +
 Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h   |   55 +
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h     |  105 +
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h  |  181 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h |  176 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h  |  190 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h      |  202 ++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h  | 2466 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h  | 1875 +++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h   | 2270 ++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h        |  332 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h       |  335 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h       |  301 +++
 Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h        | 1730 ++++++++++++++
 Silicon/NXP/iMX6Pkg/Include/iMX6_common.h    | 1350 +++++++++++
 15 files changed, 11607 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6.h b/Silicon/NXP/iMX6Pkg/Include/iMX6.h
new file mode 100644
index 000000000000..ded03eced048
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6.h
@@ -0,0 +1,39 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX6_H__
+#define __IMX6_H__
+
+// Platform specific definition
+#define EFI_ACPI_OEM_TABLE_ID      SIGNATURE_64('I','M','X','6','E','D','K','2')
+#define EFI_ACPI_OEM_REVISION      0x01000101
+#define EFI_ACPI_CREATOR_ID        SIGNATURE_32('I','M','X','6')
+#define EFI_ACPI_CREATOR_REVISION  0x00000001
+
+#if defined(CPU_IMX6DQ)
+#include "iMX6_DQ.h"
+#elif defined(CPU_IMX6DQP)
+#include "iMX6_DQP.h"
+#elif defined(CPU_IMX6SDL)
+#include "iMX6_SDL.h"
+#elif defined(CPU_IMX6SX)
+#include "iMX6_SX.h"
+#else
+#error iMX6 CPU Type Not Defined! (Preprocessor Flag)
+#endif
+
+#define SERIAL_DEBUG_PORT_INIT_MSG "\r\nDebug Serial Port Init\r\n"
+#define SERIAL_PORT_INIT_MSG "UART"
+
+#endif // __IMX6_H__
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h b/Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
new file mode 100644
index 000000000000..7997ebc72897
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
@@ -0,0 +1,55 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_BOARD_LIB_H_
+#define _IMX6_BOARD_LIB_H_
+
+/*
+  Mandatory functions to implement by the board library.
+*/
+
+VOID
+ImxClkPwrInit (
+  );
+
+/*
+  Optional functions to implement by the board library.
+  The default implementation of these functions if not overridden is NOOP.
+*/
+
+VOID
+SdhcInit (
+  );
+
+VOID
+EhciInit (
+  );
+
+VOID
+I2cInit (
+  );
+
+VOID
+SpiInit (
+  );
+
+VOID
+PcieInit (
+  );
+
+VOID
+SetupAudio (
+  );
+
+#endif // _IMX6_BOARD_LIB_H_
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
new file mode 100644
index 000000000000..18262751c443
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
@@ -0,0 +1,105 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_CLK_PWR_H_
+#define _IMX6_CLK_PWR_H_
+
+// The valid value for PLL loop divider is 27-54 so define the range of valid
+// frequency for PLL5 below before divider is applied.
+#define PLL5_MIN_FREQ 648000000
+#define PLL5_MAX_FREQ 1296000000
+
+#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
+#include "iMX6ClkPwr_DQ.h"
+#elif defined(CPU_IMX6SDL)
+#include "iMX6ClkPwr_SDL.h"
+#elif defined(CPU_IMX6SX)
+#include "iMX6ClkPwr_SX.h"
+#else
+#error iMX6 CPU Type Not Defined!
+#endif
+
+typedef enum {
+  IMX_CLOCK_GATE_STATE_OFF = 0x0,
+  IMX_CLOCK_GATE_STATE_ON_RUN = 0x1,
+  IMX_CLOCK_GATE_STATE_ON = 0x3,
+} IMX_CLOCK_GATE_STATE;
+
+typedef struct {
+  UINT32 Frequency;
+  IMX_CLK Parent;
+} IMX_CLOCK_INFO;
+
+VOID
+ImxClkPwrSetClockGate (
+  IN IMX_CLK_GATE ClockGate,
+  IN IMX_CLOCK_GATE_STATE State
+  );
+
+// Set multiple clock gates to a given state
+VOID
+ImxClkPwrSetClockGates (
+  IN CONST IMX_CLK_GATE *ClockGateList,
+  IN UINTN ClockGateCount,
+  IN IMX_CLOCK_GATE_STATE State
+  );
+
+IMX_CLOCK_GATE_STATE
+ImxClkPwrGetClockGate (
+  IN IMX_CLK_GATE ClockGate
+  );
+
+EFI_STATUS
+ImxClkPwrGetClockInfo (
+  IN IMX_CLK ClockId,
+  OUT IMX_CLOCK_INFO *ClockInfo
+);
+
+EFI_STATUS
+ImxClkPwrGpuEnable (
+  );
+
+EFI_STATUS
+ImxClkPwrIpuDIxEnable (
+  );
+
+EFI_STATUS ImxClkPwrIpuLDBxEnable (
+  );
+
+EFI_STATUS
+ImxSetPll5ReferenceRate (
+  UINT32 ClockRate
+  );
+
+EFI_STATUS
+ImxClkPwrClkOut1Enable (
+  IMX_CLK Clock,
+  UINT32 Divider
+  );
+
+VOID
+ImxClkPwrClkOut1Disable (
+  );
+
+EFI_STATUS
+ImxClkPwrValidateClocks (
+  );
+
+CONST CHAR16
+*StringFromImxClk (
+  IN IMX_CLK Value
+  );
+
+#endif // _IMX6_CLK_PWR_H_
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
new file mode 100644
index 000000000000..253e7c028bcb
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
@@ -0,0 +1,181 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_CLK_PWR_DQ_H_
+#define _IMX6_CLK_PWR_DQ_H_
+
+// Clock signal definitions
+typedef enum {
+  IMX_CLK_NONE,
+  IMX_OSC_CLK,
+  IMX_PLL1_MAIN_CLK,
+  IMX_PLL2_MAIN_CLK,
+  IMX_PLL2_PFD0,
+  IMX_PLL2_PFD1,
+  IMX_PLL2_PFD2,
+  IMX_PLL3_MAIN_CLK,
+  IMX_PLL3_PFD0,
+  IMX_PLL3_PFD1,
+  IMX_PLL3_PFD2,
+  IMX_PLL3_PFD3,
+  IMX_PLL4_MAIN_CLK,
+  IMX_PLL5_MAIN_CLK,
+  IMX_CLK1,
+  IMX_CLK2,
+  IMX_PLL1_SW_CLK,
+  IMX_STEP_CLK,
+  IMX_PLL3_SW_CLK,
+  IMX_AXI_ALT,
+  IMX_AXI_CLK_ROOT,
+  IMX_PERIPH_CLK2,
+  IMX_PERIPH_CLK,
+  IMX_PRE_PERIPH_CLK,
+  IMX_PRE_PERIPH2_CLK,
+  IMX_PERIPH2_CLK,
+  IMX_ARM_CLK_ROOT,
+  IMX_MMDC_CH0_CLK_ROOT,
+  IMX_MMDC_CH1_CLK_ROOT,
+  IMX_AHB_CLK_ROOT,
+  IMX_IPG_CLK_ROOT,
+  IMX_PERCLK_CLK_ROOT,
+  IMX_USDHC1_CLK_ROOT,
+  IMX_USDHC2_CLK_ROOT,
+  IMX_USDHC3_CLK_ROOT,
+  IMX_USDHC4_CLK_ROOT,
+  IMX_SSI1_CLK_ROOT,
+  IMX_SSI2_CLK_ROOT,
+  IMX_SSI3_CLK_ROOT,
+  IMX_GPU2D_AXI_CLK_ROOT,
+  IMX_GPU3D_AXI_CLK_ROOT,
+  IMX_PCIE_AXI_CLK_ROOT,
+  IMX_VDO_AXI_CLK_ROOT,
+  IMX_IPU1_HSP_CLK_ROOT,
+  IMX_IPU2_HSP_CLK_ROOT,
+  IMX_GPU2D_CORE_CLK_ROOT,
+  IMX_ACLK_EIM_SLOW_CLK_ROOT,
+  IMX_ACLK_CLK_ROOT,
+  IMX_ENFC_CLK_ROOT,
+  IMX_GPU3D_CORE_CLK_ROOT,
+  IMX_GPU3D_SHADER_CLK_ROOT,
+  IMX_VPU_AXI_CLK_ROOT,
+  IMX_IPU1_DI0_CLK_ROOT,
+  IMX_IPU1_DI1_CLK_ROOT,
+  IMX_IPU2_DI0_CLK_ROOT,
+  IMX_IPU2_DI1_CLK_ROOT,
+  IMX_LDB_DI0_SERIAL_CLK_ROOT,
+  IMX_LDB_DI0_IPU,
+  IMX_LDB_DI1_SERIAL_CLK_ROOT,
+  IMX_LDB_DI1_IPU,
+  IMX_SPDIF0_CLK_ROOT,
+  IMX_SPDIF1_CLK_ROOT,
+  IMX_ESAI_CLK_ROOT,
+  IMX_HSI_TX_CLK_ROOT,
+  IMX_CAN_CLK_ROOT,
+  IMX_ECSPI_CLK_ROOT,
+  IMX_UART_CLK_ROOT,
+  IMX_VIDEO_27M_CLK_ROOT,
+  IMX_CLK_MAX,
+} IMX_CLK;
+
+// Clock gate definitions
+typedef enum {
+  IMX_AIPS_TZ1_CLK_ENABLE,
+  IMX_AIPS_TZ2_CLK_ENABLE,
+  IMX_APBHDMA_HCLK_ENABLE,
+  IMX_ASRC_CLK_ENABLE,
+  IMX_CAAM_SECURE_MEM_CLK_ENABLE,
+  IMX_CAAM_WRAPPER_ACLK_ENABLE,
+  IMX_CAAM_WRAPPER_IPG_ENABLE,
+  IMX_CAN1_CLK_ENABLE,
+  IMX_CAN1_SERIAL_CLK_ENABLE,
+  IMX_CAN2_CLK_ENABLE,
+  IMX_CAN2_SERIAL_CLK_ENABLE,
+  IMX_ARM_DBG_CLK_ENABLE,
+  IMX_DCIC1_CLK_ENABLE,
+  IMX_DCIC2_CLK_ENABLE,
+  IMX_DTCP_CLK_ENABLE,
+  IMX_ECSPI1_CLK_ENABLE,
+  IMX_ECSPI2_CLK_ENABLE,
+  IMX_ECSPI3_CLK_ENABLE,
+  IMX_ECSPI4_CLK_ENABLE,
+  IMX_ECSPI5_CLK_ENABLE,
+  IMX_ENET_CLK_ENABLE,
+  IMX_EPIT1_CLK_ENABLE,
+  IMX_EPIT2_CLK_ENABLE,
+  IMX_ESAI_CLK_ENABLE,
+  IMX_GPT_CLK_ENABLE,
+  IMX_GPT_SERIAL_CLK_ENABLE,
+  IMX_GPU2D_CLK_ENABLE,
+  IMX_GPU3D_CLK_ENABLE,
+  IMX_HDMI_TX_ENABLE,
+  IMX_HDMI_TX_ISFRCLK_ENABLE,
+  IMX_I2C1_SERIAL_CLK_ENABLE,
+  IMX_I2C2_SERIAL_CLK_ENABLE,
+  IMX_I2C3_SERIAL_CLK_ENABLE,
+  IMX_IIM_CLK_ENABLE,
+  IMX_IOMUX_IPT_CLK_IO_ENABLE,
+  IMX_IPMUX1_CLK_ENABLE,
+  IMX_IPMUX2_CLK_ENABLE,
+  IMX_IPMUX3_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE,
+  IMX_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE,
+  IMX_IPU1_CLK_ENABLE,
+  IMX_IPU1_DI0_CLK_ENABLE,
+  IMX_IPU1_DI1_CLK_ENABLE,
+  IMX_IPU2_CLK_ENABLE,
+  IMX_IPU2_DI0_CLK_ENABLE,
+  IMX_IPU2_DI1_CLK_ENABLE,
+  IMX_LDB_DI0_CLK_ENABLE,
+  IMX_LDB_DI1_CLK_ENABLE,
+  IMX_MIPI_CORE_CFG_CLK_ENABLE,
+  IMX_MLB_CLK_ENABLE,
+  IMX_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE,
+  IMX_MMDC_CORE_IPG_CLK_P0_ENABLE,
+  IMX_OCRAM_CLK_ENABLE,
+  IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
+  IMX_PCIE_ROOT_ENABLE,
+  IMX_PL301_MX6QFAST1_S133CLK_ENABLE,
+  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
+  IMX_PL301_MX6QPER2_MAINCLK_ENABLE,
+  IMX_PWM1_CLK_ENABLE,
+  IMX_PWM2_CLK_ENABLE,
+  IMX_PWM3_CLK_ENABLE,
+  IMX_PWM4_CLK_ENABLE,
+  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
+  IMX_ROM_CLK_ENABLE,
+  IMX_SATA_CLK_ENABLE,
+  IMX_SDMA_CLK_ENABLE,
+  IMX_SPBA_CLK_ENABLE,
+  IMX_SPDIF_CLK_ENABLE,
+  IMX_SSI1_CLK_ENABLE,
+  IMX_SSI2_CLK_ENABLE,
+  IMX_SSI3_CLK_ENABLE,
+  IMX_UART_CLK_ENABLE,
+  IMX_UART_SERIAL_CLK_ENABLE,
+  IMX_USBOH3_CLK_ENABLE,
+  IMX_USDHC1_CLK_ENABLE,
+  IMX_USDHC2_CLK_ENABLE,
+  IMX_USDHC3_CLK_ENABLE,
+  IMX_USDHC4_CLK_ENABLE,
+  IMX_EIM_SLOW_CLK_ENABLE,
+  IMX_VDOAXICLK_CLK_ENABLE,
+  IMX_VPU_CLK_ENABLE,
+  IMX_CLK_GATE_MAX,
+} IMX_CLK_GATE;
+
+#endif  /* _IMX6_CLK_PWR_DQ_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
new file mode 100644
index 000000000000..d9e0bb1e15a7
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
@@ -0,0 +1,176 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_CLK_PWR_SDL_H_
+#define _IMX6_CLK_PWR_SDL_H_
+
+// Clock signal definitions for iMX6 Solo and DualLite
+typedef enum {
+  IMX_CLK_NONE,
+  IMX_OSC_CLK,
+  IMX_PLL1_MAIN_CLK,
+  IMX_PLL2_MAIN_CLK,
+  IMX_PLL2_PFD0,
+  IMX_PLL2_PFD1,
+  IMX_PLL2_PFD2,
+  IMX_PLL3_MAIN_CLK,
+  IMX_PLL3_PFD0,
+  IMX_PLL3_PFD1,
+  IMX_PLL3_PFD2,
+  IMX_PLL3_PFD3,
+  IMX_PLL4_MAIN_CLK,
+  IMX_PLL5_MAIN_CLK,
+  IMX_CLK1,
+  IMX_CLK2,
+  IMX_PLL1_SW_CLK,
+  IMX_STEP_CLK,
+  IMX_PLL3_SW_CLK,
+  IMX_AXI_ALT,
+  IMX_AXI_CLK_ROOT,
+  IMX_PERIPH_CLK2,
+  IMX_PERIPH_CLK,
+  IMX_PRE_PERIPH_CLK,
+  IMX_PRE_PERIPH2_CLK,
+  IMX_PERIPH2_CLK,
+  IMX_ARM_CLK_ROOT,
+  IMX_MMDC_CH0_CLK_ROOT,
+  IMX_MMDC_CH1_CLK_ROOT,
+  IMX_AHB_CLK_ROOT,
+  IMX_IPG_CLK_ROOT,
+  IMX_PERCLK_CLK_ROOT,
+  IMX_USDHC1_CLK_ROOT,
+  IMX_USDHC2_CLK_ROOT,
+  IMX_USDHC3_CLK_ROOT,
+  IMX_USDHC4_CLK_ROOT,
+  IMX_SSI1_CLK_ROOT,
+  IMX_SSI2_CLK_ROOT,
+  IMX_SSI3_CLK_ROOT,
+  IMX_GPU2D_AXI_CLK_ROOT,
+  IMX_GPU3D_AXI_CLK_ROOT,
+  IMX_PCIE_AXI_CLK_ROOT,
+  IMX_VDO_AXI_CLK_ROOT,
+  IMX_IPU1_HSP_CLK_ROOT,
+  IMX_GPU2D_CORE_CLK_ROOT,
+  IMX_ACLK_EIM_SLOW_CLK_ROOT,
+  IMX_ACLK_CLK_ROOT,
+  IMX_ENFC_CLK_ROOT,
+  IMX_GPU3D_CORE_CLK_ROOT,
+  IMX_GPU3D_SHADER_CLK_ROOT,
+  IMX_VPU_AXI_CLK_ROOT,
+  IMX_IPU1_DI0_CLK_ROOT,
+  IMX_IPU1_DI1_CLK_ROOT,
+  IMX_LDB_DI0_SERIAL_CLK_ROOT,
+  IMX_LDB_DI0_IPU,
+  IMX_LDB_DI1_SERIAL_CLK_ROOT,
+  IMX_LDB_DI1_IPU,
+  IMX_SPDIF0_CLK_ROOT,
+  IMX_SPDIF1_CLK_ROOT,
+  IMX_ESAI_CLK_ROOT,
+  IMX_HSI_TX_CLK_ROOT,
+  IMX_CAN_CLK_ROOT,
+  IMX_ECSPI_CLK_ROOT,
+  IMX_UART_CLK_ROOT,
+  IMX_VIDEO_27M_CLK_ROOT,
+  IMX_CLK_MAX,
+} IMX_CLK;
+
+// Clock gate definitions
+typedef enum {
+  IMX_AIPS_TZ1_CLK_ENABLE,
+  IMX_AIPS_TZ2_CLK_ENABLE,
+  IMX_APBHDMA_HCLK_ENABLE,
+  IMX_ASRC_CLK_ENABLE,
+  IMX_CAAM_SECURE_MEM_CLK_ENABLE,
+  IMX_CAAM_WRAPPER_ACLK_ENABLE,
+  IMX_CAAM_WRAPPER_IPG_ENABLE,
+  IMX_CAN1_CLK_ENABLE,
+  IMX_CAN1_SERIAL_CLK_ENABLE,
+  IMX_CAN2_CLK_ENABLE,
+  IMX_CAN2_SERIAL_CLK_ENABLE,
+  IMX_ARM_DBG_CLK_ENABLE,
+  IMX_DCIC1_CLK_ENABLE,
+  IMX_DCIC2_CLK_ENABLE,
+  IMX_DTCP_CLK_ENABLE,
+  IMX_ECSPI1_CLK_ENABLE,
+  IMX_ECSPI2_CLK_ENABLE,
+  IMX_ECSPI3_CLK_ENABLE,
+  IMX_ECSPI4_CLK_ENABLE,
+  IMX_ECSPI5_CLK_ENABLE,
+  IMX_ENET_CLK_ENABLE,
+  IMX_EPIT1_CLK_ENABLE,
+  IMX_EPIT2_CLK_ENABLE,
+  IMX_ESAI_CLK_ENABLE,
+  IMX_GPT_CLK_ENABLE,
+  IMX_GPT_SERIAL_CLK_ENABLE,
+  IMX_GPU2D_CLK_ENABLE,
+  IMX_GPU3D_CLK_ENABLE,
+  IMX_HDMI_TX_ENABLE,
+  IMX_HDMI_TX_ISFRCLK_ENABLE,
+  IMX_I2C1_SERIAL_CLK_ENABLE,
+  IMX_I2C2_SERIAL_CLK_ENABLE,
+  IMX_I2C3_SERIAL_CLK_ENABLE,
+  IMX_I2C4_SERIAL_CLK_ENABLE,
+  IMX_IIM_CLK_ENABLE,
+  IMX_IOMUX_IPT_CLK_IO_ENABLE,
+  IMX_IPMUX1_CLK_ENABLE,
+  IMX_IPMUX2_CLK_ENABLE,
+  IMX_IPMUX3_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE,
+  IMX_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE,
+  IMX_IPU1_CLK_ENABLE,
+  IMX_IPU1_DI0_CLK_ENABLE,
+  IMX_IPU1_DI1_CLK_ENABLE,
+  IMX_LDB_DI0_CLK_ENABLE,
+  IMX_LDB_DI1_CLK_ENABLE,
+  IMX_MIPI_CORE_CFG_CLK_ENABLE,
+  IMX_MLB_CLK_ENABLE,
+  IMX_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE,
+  IMX_MMDC_CORE_IPG_CLK_P0_ENABLE,
+  IMX_OCRAM_CLK_ENABLE,
+  IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
+  IMX_PCIE_ROOT_ENABLE,
+  IMX_PL301_MX6QFAST1_S133CLK_ENABLE,
+  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
+  IMX_PL301_MX6QPER2_MAINCLK_ENABLE,
+  IMX_PWM1_CLK_ENABLE,
+  IMX_PWM2_CLK_ENABLE,
+  IMX_PWM3_CLK_ENABLE,
+  IMX_PWM4_CLK_ENABLE,
+  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
+  IMX_ROM_CLK_ENABLE,
+  IMX_SATA_CLK_ENABLE,
+  IMX_SDMA_CLK_ENABLE,
+  IMX_SPBA_CLK_ENABLE,
+  IMX_SPDIF_CLK_ENABLE,
+  IMX_SSI1_CLK_ENABLE,
+  IMX_SSI2_CLK_ENABLE,
+  IMX_SSI3_CLK_ENABLE,
+  IMX_UART_CLK_ENABLE,
+  IMX_UART_SERIAL_CLK_ENABLE,
+  IMX_USBOH3_CLK_ENABLE,
+  IMX_USDHC1_CLK_ENABLE,
+  IMX_USDHC2_CLK_ENABLE,
+  IMX_USDHC3_CLK_ENABLE,
+  IMX_USDHC4_CLK_ENABLE,
+  IMX_EIM_SLOW_CLK_ENABLE,
+  IMX_VDOAXICLK_CLK_ENABLE,
+  IMX_VPU_CLK_ENABLE,
+  IMX_CLK_GATE_MAX,
+} IMX_CLK_GATE;
+
+#endif  /* _IMX6_CLK_PWR_SDL_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
new file mode 100644
index 000000000000..8b03f5e45b00
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
@@ -0,0 +1,190 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_CLK_PWR_SX_H_
+#define _IMX6_CLK_PWR_SX_H_
+
+// Clock signal definitions
+// Figure 19-2 Clock Tree
+typedef enum {
+  IMX_CLK_NONE,
+  IMX_OSC_CLK,
+  IMX_PLL1_MAIN_CLK,
+  IMX_PLL2_MAIN_CLK,
+  IMX_PLL2_PFD0,
+  IMX_PLL2_PFD1,
+  IMX_PLL2_PFD2,
+  IMX_PLL2_PFD3,
+  IMX_PLL3_MAIN_CLK,
+  IMX_PLL3_PFD0,
+  IMX_PLL3_PFD1,
+  IMX_PLL3_PFD2,
+  IMX_PLL3_PFD3,
+  IMX_PLL4_MAIN_CLK,
+  IMX_PLL5_MAIN_CLK,
+  IMX_CLK1,
+  IMX_CLK2,
+  IMX_PLL1_SW_CLK,
+  IMX_STEP_CLK,
+  IMX_PLL3_SW_CLK,
+  IMX_PERIPH_CLK2,
+  IMX_PERIPH_CLK,
+  IMX_PRE_PERIPH_CLK,
+  IMX_ARM_CLK_ROOT,
+  IMX_MMDC_CLK_ROOT,
+  IMX_FABRIC_CLK_ROOT,
+  IMX_OCRAM_CLK_ROOT,
+  IMX_PCIE_CLK_ROOT,
+  IMX_AHB_CLK_ROOT,
+  IMX_PERCLK_CLK_ROOT,
+  IMX_IPG_CLK_ROOT,
+  IMX_USDHC1_CLK_ROOT,
+  IMX_USDHC2_CLK_ROOT,
+  IMX_USDHC3_CLK_ROOT,
+  IMX_USDHC4_CLK_ROOT,
+  IMX_ACLK_EIM_SLOW_CLK_ROOT,
+  IMX_GPU_AXI_CLK_ROOT,
+  IMX_GPU_CORE_CLK_ROOT,
+  IMX_VID_CLK_ROOT,
+  IMX_ESAI_CLK_ROOT,
+  IMX_AUDIO_CLK_ROOT,
+  IMX_SPDIF0_CLK_ROOT,
+  IMX_SSI1_CLK_ROOT,
+  IMX_SSI2_CLK_ROOT,
+  IMX_SSI3_CLK_ROOT,
+  IMX_LCDIF2_PIX_CLK_ROOT,
+  IMX_LCDIF1_PIX_CLK_ROOT,
+  IMX_LVDS_CLK_ROOT,
+  IMX_M4_CLK_ROOT,
+  IMX_ENET_CLK_ROOT,
+  IMX_QSPI1_CLK_ROOT,
+  IMX_QSPI2_CLK_ROOT,
+  IMX_DISPLAY_CLK_ROOT,
+  IMX_CSI_CLK_ROOT,
+  IMX_CAN_CLK_ROOT,
+  IMX_ECSPI_CLK_ROOT,
+  IMX_UART_CLK_ROOT,
+  IMX_CLK_MAX,
+} IMX_CLK;
+
+// Clock gate definitions
+typedef enum {
+  IMX_AIPS_TZ1_CLK_ENABLE,
+  IMX_AIPS_TZ2_CLK_ENABLE,
+  IMX_APBHDMA_HCLK_ENABLE,
+  IMX_ASRC_CLK_ENABLE,
+  IMX_CAAM_SECURE_MEM_CLK_ENABLE,
+  IMX_CAAM_WRAPPER_ACLK_ENABLE,
+  IMX_CAAM_WRAPPER_IPG_ENABLE,
+  IMX_CAN1_CLK_ENABLE,
+  IMX_CAN1_SERIAL_CLK_ENABLE,
+  IMX_CAN2_CLK_ENABLE,
+  IMX_CAN2_SERIAL_CLK_ENABLE,
+  IMX_ARM_DBG_CLK_ENABLE,
+  IMX_DCIC1_CLK_ENABLE,
+  IMX_DCIC2_CLK_ENABLE,
+  IMX_AIPS_TZ3_CLK_ENABLE,
+  IMX_ECSPI1_CLK_ENABLE,
+  IMX_ECSPI2_CLK_ENABLE,
+  IMX_ECSPI3_CLK_ENABLE,
+  IMX_ECSPI4_CLK_ENABLE,
+  IMX_ECSPI5_CLK_ENABLE,
+  IMX_EPIT1_CLK_ENABLE,
+  IMX_EPIT2_CLK_ENABLE,
+  IMX_ESAI_CLK_ENABLE,
+  IMX_WAKEUP_CLK_ENABLE,
+  IMX_GPT_CLK_ENABLE,
+  IMX_GPT_SERIAL_CLK_ENABLE,
+  IMX_GPU_CLK_ENABLE,
+  IMX_OCRAM_S_CLK_ENABLE,
+  IMX_CANFD_CLK_ENABLE,
+  IMX_CSI_CLK_ENABLE,
+  IMX_I2C1_SERIAL_CLK_ENABLE,
+  IMX_I2C2_SERIAL_CLK_ENABLE,
+  IMX_I2C3_SERIAL_CLK_ENABLE,
+  IMX_IIM_CLK_ENABLE,
+  IMX_IOMUX_IPT_CLK_IO_ENABLE,
+  IMX_IPMUX1_CLK_ENABLE,
+  IMX_IPMUX2_CLK_ENABLE,
+  IMX_IPMUX3_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
+  IMX_LCD_CLK_ENABLE,
+  IMX_PXP_CLK_ENABLE,
+  IMX_M4_CLK_ENABLE,
+  IMX_ENET_CLK_ENABLE,
+  IMX_DISP_AXI_CLK_ENABLE,
+  IMX_LCDIF2_PIX_CLK_ENABLE,
+  IMX_LCDIF1_PIX_CLK_ENABLE,
+  IMX_LDB_DI0_CLK_ENABLE,
+  IMX_QSPI1_CLK_ENABLE,
+  IMX_MLB_CLK_ENABLE,
+  IMX_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE,
+  IMX_MMDC_CORE_IPG_CLK_P0_ENABLE,
+  IMX_MMDC_CORE_IPG_CLK_P1_ENABLE,
+  IMX_OCRAM_CLK_ENABLE,
+  IMX_PCIE_ROOT_ENABLE,
+  IMX_QSPI2_CLK_ENABLE,
+  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
+  IMX_PL301_MX6QPER2_MAINCLK_ENABLE,
+  IMX_PWM1_CLK_ENABLE,
+  IMX_PWM2_CLK_ENABLE,
+  IMX_PWM3_CLK_ENABLE,
+  IMX_PWM4_CLK_ENABLE,
+  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
+  IMX_ROM_CLK_ENABLE,
+  IMX_SDMA_CLK_ENABLE,
+  IMX_SPBA_CLK_ENABLE,
+  IMX_SPDIF_AND_AUDIO_CLK_ENABLE,
+  IMX_SSI1_CLK_ENABLE,
+  IMX_SSI2_CLK_ENABLE,
+  IMX_SSI3_CLK_ENABLE,
+  IMX_UART_CLK_ENABLE,
+  IMX_UART_SERIAL_CLK_ENABLE,
+  IMX_SAI1_CLK_ENABLE,
+  IMX_SAI2_CLK_ENABLE,
+  IMX_USBOH3_CLK_ENABLE,
+  IMX_USDHC1_CLK_ENABLE,
+  IMX_USDHC2_CLK_ENABLE,
+  IMX_USDHC3_CLK_ENABLE,
+  IMX_USDHC4_CLK_ENABLE,
+  IMX_EIM_SLOW_CLK_ENABLE,
+  IMX_PWM8_CLK_ENABLE,
+  IMX_VADC_CLK_ENABLE,
+  IMX_GIS_CLK_ENABLE,
+  IMX_I2C4_SERIAL_CLK_ENABLE,
+  IMX_PWM5_CLK_ENABLE,
+  IMX_PWM6_CLK_ENABLE,
+  IMX_PWM7_CLK_ENABLE,
+  IMX_CLK_GATE_MAX,
+} IMX_CLK_GATE;
+
+VOID
+ImxClkPwrLcdClockDisable (
+  VOID
+  );
+
+VOID
+ImxClkPwrLcdClockEnable (
+  VOID
+  );
+
+EFI_STATUS
+ImxSetLcdIfClockRate (
+  IN  UINT32  ClockRate
+  );
+
+#endif  /* _IMX6_CLK_PWR_SX_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
new file mode 100644
index 000000000000..30c859529a44
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
@@ -0,0 +1,202 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_IOMUX_H_
+#define _IMX6_IOMUX_H_
+
+//
+// IOMux common definition
+//
+#include <iMXIoMux.h>
+
+//
+// GPIO common definition
+//
+#include <iMXGpio.h>
+
+#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
+#include "iMX6IoMux_DQP.h"
+#elif defined(CPU_IMX6SX)
+#include "iMX6IoMux_SX.h"
+#elif defined(CPU_IMX6SDL)
+#include "iMX6IoMux_SDL.h"
+#else
+#error CPU Preprocessor Flag Not Defined
+#endif
+
+typedef UINT64 IMX_PADCFG;
+
+//
+// Pad control settings
+//
+typedef enum {
+  IMX_HYS_DISABLED,
+  IMX_HYS_ENABLED,
+} IMX_HYS;
+
+typedef enum {
+  IMX_PUS_100K_OHM_PD,
+  IMX_PUS_47K_OHM_PU,
+  IMX_PUS_100K_OHM_PU,
+  IMX_PUS_22K_OHM_PU,
+} IMX_PUS;
+
+typedef enum {
+  IMX_PUE_KEEP,
+  IMX_PUE_PULL,
+} IMX_PUE;
+
+typedef enum {
+  IMX_PKE_DISABLE,
+  IMX_PKE_ENABLE,
+} IMX_PKE;
+
+typedef enum {
+  IMX_ODE_DISABLE,
+  IMX_ODE_ENABLE,
+} IMX_ODE;
+
+typedef enum {
+  IMX_SPEED_LOW,
+  IMX_SPEED_MEDIUM = 2,
+  IMX_SPEED_MAXIMUM,
+} IMX_SPEED;
+
+typedef enum {
+  IMX_DSE_HIZ,
+  IMX_DSE_260_OHM,
+  IMX_DSE_130_OHM,
+  IMX_DSE_90_OHM,
+  IMX_DSE_60_OHM,
+  IMX_DSE_50_OHM,
+  IMX_DSE_40_OHM,
+  IMX_DSE_33_OHM,
+} IMX_DSE;
+
+typedef enum {
+  IMX_SRE_SLOW,
+  IMX_SRE_FAST,
+} IMX_SRE;
+
+typedef enum {
+  IMX_SION_DISABLED,
+  IMX_SION_ENABLED,
+} IMX_IOMUXC_CTL_SION;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 SRE : 1;
+    UINT32 reserved0 : 2;
+    UINT32 DSE : 3;
+    UINT32 SPEED : 2;
+    UINT32 reserved1 : 3;
+    UINT32 ODE : 1 ;
+    UINT32 PKE : 1;
+    UINT32 PUE : 1;
+    UINT32 PUS : 2;
+    UINT32 HYS : 1;
+    UINT32 reserved2 : 15;
+  } Fields;
+} IMX_IOMUXC_PAD_CTL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 MUX_MODE : 3;
+    UINT32 reserved0 : 1;
+    UINT32 SION : 1;
+    UINT32 reserved1 : 27;
+  } Fields;
+} IMX_IOMUXC_MUX_CTL;
+
+typedef struct {
+  UINT32 DAISY : 3;
+  UINT32 reserved : 29;
+} IMX_IOMUXC_SEL_INP_CTL;
+
+#define _IMX_SEL_INP_VALUE(InpSel) \
+          (((InpSel) >> 8) & 0x07)
+
+#define _IMX_SEL_INP_REGISTER(InpSel) \
+          ((((InpSel) & 0xFF) * 4) + IOMUXC_SELECT_INPUT_BASE_ADDRESS)
+
+#define _IMX_MAKE_INP_SEL(InpSelReg, InpSelVal) \
+          (((((InpSelReg) - IOMUXC_SELECT_INPUT_BASE_ADDRESS) / 4) & 0xFF) | \
+          (((InpSelVal) & 0x7) << 8))
+
+#define _IMX_MAKE_MUX_CTL(Sion, MuxAlt) \
+          (((MuxAlt) & 0x7) | \
+          (((Sion) & 0x1) << 4))
+
+#define _IMX_MAKE_PAD_CTL(Sre, Dse, Speed, Ode, Pke, Pue, Pus, Hys) \
+          (((Sre) & 0x1) | \
+          (((Dse) & 0x7) << 3) | \
+          (((Speed) & 0x3) << 6) | \
+          (((Ode) & 0x1) << 11) | \
+          (((Pke) & 0x1) << 12) | \
+          (((Pue) & 0x1) << 13) | \
+          (((Pus) & 0x3) << 14) | \
+          (((Hys) & 0x1) << 16))
+
+/**
+  Define a configuration for a pad, including drive settings,
+  MUX setting and Select Input setting and offset.
+
+  Sre - IMX_SRE - Slew Rate setting
+  Dse - IMX_DSE - Drive strength
+  Speed - IMX_SPEED - Pad speed setting
+  Ode - IMX_ODE - Open drain enable
+  Pke - IMX_PKE - Pull/Keeper enable
+  Pue - IMX_PUE - Pull/Keep mode select
+  Pus - IMX_PUS - Pull strength
+  Hys - IMX_HYS - Hysteresis enable/disable
+  Sion - Software Input on Field
+  MuxAlt- Alternate function number
+  SelInpReg - select input register offset div 4
+  SelInpVal - select input value
+
+**/
+#define _IMX_MAKE_PADCFG_INPSEL(Sre, Dse, Speed, Ode, Pke, Pue, Pus, Hys, Sion, MuxAlt, SelInpReg, SelInpValue) \
+          (_IMX_MAKE_PAD_CTL(Sre, Dse, Speed, Ode, Pke, Pue, Pus, Hys) | \
+           (_IMX_MAKE_MUX_CTL(Sion, MuxAlt) << 17) | \
+           (_IMX_MAKE_INP_SEL(SelInpReg, SelInpValue) << 22))
+
+#define _IMX_MAKE_PADCFG(Sre, Dse, Speed, Ode, Pke, Pue, Pus, Hys, Sion, MuxAlt) \
+          (_IMX_MAKE_PAD_CTL(Sre, Dse, Speed, Ode, Pke, Pue, Pus, Hys) | \
+           _IMX_MAKE_MUX_CTL(Sion, MuxAlt) << 17)
+
+#define _IMX_MAKE_PADCFG2(PadCtl, Sion, MuxAlt) \
+          ((PadCtl) | \
+           _IMX_MAKE_MUX_CTL(Sion, MuxAlt) << 17)
+
+#define _IMX_PADCFG_PAD_CTL(PadCfg) ((PadCfg) & 0x0001F8F9)
+#define _IMX_PADCFG_MUX_CTL(PadCfg) (((PadCfg) >> 17) & 0x00000017)
+#define _IMX_PADCFG_SEL_INP(PadCfg) (((PadCfg) >> 22) & 0x000007FF)
+
+/**
+  Put a pad in the specified configuration.
+
+  For example, to configure GPIO0 as CCM_CLK01 output:
+    ImxPadConfig (IMX_PAD_GPIO_0, IMX_PAD_GPIO_0_CCM_CLKO1);
+
+**/
+VOID ImxPadConfig (IMX_PAD Pad, IMX_PADCFG PadConfig);
+
+/**
+  Dumps to console the specified PAD mux/control configuration.
+**/
+VOID ImxPadDumpConfig (char *PadName, IMX_PAD Pad);
+
+#endif // _IMX6_IOMUX_H_
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h
new file mode 100644
index 000000000000..539d99c1b4a4
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h
@@ -0,0 +1,2466 @@
+/** @file
+*
+*  Header defining IMX6 Dual, Quad, DualPlus, QuadPlus Muxing definitions
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_IOMUX_DQP_H_
+#define _IMX6_IOMUX_DQP_H_
+
+//
+// SELECT INPUT defines
+
+#define EIM_DATA21_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D21 for I2C1_SCL
+#define CSI0_DAT9_ALT4 0x1 // Selecting ALT4 mode of pad CSI0_DAT9 for I2C1_SCL
+
+#define EIM_DATA28_ALT1 0x0 // Selecting ALT1 mode of pad EIM_D28 for I2C1_SDA
+#define CSI0_DAT8_ALT4 0x1 // Selecting ALT4 mode of pad CSI0_DAT8 for I2C1_SDA
+
+#define EIM_EB2_B_ALT6 0x0 // Selecting ALT6 mode of pad EIM_EB2 for I2C2_SCL
+#define KEY_COL3_ALT4 0x1 // Selecting ALT4 mode of pad KEY_COL3 for I2C2_SCL
+
+#define EIM_DATA16_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D16 for I2C2_SDA
+#define KEY_ROW3_ALT4 0x1 // Selecting ALT4 mode of pad KEY_ROW3 for I2C2_SDA
+
+#define EIM_DATA17_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D17 for I2C3_SCL
+#define GPIO03_ALT2 0x1 // Selecting ALT2 mode of pad GPIO_3 for I2C3_SCL
+#define GPIO05_ALT6 0x2 // Selecting ALT6 mode of pad GPIO_5 for I2C3_SCL
+
+#define EIM_DATA18_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D18 for I2C3_SDA
+#define GPIO06_ALT2 0x1 // Selecting ALT2 mode of pad GPIO_6 for I2C3_SDA
+#define GPIO16_ALT6 0x2 // Selecting ALT6 mode of pad GPIO_16 for I2C3_SDA
+
+#define DISP0_DATA19_ALT3 0
+#define KEY_ROW1_ALT2 1
+
+#define DISP0_DATA17_ALT3 0
+#define KEY_ROW0_ALT2 1
+
+#define DISP0_DATA16_ALT3 0
+#define KEY_COL0_ALT2 1
+
+#define DISP0_DATA18_ALT3 0
+#define KEY_COL1_ALT2 1
+
+#define EIM_DATA21_ALT4 0
+#define KEY_COL4_ALT2 1
+
+#define EIM_DATA30_ALT6 0
+#define GPIO03_ALT6 1
+
+#define RGMII_TX_CTL_ALT7 0
+#define GPIO16_ALT2 1
+
+#define CSI0_DATA10_ALT3 0 // Selecting ALT3 mode of pad CSI0_DAT10 for UART1_TX_DATA.
+#define CSI0_DATA11_ALT3 1 // Selecting ALT3 mode of pad CSI0_DAT11 for UART1_RX_DATA.
+#define SD3_DATA7_ALT1 2 // Selecting ALT1 mode of pad SD3_DAT7 for UART1_TX_DATA.
+#define SD3_DATA6_ALT1 3 // Selecting ALT1 mode of pad SD3_DAT6 for UART1_RX_DATA.
+
+#define EIM_DATA26_ALT4 0 // Selecting ALT4 mode of pad EIM_D26 for UART2_TX_DATA.
+#define EIM_DATA27_ALT4 1 // Selecting ALT4 mode of pad EIM_D27 for UART2_RX_DATA.
+#define GPIO07_ALT4 2 // Selecting ALT4 mode of pad GPIO_7 for UART2_TX_DATA.
+#define GPIO08_ALT4 3 // Selecting ALT4 mode of pad GPIO_8 for UART2_RX_DATA.
+#define SD3_DATA5_ALT1 4 // Selecting ALT1 mode of pad SD3_DAT5 for UART2_TX_DATA.
+#define SD3_DATA4_ALT1 5 // Selecting ALT1 mode of pad SD3_DAT4 for UART2_RX_DATA.
+#define SD4_DATA4_ALT2 6 // Selecting ALT2 mode of pad SD4_DAT4 for UART2_RX_DATA.
+#define SD4_DATA7_ALT2 7 // Selecting ALT2 mode of pad SD4_DAT7 for UART2_TX_DATA.
+
+#define EIM_DATA24_ALT2 0 // Selecting ALT2 mode of pad EIM_D24 for UART3_TX_DATA.
+#define EIM_DATA25_ALT2 1 // Selecting ALT2 mode of pad EIM_D25 for UART3_RX_DATA.
+#define SD4_CMD_ALT2 2 // Selecting ALT2 mode of pad SD4_CMD for UART3_TX_DATA.
+#define SD4_CLK_ALT2 3 // Selecting ALT2 mode of pad SD4_CLK for UART3_RX_DATA.
+
+
+//
+// AUD5 select input register defines.
+//
+typedef enum {
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO00)
+  IMX_PAD_GPIO_0 = _IMX_PAD (0x5F0, 0x220), // CCM_CLKO1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO01)
+  IMX_PAD_GPIO_1 = _IMX_PAD (0x5F4, 0x224), // ESAI_RX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO02)
+  IMX_PAD_GPIO_2 = _IMX_PAD (0x604, 0x234), // ESAI_TX_FS
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO03)
+  IMX_PAD_GPIO_3 = _IMX_PAD (0x5FC, 0x22C), // ESAI_RX_HF_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO04)
+  IMX_PAD_GPIO_4 = _IMX_PAD (0x608, 0x238), // ESAI_TX_HF_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO05)
+  IMX_PAD_GPIO_5 = _IMX_PAD (0x60C, 0x23C), // ESAI_TX2_RX3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO06)
+  IMX_PAD_GPIO_6 = _IMX_PAD (0x600, 0x230), // ESAI_TX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO07)
+  IMX_PAD_GPIO_7 = _IMX_PAD (0x610, 0x240), // ESAI_TX4_RX1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO08)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO08)
+  IMX_PAD_GPIO_8 = _IMX_PAD (0x614, 0x244), // ESAI_TX5_RX0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO09)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO09)
+  IMX_PAD_GPIO_9 = _IMX_PAD (0x5F8, 0x228), // ESAI_RX_FS
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_CLK)
+  IMX_PAD_SD2_CLK = _IMX_PAD (0x73C, 0x354), // SD2_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_CMD)
+  IMX_PAD_SD2_CMD = _IMX_PAD (0x740, 0x358), // SD2_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA3)
+  IMX_PAD_SD2_DAT3 = _IMX_PAD (0x744, 0x35C), // SD2_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA2)
+  IMX_PAD_SD2_DAT2 = _IMX_PAD (0x364, 0x50), // SD2_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA1)
+  IMX_PAD_SD2_DAT1 = _IMX_PAD (0x360, 0x4C), // SD2_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA0)
+  IMX_PAD_SD2_DAT0 = _IMX_PAD (0x368, 0x54), // SD2_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA0)
+  IMX_PAD_SD1_DAT0 = _IMX_PAD (0x728, 0x340), // SD1_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA1)
+  IMX_PAD_SD1_DAT1 = _IMX_PAD (0x724, 0x33C), // SD1_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_CMD)
+  IMX_PAD_SD1_CMD = _IMX_PAD (0x730, 0x348), // SD1_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2)
+  IMX_PAD_SD1_DAT2 = _IMX_PAD (0x734, 0x34C), // SD1_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_CLK)
+  IMX_PAD_SD1_CLK = _IMX_PAD (0x738, 0x350), // SD1_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA3)
+  IMX_PAD_SD1_DAT3 = _IMX_PAD (0x72C, 0x344), // SD1_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_MDIO)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_MDIO)
+  IMX_PAD_ENET_MDIO = _IMX_PAD (0x4E4, 0x1D0), // ENET_MDIO
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_REF_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_REF_CLK)
+  IMX_PAD_ENET_REF_CLK = _IMX_PAD (0x4E8, 0x1D4), // ENET_TX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_RX_ER)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_RX_ER)
+  IMX_PAD_ENET_RX_ER = _IMX_PAD (0x4EC, 0x1D8), // USB_OTG_ID
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_CRS_DV)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_CRS_DV)
+  IMX_PAD_ENET_CRS_DV = _IMX_PAD (0x4F0, 0x1DC), // ENET_RX_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_RX_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_RX_DATA1)
+  IMX_PAD_ENET_RXD1 = _IMX_PAD (0x4F4, 0x1E0), // MLB_SIG
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_RX_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_RX_DATA0)
+  IMX_PAD_ENET_RXD0 = _IMX_PAD (0x4F8, 0x1E4), // XTALOSC_OSC32K_32K_OUT
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_TX_EN)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_TX_EN)
+  IMX_PAD_ENET_TX_EN = _IMX_PAD (0x4FC, 0x1E8), // ENET_TX_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_TX_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_TX_DATA1)
+  IMX_PAD_ENET_TXD1 = _IMX_PAD (0x500, 0x1EC), // MLB_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_TX_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_TX_DATA0)
+  IMX_PAD_ENET_TXD0 = _IMX_PAD (0x504, 0x1F0), // ENET_TX_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET_MDC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET_MDC)
+  IMX_PAD_ENET_MDC = _IMX_PAD (0x508, 0x1F4), // MLB_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA00)
+  IMX_PAD_NANDF_D0 = _IMX_PAD (0x6E4, 0x2FC), // NAND_DATA00
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA01)
+  IMX_PAD_NANDF_D1 = _IMX_PAD (0x6E8, 0x300), // NAND_DATA01
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA02)
+  IMX_PAD_NANDF_D2 = _IMX_PAD (0x6EC, 0x304), // NAND_DATA02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA03)
+  IMX_PAD_NANDF_D3 = _IMX_PAD (0x6F0, 0x308), // NAND_DATA03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA04)
+  IMX_PAD_NANDF_D4 = _IMX_PAD (0x6F4, 0x30C), // NAND_DATA04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA05)
+  IMX_PAD_NANDF_D5 = _IMX_PAD (0x6F8, 0x310), // NAND_DATA05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA06)
+  IMX_PAD_NANDF_D6 = _IMX_PAD (0x6FC, 0x314), // NAND_DATA06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA07)
+  IMX_PAD_NANDF_D7 = _IMX_PAD (0x700, 0x318), // NAND_DATA07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA0)
+  IMX_PAD_SD4_DAT0 = _IMX_PAD (0x704, 0x31C), // SD4_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA1)
+  IMX_PAD_SD4_DAT1 = _IMX_PAD (0x708, 0x320), // SD4_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA2)
+  IMX_PAD_SD4_DAT2 = _IMX_PAD (0x70C, 0x324), // SD4_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA3)
+  IMX_PAD_SD4_DAT3 = _IMX_PAD (0x710, 0x328), // SD4_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA4)
+  IMX_PAD_SD4_DAT4 = _IMX_PAD (0x714, 0x32C), // SD4_DATA4
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA5)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA5)
+  IMX_PAD_SD4_DAT5 = _IMX_PAD (0x718, 0x330), // SD4_DATA5
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA6)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA6)
+  IMX_PAD_SD4_DAT6 = _IMX_PAD (0x71C, 0x334), // SD4_DATA6
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA7)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA7)
+  IMX_PAD_SD4_DAT7 = _IMX_PAD (0x720, 0x338), // SD4_DATA7
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR22)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR22)
+  IMX_PAD_EIM_A22 = _IMX_PAD (0x3F0, 0xDC), // EIM_ADDR22
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR21)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR21)
+  IMX_PAD_EIM_A21 = _IMX_PAD (0x3F4, 0xE0), // EIM_ADDR21
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR20)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR20)
+  IMX_PAD_EIM_A20 = _IMX_PAD (0x3F8, 0xE4), // EIM_ADDR20
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR19)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR19)
+  IMX_PAD_EIM_A19 = _IMX_PAD (0x3FC, 0xE8), // EIM_ADDR19
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR18)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR18)
+  IMX_PAD_EIM_A18 = _IMX_PAD (0x400, 0xEC), // EIM_ADDR18
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR17)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR17)
+  IMX_PAD_EIM_A17 = _IMX_PAD (0x404, 0xF0), // EIM_ADDR17
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR16)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR16)
+  IMX_PAD_EIM_A16 = _IMX_PAD (0x408, 0xF4), // EIM_ADDR16
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B)
+  IMX_PAD_EIM_CS0 = _IMX_PAD (0x40C, 0xF8), // EIM_CS0_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_CS1_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_CS1_B)
+  IMX_PAD_EIM_CS1 = _IMX_PAD (0x410, 0xFC), // EIM_CS1_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B)
+  IMX_PAD_EIM_OE = _IMX_PAD (0x414, 0x100), // EIM_OE_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_RW)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_RW)
+  IMX_PAD_EIM_RW = _IMX_PAD (0x418, 0x104), // EIM_RW
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B)
+  IMX_PAD_EIM_LBA = _IMX_PAD (0x41C, 0x108), // EIM_LBA_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_EB0_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_EB0_B)
+  IMX_PAD_EIM_EB0 = _IMX_PAD (0x420, 0x10C), // EIM_EB0_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_EB1_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_EB1_B)
+  IMX_PAD_EIM_EB1 = _IMX_PAD (0x424, 0x110), // EIM_EB1_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_EB2_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_EB2_B)
+  IMX_PAD_EIM_EB2 = _IMX_PAD (0x3A0, 0x8C), // EIM_EB2_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_EB3_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_EB3_B)
+  IMX_PAD_EIM_EB3 = _IMX_PAD (0x3C4, 0xB0), // EIM_EB3_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD00)
+  IMX_PAD_EIM_DA0 = _IMX_PAD (0x428, 0x114), // EIM_AD00
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD01)
+  IMX_PAD_EIM_DA1 = _IMX_PAD (0x42C, 0x118), // EIM_AD01
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD02)
+  IMX_PAD_EIM_DA2 = _IMX_PAD (0x430, 0x11C), // EIM_AD02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD03)
+  IMX_PAD_EIM_DA3 = _IMX_PAD (0x434, 0x120), // EIM_AD03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD04)
+  IMX_PAD_EIM_DA4 = _IMX_PAD (0x438, 0x124), // EIM_AD04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD05)
+  IMX_PAD_EIM_DA5 = _IMX_PAD (0x43C, 0x128), // EIM_AD05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD06)
+  IMX_PAD_EIM_DA6 = _IMX_PAD (0x440, 0x12C), // EIM_AD06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD07)
+  IMX_PAD_EIM_DA7 = _IMX_PAD (0x444, 0x130), // EIM_AD07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD08)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD08)
+  IMX_PAD_EIM_DA8 = _IMX_PAD (0x448, 0x134), // EIM_AD08
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD09)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD09)
+  IMX_PAD_EIM_DA9 = _IMX_PAD (0x44C, 0x138), // EIM_AD09
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD10)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD10)
+  IMX_PAD_EIM_DA10 = _IMX_PAD (0x450, 0x13C), // EIM_AD10
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD11)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD11)
+  IMX_PAD_EIM_DA11 = _IMX_PAD (0x454, 0x140), // EIM_AD11
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD12)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD12)
+  IMX_PAD_EIM_DA12 = _IMX_PAD (0x458, 0x144), // EIM_AD12
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD13)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD13)
+  IMX_PAD_EIM_DA13 = _IMX_PAD (0x45C, 0x148), // EIM_AD13
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD14)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD14)
+  IMX_PAD_EIM_DA14 = _IMX_PAD (0x460, 0x14C), // EIM_AD14
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_AD15)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_AD15)
+  IMX_PAD_EIM_DA15 = _IMX_PAD (0x464, 0x150), // EIM_AD15
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA16)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16)
+  IMX_PAD_EIM_D16 = _IMX_PAD (0x3A4, 0x90), // EIM_DATA16
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA17)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA17)
+  IMX_PAD_EIM_D17 = _IMX_PAD (0x3A8, 0x94), // EIM_DATA17
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA18)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA18)
+  IMX_PAD_EIM_D18 = _IMX_PAD (0x3AC, 0x98), // EIM_DATA18
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA19)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA19)
+  IMX_PAD_EIM_D19 = _IMX_PAD (0x3B0, 0x9C), // EIM_DATA19
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA20)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA20)
+  IMX_PAD_EIM_D20 = _IMX_PAD (0x3B4, 0xA0), // EIM_DATA20
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA21)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA21)
+  IMX_PAD_EIM_D21 = _IMX_PAD (0x3B8, 0xA4), // EIM_DATA21
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA22)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA22)
+  IMX_PAD_EIM_D22 = _IMX_PAD (0x3BC, 0xA8), // EIM_DATA22
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA23)
+  IMX_PAD_EIM_D23 = _IMX_PAD (0x3C0, 0xAC), // EIM_DATA23
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA24)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA24)
+  IMX_PAD_EIM_D24 = _IMX_PAD (0x3C8, 0xB4), // EIM_DATA24
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA25)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA25)
+  IMX_PAD_EIM_D25 = _IMX_PAD (0x3CC, 0xB8), // EIM_DATA25
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA26)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA26)
+  IMX_PAD_EIM_D26 = _IMX_PAD (0x3D0, 0xBC), // EIM_DATA26
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA27)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA27)
+  IMX_PAD_EIM_D27 = _IMX_PAD (0x3D4, 0xC0), // EIM_DATA27
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA28)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA28)
+  IMX_PAD_EIM_D28 = _IMX_PAD (0x3D8, 0xC4), // EIM_DATA28
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA29)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA29)
+  IMX_PAD_EIM_D29 = _IMX_PAD (0x3DC, 0xC8), // EIM_DATA29
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA30)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA30)
+  IMX_PAD_EIM_D30 = _IMX_PAD (0x3E0, 0xCC), // EIM_DATA30
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_DATA31)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_DATA31)
+  IMX_PAD_EIM_D31 = _IMX_PAD (0x3E4, 0xD0), // EIM_DATA31
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO19)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO19)
+  IMX_PAD_GPIO_19 = _IMX_PAD (0x624, 0x254), // KEY_COL5
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL0)
+  IMX_PAD_KEY_COL0 = _IMX_PAD (0x5C8, 0x1F8), // ECSPI1_SCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0)
+  IMX_PAD_KEY_ROW0 = _IMX_PAD (0x5CC, 0x1FC), // ECSPI1_MOSI
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL1)
+  IMX_PAD_KEY_COL1 = _IMX_PAD (0x5D0, 0x200), // ECSPI1_MISO
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1)
+  IMX_PAD_KEY_ROW1 = _IMX_PAD (0x5D4, 0x204), // ECSPI1_SS0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL2)
+  IMX_PAD_KEY_COL2 = _IMX_PAD (0x5D8, 0x208), // ECSPI1_SS1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2)
+  IMX_PAD_KEY_ROW2 = _IMX_PAD (0x5DC, 0x20C), // ECSPI1_SS2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL3)
+  IMX_PAD_KEY_COL3 = _IMX_PAD (0x5E0, 0x210), // ECSPI1_SS3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3)
+  IMX_PAD_KEY_ROW3 = _IMX_PAD (0x5E4, 0x214), // XTALOSC_OSC32K_32K_OUT
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL4)
+  IMX_PAD_KEY_COL4 = _IMX_PAD (0x5E8, 0x218), // FLEXCAN2_TX
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4)
+  IMX_PAD_KEY_ROW4 = _IMX_PAD (0x5EC, 0x21C), // FLEXCAN2_RX
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DI0_DISP_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DI0_DISP_CLK)
+  IMX_PAD_DI0_DISP_CLK = _IMX_PAD (0x470, 0x15C), // IPU1_DI0_DISP_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DI0_PIN15)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DI0_PIN15)
+  IMX_PAD_DI0_PIN15 = _IMX_PAD (0x474, 0x160), // IPU1_DI0_PIN15
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DI0_PIN02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DI0_PIN02)
+  IMX_PAD_DI0_PIN2 = _IMX_PAD (0x478, 0x164), // IPU1_DI0_PIN02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DI0_PIN03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DI0_PIN03)
+  IMX_PAD_DI0_PIN3 = _IMX_PAD (0x47C, 0x168), // IPU1_DI0_PIN03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DI0_PIN04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DI0_PIN04)
+  IMX_PAD_DI0_PIN4 = _IMX_PAD (0x480, 0x16C), // IPU1_DI0_PIN04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA00)
+  IMX_PAD_DISP0_DAT0 = _IMX_PAD (0x484, 0x170), // IPU1_DISP0_DATA00
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA01)
+  IMX_PAD_DISP0_DAT1 = _IMX_PAD (0x488, 0x174), // IPU1_DISP0_DATA01
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA02)
+  IMX_PAD_DISP0_DAT2 = _IMX_PAD (0x48C, 0x178), // IPU1_DISP0_DATA02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA03)
+  IMX_PAD_DISP0_DAT3 = _IMX_PAD (0x490, 0x17C), // IPU1_DISP0_DATA03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA04)
+  IMX_PAD_DISP0_DAT4 = _IMX_PAD (0x494, 0x180), // IPU1_DISP0_DATA04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA05)
+  IMX_PAD_DISP0_DAT5 = _IMX_PAD (0x498, 0x184), // IPU1_DISP0_DATA05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA06)
+  IMX_PAD_DISP0_DAT6 = _IMX_PAD (0x49C, 0x188), // IPU1_DISP0_DATA06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA07)
+  IMX_PAD_DISP0_DAT7 = _IMX_PAD (0x4A0, 0x18C), // IPU1_DISP0_DATA07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA08)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA08)
+  IMX_PAD_DISP0_DAT8 = _IMX_PAD (0x4A4, 0x190), // IPU1_DISP0_DATA08
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA09)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA09)
+  IMX_PAD_DISP0_DAT9 = _IMX_PAD (0x4A8, 0x194), // IPU1_DISP0_DATA09
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA10)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA10)
+  IMX_PAD_DISP0_DAT10 = _IMX_PAD (0x4AC, 0x198), // IPU1_DISP0_DATA10
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B)
+  IMX_PAD_EIM_WAIT = _IMX_PAD (0x468, 0x154), // EIM_WAIT_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR25)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR25)
+  IMX_PAD_EIM_A25 = _IMX_PAD (0x39C, 0x88), // EIM_ADDR25
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR24)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR24)
+  IMX_PAD_EIM_A24 = _IMX_PAD (0x3E8, 0xD4), // EIM_ADDR24
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA11)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA11)
+  IMX_PAD_DISP0_DAT11 = _IMX_PAD (0x4B0, 0x19C), // IPU1_DISP0_DATA11
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA12)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA12)
+  IMX_PAD_DISP0_DAT12 = _IMX_PAD (0x4B4, 0x1A0), // IPU1_DISP0_DATA12
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA13)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA13)
+  IMX_PAD_DISP0_DAT13 = _IMX_PAD (0x4B8, 0x1A4), // IPU1_DISP0_DATA13
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA14)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA14)
+  IMX_PAD_DISP0_DAT14 = _IMX_PAD (0x4BC, 0x1A8), // IPU1_DISP0_DATA14
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA15)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA15)
+  IMX_PAD_DISP0_DAT15 = _IMX_PAD (0x4C0, 0x1AC), // IPU1_DISP0_DATA15
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA16)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA16)
+  IMX_PAD_DISP0_DAT16 = _IMX_PAD (0x4C4, 0x1B0), // IPU1_DISP0_DATA16
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA17)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA17)
+  IMX_PAD_DISP0_DAT17 = _IMX_PAD (0x4C8, 0x1B4), // IPU1_DISP0_DATA17
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA18)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA18)
+  IMX_PAD_DISP0_DAT18 = _IMX_PAD (0x4CC, 0x1B8), // IPU1_DISP0_DATA18
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA19)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA19)
+  IMX_PAD_DISP0_DAT19 = _IMX_PAD (0x4D0, 0x1BC), // IPU1_DISP0_DATA19
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA20)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA20)
+  IMX_PAD_DISP0_DAT20 = _IMX_PAD (0x4D4, 0x1C0), // IPU1_DISP0_DATA20
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA21)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA21)
+  IMX_PAD_DISP0_DAT21 = _IMX_PAD (0x4D8, 0x1C4), // IPU1_DISP0_DATA21
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA22)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA22)
+  IMX_PAD_DISP0_DAT22 = _IMX_PAD (0x4DC, 0x1C8), // IPU1_DISP0_DATA22
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_DISP0_DATA23)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA23)
+  IMX_PAD_DISP0_DAT23 = _IMX_PAD (0x4E0, 0x1CC), // IPU1_DISP0_DATA23
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_PIXCLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_PIXCLK)
+  IMX_PAD_CSI0_PIXCLK = _IMX_PAD (0x628, 0x258), // IPU1_CSI0_PIXCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_HSYNC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_HSYNC)
+  IMX_PAD_CSI0_MCLK = _IMX_PAD (0x62C, 0x25C), // IPU1_CSI0_HSYNC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA_EN)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA_EN)
+  IMX_PAD_CSI0_DATA_EN = _IMX_PAD (0x630, 0x260), // IPU1_CSI0_DATA_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_VSYNC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_VSYNC)
+  IMX_PAD_CSI0_VSYNC = _IMX_PAD (0x634, 0x264), // IPU1_CSI0_VSYNC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA04)
+  IMX_PAD_CSI0_DAT4 = _IMX_PAD (0x638, 0x268), // IPU1_CSI0_DATA04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA05)
+  IMX_PAD_CSI0_DAT5 = _IMX_PAD (0x63C, 0x26C), // IPU1_CSI0_DATA05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA06)
+  IMX_PAD_CSI0_DAT6 = _IMX_PAD (0x640, 0x270), // IPU1_CSI0_DATA06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA07)
+  IMX_PAD_CSI0_DAT7 = _IMX_PAD (0x644, 0x274), // IPU1_CSI0_DATA07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA08)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA08)
+  IMX_PAD_CSI0_DAT8 = _IMX_PAD (0x648, 0x278), // IPU1_CSI0_DATA08
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA09)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA09)
+  IMX_PAD_CSI0_DAT9 = _IMX_PAD (0x64C, 0x27C), // IPU1_CSI0_DATA09
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA10)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA10)
+  IMX_PAD_CSI0_DAT10 = _IMX_PAD (0x650, 0x280), // IPU1_CSI0_DATA10
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA11)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA11)
+  IMX_PAD_CSI0_DAT11 = _IMX_PAD (0x654, 0x284), // IPU1_CSI0_DATA11
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA12)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA12)
+  IMX_PAD_CSI0_DAT12 = _IMX_PAD (0x658, 0x288), // IPU1_CSI0_DATA12
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA13)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA13)
+  IMX_PAD_CSI0_DAT13 = _IMX_PAD (0x65C, 0x28C), // IPU1_CSI0_DATA13
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA14)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA14)
+  IMX_PAD_CSI0_DAT14 = _IMX_PAD (0x660, 0x290), // IPU1_CSI0_DATA14
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA15)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA15)
+  IMX_PAD_CSI0_DAT15 = _IMX_PAD (0x664, 0x294), // IPU1_CSI0_DATA15
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA16)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA16)
+  IMX_PAD_CSI0_DAT16 = _IMX_PAD (0x668, 0x298), // IPU1_CSI0_DATA16
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA17)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA17)
+  IMX_PAD_CSI0_DAT17 = _IMX_PAD (0x66C, 0x29C), // IPU1_CSI0_DATA17
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA18)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA18)
+  IMX_PAD_CSI0_DAT18 = _IMX_PAD (0x670, 0x2A0), // IPU1_CSI0_DATA18
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA19)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA19)
+  IMX_PAD_CSI0_DAT19 = _IMX_PAD (0x674, 0x2A4), // IPU1_CSI0_DATA19
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_ADDR23)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_ADDR23)
+  IMX_PAD_EIM_A23 = _IMX_PAD (0x3EC, 0xD8), // EIM_ADDR23
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CLE)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CLE)
+  IMX_PAD_NANDF_CLE = _IMX_PAD (0x6BC, 0x2D4), // NAND_CLE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_ALE)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_ALE)
+  IMX_PAD_NANDF_ALE = _IMX_PAD (0x6C0, 0x2D8), // NAND_ALE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_WP_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_WP_B)
+  IMX_PAD_NANDF_WP_B = _IMX_PAD (0x6C4, 0x2DC), // NAND_WP_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_READY_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_READY_B)
+  IMX_PAD_NANDF_RB0 = _IMX_PAD (0x6C8, 0x2E0), // NAND_READY_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CS0_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CS0_B)
+  IMX_PAD_NANDF_CS0 = _IMX_PAD (0x6CC, 0x2E4), // NAND_CE0_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CS1_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CS1_B)
+  IMX_PAD_NANDF_CS1 = _IMX_PAD (0x6D0, 0x2E8), // NAND_CE1_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CS2_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CS2_B)
+  IMX_PAD_NANDF_CS2 = _IMX_PAD (0x6D4, 0x2EC), // NAND_CE2_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CS3_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CS3_B)
+  IMX_PAD_NANDF_CS3 = _IMX_PAD (0x6D8, 0x2F0), // NAND_CE3_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA7)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA7)
+  IMX_PAD_SD3_DAT7 = _IMX_PAD (0x690, 0x2A8), // SD3_DATA7
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA6)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA6)
+  IMX_PAD_SD3_DAT6 = _IMX_PAD (0x694, 0x2AC), // SD3_DATA6
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_TXC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_TXC)
+  IMX_PAD_RGMII_TXC = _IMX_PAD (0x36C, 0x58), // USB_H2_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_TD0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_TD0)
+  IMX_PAD_RGMII_TD0 = _IMX_PAD (0x370, 0x5C), // HSI_TX_READY
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_TD1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_TD1)
+  IMX_PAD_RGMII_TD1 = _IMX_PAD (0x374, 0x60), // HSI_RX_FLAG
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_TD2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_TD2)
+  IMX_PAD_RGMII_TD2 = _IMX_PAD (0x378, 0x64), // HSI_RX_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_TD3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_TD3)
+  IMX_PAD_RGMII_TD3 = _IMX_PAD (0x37C, 0x68), // HSI_RX_WAKE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_RX_CTL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_RX_CTL)
+  IMX_PAD_RGMII_RX_CTL = _IMX_PAD (0x380, 0x6C), // USB_H3_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_RD0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_RD0)
+  IMX_PAD_RGMII_RD0 = _IMX_PAD (0x384, 0x70), // HSI_RX_READY
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_TX_CTL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_TX_CTL)
+  IMX_PAD_RGMII_TX_CTL = _IMX_PAD (0x388, 0x74), // USB_H2_STROBE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_RD1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_RD1)
+  IMX_PAD_RGMII_RD1 = _IMX_PAD (0x38C, 0x78), // HSI_TX_FLAG
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_RD2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_RD2)
+  IMX_PAD_RGMII_RD2 = _IMX_PAD (0x390, 0x7C), // HSI_TX_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_RD3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_RD3)
+  IMX_PAD_RGMII_RD3 = _IMX_PAD (0x394, 0x80), // HSI_TX_WAKE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII_RXC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII_RXC)
+  IMX_PAD_RGMII_RXC = _IMX_PAD (0x398, 0x84), // USB_H3_STROBE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK)
+  IMX_PAD_EIM_BCLK = _IMX_PAD (0x46C, 0x158), // EIM_BCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA5)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA5)
+  IMX_PAD_SD3_DAT5 = _IMX_PAD (0x698, 0x2B0), // SD3_DATA5
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA4)
+  IMX_PAD_SD3_DAT4 = _IMX_PAD (0x69C, 0x2B4), // SD3_DATA4
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_CMD)
+  IMX_PAD_SD3_CMD = _IMX_PAD (0x6A0, 0x2B8), // SD3_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_CLK)
+  IMX_PAD_SD3_CLK = _IMX_PAD (0x6A4, 0x2BC), // SD3_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA0)
+  IMX_PAD_SD3_DAT0 = _IMX_PAD (0x6A8, 0x2C0), // SD3_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA1)
+  IMX_PAD_SD3_DAT1 = _IMX_PAD (0x6AC, 0x2C4), // SD3_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA2)
+  IMX_PAD_SD3_DAT2 = _IMX_PAD (0x6B0, 0x2C8), // SD3_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA3)
+  IMX_PAD_SD3_DAT3 = _IMX_PAD (0x6B4, 0x2CC), // SD3_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_RESET)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_RESET)
+  IMX_PAD_SD3_RST = _IMX_PAD (0x6B8, 0x2D0), // SD3_RESET
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_CMD)
+  IMX_PAD_SD4_CMD = _IMX_PAD (0x6DC, 0x2F4), // SD4_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_CLK)
+  IMX_PAD_SD4_CLK = _IMX_PAD (0x6E0, 0x2F8), // SD4_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO16)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO16)
+  IMX_PAD_GPIO_16 = _IMX_PAD (0x618, 0x248), // ESAI_TX3_RX2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO17)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO17)
+  IMX_PAD_GPIO_17 = _IMX_PAD (0x61C, 0x24C), // ESAI_TX0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO18)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO18)
+  IMX_PAD_GPIO_18 = _IMX_PAD (0x620, 0x250), // ESAI_TX1
+} IMX_PAD;
+
+//
+// Alternate function numbers
+//
+
+typedef enum {
+  IMX_IOMUXC_GPIO_0_ALT0_CCM_CLKO1 = 0,
+  IMX_IOMUXC_GPIO_0_ALT2_KEY_COL5 = 2,
+  IMX_IOMUXC_GPIO_0_ALT3_ASRC_EXT_CLK = 3,
+  IMX_IOMUXC_GPIO_0_ALT4_EPIT1_OUT = 4,
+  IMX_IOMUXC_GPIO_0_ALT5_GPIO1_IO00 = 5,
+  IMX_IOMUXC_GPIO_0_ALT6_USB_H1_PWR = 6,
+  IMX_IOMUXC_GPIO_0_ALT7_SNVS_VIO_5 = 7,
+} IMX_IOMUXC_GPIO_0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_1_ALT0_ESAI_RX_CLK = 0,
+  IMX_IOMUXC_GPIO_1_ALT1_WDOG2_B = 1,
+  IMX_IOMUXC_GPIO_1_ALT2_KEY_ROW5 = 2,
+  IMX_IOMUXC_GPIO_1_ALT3_USB_OTG_ID = 3,
+  IMX_IOMUXC_GPIO_1_ALT4_PWM2_OUT = 4,
+  IMX_IOMUXC_GPIO_1_ALT5_GPIO1_IO01 = 5,
+  IMX_IOMUXC_GPIO_1_ALT6_SD1_CD_B = 6,
+} IMX_IOMUXC_GPIO_1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_2_ALT0_ESAI_TX_FS = 0,
+  IMX_IOMUXC_GPIO_2_ALT2_KEY_ROW6 = 2,
+  IMX_IOMUXC_GPIO_2_ALT5_GPIO1_IO02 = 5,
+  IMX_IOMUXC_GPIO_2_ALT6_SD2_WP = 6,
+  IMX_IOMUXC_GPIO_2_ALT7_MLB_DATA = 7,
+} IMX_IOMUXC_GPIO_2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_3_ALT0_ESAI_RX_HF_CLK = 0,
+  IMX_IOMUXC_GPIO_3_ALT2_I2C3_SCL = 2,
+  IMX_IOMUXC_GPIO_3_ALT3_XTALOSC_REF_CLK_24M = 3,
+  IMX_IOMUXC_GPIO_3_ALT4_CCM_CLKO2 = 4,
+  IMX_IOMUXC_GPIO_3_ALT5_GPIO1_IO03 = 5,
+  IMX_IOMUXC_GPIO_3_ALT6_USB_H1_OC = 6,
+  IMX_IOMUXC_GPIO_3_ALT7_MLB_CLK = 7,
+} IMX_IOMUXC_GPIO_3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_4_ALT0_ESAI_TX_HF_CLK = 0,
+  IMX_IOMUXC_GPIO_4_ALT2_KEY_COL7 = 2,
+  IMX_IOMUXC_GPIO_4_ALT5_GPIO1_IO04 = 5,
+  IMX_IOMUXC_GPIO_4_ALT6_SD2_CD_B = 6,
+} IMX_IOMUXC_GPIO_4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_5_ALT0_ESAI_TX2_RX3 = 0,
+  IMX_IOMUXC_GPIO_5_ALT2_KEY_ROW7 = 2,
+  IMX_IOMUXC_GPIO_5_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_GPIO_5_ALT5_GPIO1_IO05 = 5,
+  IMX_IOMUXC_GPIO_5_ALT6_I2C3_SCL = 6,
+  IMX_IOMUXC_GPIO_5_ALT7_ARM_EVENTI = 7,
+} IMX_IOMUXC_GPIO_5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_6_ALT0_ESAI_TX_CLK = 0,
+  IMX_IOMUXC_GPIO_6_ALT1 = 1,
+  IMX_IOMUXC_GPIO_6_ALT2_I2C3_SDA = 2,
+  IMX_IOMUXC_GPIO_6_ALT5_GPIO1_IO06 = 5,
+  IMX_IOMUXC_GPIO_6_ALT6_SD2_LCTL = 6,
+  IMX_IOMUXC_GPIO_6_ALT7_MLB_SIG = 7,
+} IMX_IOMUXC_GPIO_6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_7_ALT0_ESAI_TX4_RX1 = 0,
+  IMX_IOMUXC_GPIO_7_ALT1_ECSPI5_RDY = 1,
+  IMX_IOMUXC_GPIO_7_ALT2_EPIT1_OUT = 2,
+  IMX_IOMUXC_GPIO_7_ALT3_FLEXCAN1_TX = 3,
+  IMX_IOMUXC_GPIO_7_ALT4_UART2_TX_DATA = 4,
+  IMX_IOMUXC_GPIO_7_ALT5_GPIO1_IO07 = 5,
+  IMX_IOMUXC_GPIO_7_ALT6_SPDIF_LOCK = 6,
+  IMX_IOMUXC_GPIO_7_ALT7_USB_OTG_HOST_MODE = 7,
+} IMX_IOMUXC_GPIO_7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_8_ALT0_ESAI_TX5_RX0 = 0,
+  IMX_IOMUXC_GPIO_8_ALT1_XTALOSC_REF_CLK_32K = 1,
+  IMX_IOMUXC_GPIO_8_ALT2_EPIT2_OUT = 2,
+  IMX_IOMUXC_GPIO_8_ALT3_FLEXCAN1_RX = 3,
+  IMX_IOMUXC_GPIO_8_ALT4_UART2_RX_DATA = 4,
+  IMX_IOMUXC_GPIO_8_ALT5_GPIO1_IO08 = 5,
+  IMX_IOMUXC_GPIO_8_ALT6_SPDIF_SR_CLK = 6,
+  IMX_IOMUXC_GPIO_8_ALT7_USB_OTG_PWR_CTL_WAKE = 7,
+} IMX_IOMUXC_GPIO_8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_9_ALT0_ESAI_RX_FS = 0,
+  IMX_IOMUXC_GPIO_9_ALT1_WDOG1_B = 1,
+  IMX_IOMUXC_GPIO_9_ALT2_KEY_COL6 = 2,
+  IMX_IOMUXC_GPIO_9_ALT3_CCM_REF_EN_B = 3,
+  IMX_IOMUXC_GPIO_9_ALT4_PWM1_OUT = 4,
+  IMX_IOMUXC_GPIO_9_ALT5_GPIO1_IO09 = 5,
+  IMX_IOMUXC_GPIO_9_ALT6_SD1_WP = 6,
+} IMX_IOMUXC_GPIO_9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_CLK_ALT0_SD2_CLK = 0,
+  IMX_IOMUXC_SD2_CLK_ALT1_ECSPI5_SCLK = 1,
+  IMX_IOMUXC_SD2_CLK_ALT2_KEY_COL5 = 2,
+  IMX_IOMUXC_SD2_CLK_ALT3_AUD4_RXFS = 3,
+  IMX_IOMUXC_SD2_CLK_ALT5_GPIO1_IO10 = 5,
+} IMX_IOMUXC_SD2_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_CMD_ALT0_SD2_CMD = 0,
+  IMX_IOMUXC_SD2_CMD_ALT1_ECSPI5_MOSI = 1,
+  IMX_IOMUXC_SD2_CMD_ALT2_KEY_ROW5 = 2,
+  IMX_IOMUXC_SD2_CMD_ALT3_AUD4_RXC = 3,
+  IMX_IOMUXC_SD2_CMD_ALT5_GPIO1_IO11 = 5,
+} IMX_IOMUXC_SD2_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT3_ALT0_SD2_DATA3 = 0,
+  IMX_IOMUXC_SD2_DAT3_ALT1_ECSPI5_SS3 = 1,
+  IMX_IOMUXC_SD2_DAT3_ALT2_KEY_COL6 = 2,
+  IMX_IOMUXC_SD2_DAT3_ALT3_AUD4_TXC = 3,
+  IMX_IOMUXC_SD2_DAT3_ALT5_GPIO1_IO12 = 5,
+} IMX_IOMUXC_SD2_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT2_ALT0_SD2_DATA2 = 0,
+  IMX_IOMUXC_SD2_DAT2_ALT1_ECSPI5_SS1 = 1,
+  IMX_IOMUXC_SD2_DAT2_ALT2_EIM_CS3_B = 2,
+  IMX_IOMUXC_SD2_DAT2_ALT3_AUD4_TXD = 3,
+  IMX_IOMUXC_SD2_DAT2_ALT4_KEY_ROW6 = 4,
+  IMX_IOMUXC_SD2_DAT2_ALT5_GPIO1_IO13 = 5,
+} IMX_IOMUXC_SD2_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT1_ALT0_SD2_DATA1 = 0,
+  IMX_IOMUXC_SD2_DAT1_ALT1_ECSPI5_SS0 = 1,
+  IMX_IOMUXC_SD2_DAT1_ALT2_EIM_CS2_B = 2,
+  IMX_IOMUXC_SD2_DAT1_ALT3_AUD4_TXFS = 3,
+  IMX_IOMUXC_SD2_DAT1_ALT4_KEY_COL7 = 4,
+  IMX_IOMUXC_SD2_DAT1_ALT5_GPIO1_IO14 = 5,
+} IMX_IOMUXC_SD2_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT0_ALT0_SD2_DATA0 = 0,
+  IMX_IOMUXC_SD2_DAT0_ALT1_ECSPI5_MISO = 1,
+  IMX_IOMUXC_SD2_DAT0_ALT3_AUD4_RXD = 3,
+  IMX_IOMUXC_SD2_DAT0_ALT4_KEY_ROW7 = 4,
+  IMX_IOMUXC_SD2_DAT0_ALT5_GPIO1_IO15 = 5,
+  IMX_IOMUXC_SD2_DAT0_ALT6_DCIC2_OUT = 6,
+} IMX_IOMUXC_SD2_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT0_ALT0_SD1_DATA0 = 0,
+  IMX_IOMUXC_SD1_DAT0_ALT1_ECSPI5_MISO = 1,
+  IMX_IOMUXC_SD1_DAT0_ALT3_GPT_CAPTURE1 = 3,
+  IMX_IOMUXC_SD1_DAT0_ALT5_GPIO1_IO16 = 5,
+} IMX_IOMUXC_SD1_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT1_ALT0_SD1_DATA1 = 0,
+  IMX_IOMUXC_SD1_DAT1_ALT1_ECSPI5_SS0 = 1,
+  IMX_IOMUXC_SD1_DAT1_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_SD1_DAT1_ALT3_GPT_CAPTURE2 = 3,
+  IMX_IOMUXC_SD1_DAT1_ALT5_GPIO1_IO17 = 5,
+} IMX_IOMUXC_SD1_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_CMD_ALT0_SD1_CMD = 0,
+  IMX_IOMUXC_SD1_CMD_ALT1_ECSPI5_MOSI = 1,
+  IMX_IOMUXC_SD1_CMD_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_SD1_CMD_ALT3_GPT_COMPARE1 = 3,
+  IMX_IOMUXC_SD1_CMD_ALT5_GPIO1_IO18 = 5,
+} IMX_IOMUXC_SD1_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT2_ALT0_SD1_DATA2 = 0,
+  IMX_IOMUXC_SD1_DAT2_ALT1_ECSPI5_SS1 = 1,
+  IMX_IOMUXC_SD1_DAT2_ALT2_GPT_COMPARE2 = 2,
+  IMX_IOMUXC_SD1_DAT2_ALT3_PWM2_OUT = 3,
+  IMX_IOMUXC_SD1_DAT2_ALT4_WDOG1_B = 4,
+  IMX_IOMUXC_SD1_DAT2_ALT5_GPIO1_IO19 = 5,
+  IMX_IOMUXC_SD1_DAT2_ALT6_WDOG1_RESET_B_DEB = 6,
+} IMX_IOMUXC_SD1_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_CLK_ALT0_SD1_CLK = 0,
+  IMX_IOMUXC_SD1_CLK_ALT1_ECSPI5_SCLK = 1,
+  IMX_IOMUXC_SD1_CLK_ALT2_XTALOSC_OSC32K_32K_OUT = 2,
+  IMX_IOMUXC_SD1_CLK_ALT3_GPT_CLKIN = 3,
+  IMX_IOMUXC_SD1_CLK_ALT5_GPIO1_IO20 = 5,
+} IMX_IOMUXC_SD1_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT3_ALT0_SD1_DATA3 = 0,
+  IMX_IOMUXC_SD1_DAT3_ALT1_ECSPI5_SS2 = 1,
+  IMX_IOMUXC_SD1_DAT3_ALT2_GPT_COMPARE3 = 2,
+  IMX_IOMUXC_SD1_DAT3_ALT3_PWM1_OUT = 3,
+  IMX_IOMUXC_SD1_DAT3_ALT4_WDOG2_B = 4,
+  IMX_IOMUXC_SD1_DAT3_ALT5_GPIO1_IO21 = 5,
+  IMX_IOMUXC_SD1_DAT3_ALT6_WDOG2_RESET_B_DEB = 6,
+} IMX_IOMUXC_SD1_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_MDIO_ALT1_ENET_MDIO = 1,
+  IMX_IOMUXC_ENET_MDIO_ALT2_ESAI_RX_CLK = 2,
+  IMX_IOMUXC_ENET_MDIO_ALT4_ENET_1588_EVENT1_OUT = 4,
+  IMX_IOMUXC_ENET_MDIO_ALT5_GPIO1_IO22 = 5,
+  IMX_IOMUXC_ENET_MDIO_ALT6_SPDIF_LOCK = 6,
+} IMX_IOMUXC_ENET_MDIO_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_REF_CLK_ALT1_ENET_TX_CLK = 1,
+  IMX_IOMUXC_ENET_REF_CLK_ALT2_ESAI_RX_FS = 2,
+  IMX_IOMUXC_ENET_REF_CLK_ALT5_GPIO1_IO23 = 5,
+  IMX_IOMUXC_ENET_REF_CLK_ALT6_SPDIF_SR_CLK = 6,
+} IMX_IOMUXC_ENET_REF_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_RX_ER_ALT0_USB_OTG_ID = 0,
+  IMX_IOMUXC_ENET_RX_ER_ALT1_ENET_RX_ER = 1,
+  IMX_IOMUXC_ENET_RX_ER_ALT2_ESAI_RX_HF_CLK = 2,
+  IMX_IOMUXC_ENET_RX_ER_ALT3_SPDIF_IN = 3,
+  IMX_IOMUXC_ENET_RX_ER_ALT4_ENET_1588_EVENT2_OUT = 4,
+  IMX_IOMUXC_ENET_RX_ER_ALT5_GPIO1_IO24 = 5,
+} IMX_IOMUXC_ENET_RX_ER_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_CRS_DV_ALT1_ENET_RX_EN = 1,
+  IMX_IOMUXC_ENET_CRS_DV_ALT2_ESAI_TX_CLK = 2,
+  IMX_IOMUXC_ENET_CRS_DV_ALT3_SPDIF_EXT_CLK = 3,
+  IMX_IOMUXC_ENET_CRS_DV_ALT5_GPIO1_IO25 = 5,
+} IMX_IOMUXC_ENET_CRS_DV_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_RXD1_ALT0_MLB_SIG = 0,
+  IMX_IOMUXC_ENET_RXD1_ALT1_ENET_RX_DATA1 = 1,
+  IMX_IOMUXC_ENET_RXD1_ALT2_ESAI_TX_FS = 2,
+  IMX_IOMUXC_ENET_RXD1_ALT4_ENET_1588_EVENT3_OUT = 4,
+  IMX_IOMUXC_ENET_RXD1_ALT5_GPIO1_IO26 = 5,
+} IMX_IOMUXC_ENET_RXD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_RXD0_ALT0_XTALOSC_OSC32K_32K_OUT = 0,
+  IMX_IOMUXC_ENET_RXD0_ALT1_ENET_RX_DATA0 = 1,
+  IMX_IOMUXC_ENET_RXD0_ALT2_ESAI_TX_HF_CLK = 2,
+  IMX_IOMUXC_ENET_RXD0_ALT3_SPDIF_OUT = 3,
+  IMX_IOMUXC_ENET_RXD0_ALT5_GPIO1_IO27 = 5,
+} IMX_IOMUXC_ENET_RXD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_TX_EN_ALT1_ENET_TX_EN = 1,
+  IMX_IOMUXC_ENET_TX_EN_ALT2_ESAI_TX3_RX2 = 2,
+  IMX_IOMUXC_ENET_TX_EN_ALT5_GPIO1_IO28 = 5,
+} IMX_IOMUXC_ENET_TX_EN_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_TXD1_ALT0_MLB_CLK = 0,
+  IMX_IOMUXC_ENET_TXD1_ALT1_ENET_TX_DATA1 = 1,
+  IMX_IOMUXC_ENET_TXD1_ALT2_ESAI_TX2_RX3 = 2,
+  IMX_IOMUXC_ENET_TXD1_ALT4_ENET_1588_EVENT0_IN = 4,
+  IMX_IOMUXC_ENET_TXD1_ALT5_GPIO1_IO29 = 5,
+} IMX_IOMUXC_ENET_TXD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_TXD0_ALT1_ENET_TX_DATA0 = 1,
+  IMX_IOMUXC_ENET_TXD0_ALT2_ESAI_TX4_RX1 = 2,
+  IMX_IOMUXC_ENET_TXD0_ALT5_GPIO1_IO30 = 5,
+} IMX_IOMUXC_ENET_TXD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_MDC_ALT0_MLB_DATA = 0,
+  IMX_IOMUXC_ENET_MDC_ALT1_ENET_MDC = 1,
+  IMX_IOMUXC_ENET_MDC_ALT2_ESAI_TX5_RX0 = 2,
+  IMX_IOMUXC_ENET_MDC_ALT4_ENET_1588_EVENT1_IN = 4,
+  IMX_IOMUXC_ENET_MDC_ALT5_GPIO1_IO31 = 5,
+} IMX_IOMUXC_ENET_MDC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D0_ALT0_NAND_DATA00 = 0,
+  IMX_IOMUXC_NANDF_D0_ALT1_SD1_DATA4 = 1,
+  IMX_IOMUXC_NANDF_D0_ALT5_GPIO2_IO00 = 5,
+} IMX_IOMUXC_NANDF_D0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D1_ALT0_NAND_DATA01 = 0,
+  IMX_IOMUXC_NANDF_D1_ALT1_SD1_DATA5 = 1,
+  IMX_IOMUXC_NANDF_D1_ALT5_GPIO2_IO01 = 5,
+} IMX_IOMUXC_NANDF_D1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D2_ALT0_NAND_DATA02 = 0,
+  IMX_IOMUXC_NANDF_D2_ALT1_SD1_DATA6 = 1,
+  IMX_IOMUXC_NANDF_D2_ALT5_GPIO2_IO02 = 5,
+} IMX_IOMUXC_NANDF_D2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D3_ALT0_NAND_DATA03 = 0,
+  IMX_IOMUXC_NANDF_D3_ALT1_SD1_DATA7 = 1,
+  IMX_IOMUXC_NANDF_D3_ALT5_GPIO2_IO03 = 5,
+} IMX_IOMUXC_NANDF_D3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D4_ALT0_NAND_DATA04 = 0,
+  IMX_IOMUXC_NANDF_D4_ALT1_SD2_DATA4 = 1,
+  IMX_IOMUXC_NANDF_D4_ALT5_GPIO2_IO04 = 5,
+} IMX_IOMUXC_NANDF_D4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D5_ALT0_NAND_DATA05 = 0,
+  IMX_IOMUXC_NANDF_D5_ALT1_SD2_DATA5 = 1,
+  IMX_IOMUXC_NANDF_D5_ALT5_GPIO2_IO05 = 5,
+} IMX_IOMUXC_NANDF_D5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D6_ALT0_NAND_DATA06 = 0,
+  IMX_IOMUXC_NANDF_D6_ALT1_SD2_DATA6 = 1,
+  IMX_IOMUXC_NANDF_D6_ALT5_GPIO2_IO06 = 5,
+} IMX_IOMUXC_NANDF_D6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D7_ALT0_NAND_DATA07 = 0,
+  IMX_IOMUXC_NANDF_D7_ALT1_SD2_DATA7 = 1,
+  IMX_IOMUXC_NANDF_D7_ALT5_GPIO2_IO07 = 5,
+} IMX_IOMUXC_NANDF_D7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT0_ALT1_SD4_DATA0 = 1,
+  IMX_IOMUXC_SD4_DAT0_ALT2_NAND_DQS = 2,
+  IMX_IOMUXC_SD4_DAT0_ALT5_GPIO2_IO08 = 5,
+} IMX_IOMUXC_SD4_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT1_ALT1_SD4_DATA1 = 1,
+  IMX_IOMUXC_SD4_DAT1_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_SD4_DAT1_ALT5_GPIO2_IO09 = 5,
+} IMX_IOMUXC_SD4_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT2_ALT1_SD4_DATA2 = 1,
+  IMX_IOMUXC_SD4_DAT2_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_SD4_DAT2_ALT5_GPIO2_IO10 = 5,
+} IMX_IOMUXC_SD4_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT3_ALT1_SD4_DATA3 = 1,
+  IMX_IOMUXC_SD4_DAT3_ALT5_GPIO2_IO11 = 5,
+} IMX_IOMUXC_SD4_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT4_ALT1_SD4_DATA4 = 1,
+  IMX_IOMUXC_SD4_DAT4_ALT2_UART2_RX_DATA = 2,
+  IMX_IOMUXC_SD4_DAT4_ALT5_GPIO2_IO12 = 5,
+} IMX_IOMUXC_SD4_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT5_ALT1_SD4_DATA5 = 1,
+  IMX_IOMUXC_SD4_DAT5_ALT2_UART2_RTS_B = 2,
+  IMX_IOMUXC_SD4_DAT5_ALT5_GPIO2_IO13 = 5,
+} IMX_IOMUXC_SD4_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT6_ALT1_SD4_DATA6 = 1,
+  IMX_IOMUXC_SD4_DAT6_ALT2_UART2_CTS_B = 2,
+  IMX_IOMUXC_SD4_DAT6_ALT5_GPIO2_IO14 = 5,
+} IMX_IOMUXC_SD4_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT7_ALT1_SD4_DATA7 = 1,
+  IMX_IOMUXC_SD4_DAT7_ALT2_UART2_TX_DATA = 2,
+  IMX_IOMUXC_SD4_DAT7_ALT5_GPIO2_IO15 = 5,
+} IMX_IOMUXC_SD4_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A22_ALT0_EIM_ADDR22 = 0,
+  IMX_IOMUXC_EIM_A22_ALT1_IPU1_DISP1_DATA17 = 1,
+  IMX_IOMUXC_EIM_A22_ALT2_IPU2_CSI1_DATA17 = 2,
+  IMX_IOMUXC_EIM_A22_ALT5_GPIO2_IO16 = 5,
+  IMX_IOMUXC_EIM_A22_ALT7_SRC_BOOT_CFG22 = 7,
+} IMX_IOMUXC_EIM_A22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A21_ALT0_EIM_ADDR21 = 0,
+  IMX_IOMUXC_EIM_A21_ALT1_IPU1_DISP1_DATA16 = 1,
+  IMX_IOMUXC_EIM_A21_ALT2_IPU2_CSI1_DATA16 = 2,
+  IMX_IOMUXC_EIM_A21_ALT5_GPIO2_IO17 = 5,
+  IMX_IOMUXC_EIM_A21_ALT7_SRC_BOOT_CFG21 = 7,
+} IMX_IOMUXC_EIM_A21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A20_ALT0_EIM_ADDR20 = 0,
+  IMX_IOMUXC_EIM_A20_ALT1_IPU1_DISP1_DATA15 = 1,
+  IMX_IOMUXC_EIM_A20_ALT2_IPU2_CSI1_DATA15 = 2,
+  IMX_IOMUXC_EIM_A20_ALT5_GPIO2_IO18 = 5,
+  IMX_IOMUXC_EIM_A20_ALT7_SRC_BOOT_CFG20 = 7,
+} IMX_IOMUXC_EIM_A20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A19_ALT0_EIM_ADDR19 = 0,
+  IMX_IOMUXC_EIM_A19_ALT1_IPU1_DISP1_DATA14 = 1,
+  IMX_IOMUXC_EIM_A19_ALT2_IPU2_CSI1_DATA14 = 2,
+  IMX_IOMUXC_EIM_A19_ALT5_GPIO2_IO19 = 5,
+  IMX_IOMUXC_EIM_A19_ALT7_SRC_BOOT_CFG19 = 7,
+} IMX_IOMUXC_EIM_A19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A18_ALT0_EIM_ADDR18 = 0,
+  IMX_IOMUXC_EIM_A18_ALT1_IPU1_DISP1_DATA13 = 1,
+  IMX_IOMUXC_EIM_A18_ALT2_IPU2_CSI1_DATA13 = 2,
+  IMX_IOMUXC_EIM_A18_ALT5_GPIO2_IO20 = 5,
+  IMX_IOMUXC_EIM_A18_ALT7_SRC_BOOT_CFG18 = 7,
+} IMX_IOMUXC_EIM_A18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A17_ALT0_EIM_ADDR17 = 0,
+  IMX_IOMUXC_EIM_A17_ALT1_IPU1_DISP1_DATA12 = 1,
+  IMX_IOMUXC_EIM_A17_ALT2_IPU2_CSI1_DATA12 = 2,
+  IMX_IOMUXC_EIM_A17_ALT5_GPIO2_IO21 = 5,
+  IMX_IOMUXC_EIM_A17_ALT7_SRC_BOOT_CFG17 = 7,
+} IMX_IOMUXC_EIM_A17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A16_ALT0_EIM_ADDR16 = 0,
+  IMX_IOMUXC_EIM_A16_ALT1_IPU1_DI1_DISP_CLK = 1,
+  IMX_IOMUXC_EIM_A16_ALT2_IPU2_CSI1_PIXCLK = 2,
+  IMX_IOMUXC_EIM_A16_ALT5_GPIO2_IO22 = 5,
+  IMX_IOMUXC_EIM_A16_ALT7_SRC_BOOT_CFG16 = 7,
+} IMX_IOMUXC_EIM_A16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_CS0_ALT0_EIM_CS0_B = 0,
+  IMX_IOMUXC_EIM_CS0_ALT1_IPU1_DI1_PIN05 = 1,
+  IMX_IOMUXC_EIM_CS0_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_EIM_CS0_ALT5_GPIO2_IO23 = 5,
+} IMX_IOMUXC_EIM_CS0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_CS1_ALT0_EIM_CS1_B = 0,
+  IMX_IOMUXC_EIM_CS1_ALT1_IPU1_DI1_PIN06 = 1,
+  IMX_IOMUXC_EIM_CS1_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_EIM_CS1_ALT5_GPIO2_IO24 = 5,
+} IMX_IOMUXC_EIM_CS1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_OE_ALT0_EIM_OE_B = 0,
+  IMX_IOMUXC_EIM_OE_ALT1_IPU1_DI1_PIN07 = 1,
+  IMX_IOMUXC_EIM_OE_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_EIM_OE_ALT5_GPIO2_IO25 = 5,
+} IMX_IOMUXC_EIM_OE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_RW_ALT0_EIM_RW = 0,
+  IMX_IOMUXC_EIM_RW_ALT1_IPU1_DI1_PIN08 = 1,
+  IMX_IOMUXC_EIM_RW_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_EIM_RW_ALT5_GPIO2_IO26 = 5,
+  IMX_IOMUXC_EIM_RW_ALT7_SRC_BOOT_CFG29 = 7,
+} IMX_IOMUXC_EIM_RW_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_LBA_ALT0_EIM_LBA_B = 0,
+  IMX_IOMUXC_EIM_LBA_ALT1_IPU1_DI1_PIN17 = 1,
+  IMX_IOMUXC_EIM_LBA_ALT2_ECSPI2_SS1 = 2,
+  IMX_IOMUXC_EIM_LBA_ALT5_GPIO2_IO27 = 5,
+  IMX_IOMUXC_EIM_LBA_ALT7_SRC_BOOT_CFG26 = 7,
+} IMX_IOMUXC_EIM_LBA_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB0_ALT0_EIM_EB0_B = 0,
+  IMX_IOMUXC_EIM_EB0_ALT1_IPU1_DISP1_DATA11 = 1,
+  IMX_IOMUXC_EIM_EB0_ALT2_IPU2_CSI1_DATA11 = 2,
+  IMX_IOMUXC_EIM_EB0_ALT4_CCM_PMIC_READY = 4,
+  IMX_IOMUXC_EIM_EB0_ALT5_GPIO2_IO28 = 5,
+  IMX_IOMUXC_EIM_EB0_ALT7_SRC_BOOT_CFG27 = 7,
+} IMX_IOMUXC_EIM_EB0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB1_ALT0_EIM_EB1_B = 0,
+  IMX_IOMUXC_EIM_EB1_ALT1_IPU1_DISP1_DATA10 = 1,
+  IMX_IOMUXC_EIM_EB1_ALT2_IPU2_CSI1_DATA10 = 2,
+  IMX_IOMUXC_EIM_EB1_ALT5_GPIO2_IO29 = 5,
+  IMX_IOMUXC_EIM_EB1_ALT7_SRC_BOOT_CFG28 = 7,
+} IMX_IOMUXC_EIM_EB1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB2_ALT0_EIM_EB2_B = 0,
+  IMX_IOMUXC_EIM_EB2_ALT1_ECSPI1_SS0 = 1,
+  IMX_IOMUXC_EIM_EB2_ALT3_IPU2_CSI1_DATA19 = 3,
+  IMX_IOMUXC_EIM_EB2_ALT4_HDMI_TX_DDC_SCL = 4,
+  IMX_IOMUXC_EIM_EB2_ALT5_GPIO2_IO30 = 5,
+  IMX_IOMUXC_EIM_EB2_ALT6_I2C2_SCL = 6,
+  IMX_IOMUXC_EIM_EB2_ALT7_SRC_BOOT_CFG30 = 7,
+} IMX_IOMUXC_EIM_EB2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB3_ALT0_EIM_EB3_B = 0,
+  IMX_IOMUXC_EIM_EB3_ALT1_ECSPI4_RDY = 1,
+  IMX_IOMUXC_EIM_EB3_ALT2_UART3_RTS_B = 2,
+  IMX_IOMUXC_EIM_EB3_ALT3_UART1_RI_B = 3,
+  IMX_IOMUXC_EIM_EB3_ALT4_IPU2_CSI1_HSYNC = 4,
+  IMX_IOMUXC_EIM_EB3_ALT5_GPIO2_IO31 = 5,
+  IMX_IOMUXC_EIM_EB3_ALT6_IPU1_DI1_PIN03 = 6,
+  IMX_IOMUXC_EIM_EB3_ALT7_SRC_BOOT_CFG31 = 7,
+} IMX_IOMUXC_EIM_EB3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA0_ALT0_EIM_AD00 = 0,
+  IMX_IOMUXC_EIM_DA0_ALT1_IPU1_DISP1_DATA09 = 1,
+  IMX_IOMUXC_EIM_DA0_ALT2_IPU2_CSI1_DATA09 = 2,
+  IMX_IOMUXC_EIM_DA0_ALT5_GPIO3_IO00 = 5,
+  IMX_IOMUXC_EIM_DA0_ALT7_SRC_BOOT_CFG00 = 7,
+} IMX_IOMUXC_EIM_DA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA1_ALT0_EIM_AD01 = 0,
+  IMX_IOMUXC_EIM_DA1_ALT1_IPU1_DISP1_DATA08 = 1,
+  IMX_IOMUXC_EIM_DA1_ALT2_IPU2_CSI1_DATA08 = 2,
+  IMX_IOMUXC_EIM_DA1_ALT5_GPIO3_IO01 = 5,
+  IMX_IOMUXC_EIM_DA1_ALT7_SRC_BOOT_CFG01 = 7,
+} IMX_IOMUXC_EIM_DA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA2_ALT0_EIM_AD02 = 0,
+  IMX_IOMUXC_EIM_DA2_ALT1_IPU1_DISP1_DATA07 = 1,
+  IMX_IOMUXC_EIM_DA2_ALT2_IPU2_CSI1_DATA07 = 2,
+  IMX_IOMUXC_EIM_DA2_ALT5_GPIO3_IO02 = 5,
+  IMX_IOMUXC_EIM_DA2_ALT7_SRC_BOOT_CFG02 = 7,
+} IMX_IOMUXC_EIM_DA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA3_ALT0_EIM_AD03 = 0,
+  IMX_IOMUXC_EIM_DA3_ALT1_IPU1_DISP1_DATA06 = 1,
+  IMX_IOMUXC_EIM_DA3_ALT2_IPU2_CSI1_DATA06 = 2,
+  IMX_IOMUXC_EIM_DA3_ALT5_GPIO3_IO03 = 5,
+  IMX_IOMUXC_EIM_DA3_ALT7_SRC_BOOT_CFG03 = 7,
+} IMX_IOMUXC_EIM_DA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA4_ALT0_EIM_AD04 = 0,
+  IMX_IOMUXC_EIM_DA4_ALT1_IPU1_DISP1_DATA05 = 1,
+  IMX_IOMUXC_EIM_DA4_ALT2_IPU2_CSI1_DATA05 = 2,
+  IMX_IOMUXC_EIM_DA4_ALT5_GPIO3_IO04 = 5,
+  IMX_IOMUXC_EIM_DA4_ALT7_SRC_BOOT_CFG04 = 7,
+} IMX_IOMUXC_EIM_DA4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA5_ALT0_EIM_AD05 = 0,
+  IMX_IOMUXC_EIM_DA5_ALT1_IPU1_DISP1_DATA04 = 1,
+  IMX_IOMUXC_EIM_DA5_ALT2_IPU2_CSI1_DATA04 = 2,
+  IMX_IOMUXC_EIM_DA5_ALT5_GPIO3_IO05 = 5,
+  IMX_IOMUXC_EIM_DA5_ALT7_SRC_BOOT_CFG05 = 7,
+} IMX_IOMUXC_EIM_DA5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA6_ALT0_EIM_AD06 = 0,
+  IMX_IOMUXC_EIM_DA6_ALT1_IPU1_DISP1_DATA03 = 1,
+  IMX_IOMUXC_EIM_DA6_ALT2_IPU2_CSI1_DATA03 = 2,
+  IMX_IOMUXC_EIM_DA6_ALT5_GPIO3_IO06 = 5,
+  IMX_IOMUXC_EIM_DA6_ALT7_SRC_BOOT_CFG06 = 7,
+} IMX_IOMUXC_EIM_DA6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA7_ALT0_EIM_AD07 = 0,
+  IMX_IOMUXC_EIM_DA7_ALT1_IPU1_DISP1_DATA02 = 1,
+  IMX_IOMUXC_EIM_DA7_ALT2_IPU2_CSI1_DATA02 = 2,
+  IMX_IOMUXC_EIM_DA7_ALT5_GPIO3_IO07 = 5,
+  IMX_IOMUXC_EIM_DA7_ALT7_SRC_BOOT_CFG07 = 7,
+} IMX_IOMUXC_EIM_DA7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA8_ALT0_EIM_AD08 = 0,
+  IMX_IOMUXC_EIM_DA8_ALT1_IPU1_DISP1_DATA01 = 1,
+  IMX_IOMUXC_EIM_DA8_ALT2_IPU2_CSI1_DATA01 = 2,
+  IMX_IOMUXC_EIM_DA8_ALT5_GPIO3_IO08 = 5,
+  IMX_IOMUXC_EIM_DA8_ALT7_SRC_BOOT_CFG08 = 7,
+} IMX_IOMUXC_EIM_DA8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA9_ALT0_EIM_AD09 = 0,
+  IMX_IOMUXC_EIM_DA9_ALT1_IPU1_DISP1_DATA00 = 1,
+  IMX_IOMUXC_EIM_DA9_ALT2_IPU2_CSI1_DATA00 = 2,
+  IMX_IOMUXC_EIM_DA9_ALT5_GPIO3_IO09 = 5,
+  IMX_IOMUXC_EIM_DA9_ALT7_SRC_BOOT_CFG09 = 7,
+} IMX_IOMUXC_EIM_DA9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA10_ALT0_EIM_AD10 = 0,
+  IMX_IOMUXC_EIM_DA10_ALT1_IPU1_DI1_PIN15 = 1,
+  IMX_IOMUXC_EIM_DA10_ALT2_IPU2_CSI1_DATA_EN = 2,
+  IMX_IOMUXC_EIM_DA10_ALT5_GPIO3_IO10 = 5,
+  IMX_IOMUXC_EIM_DA10_ALT7_SRC_BOOT_CFG10 = 7,
+} IMX_IOMUXC_EIM_DA10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA11_ALT0_EIM_AD11 = 0,
+  IMX_IOMUXC_EIM_DA11_ALT1_IPU1_DI1_PIN02 = 1,
+  IMX_IOMUXC_EIM_DA11_ALT2_IPU2_CSI1_HSYNC = 2,
+  IMX_IOMUXC_EIM_DA11_ALT5_GPIO3_IO11 = 5,
+  IMX_IOMUXC_EIM_DA11_ALT7_SRC_BOOT_CFG11 = 7,
+} IMX_IOMUXC_EIM_DA11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA12_ALT0_EIM_AD12 = 0,
+  IMX_IOMUXC_EIM_DA12_ALT1_IPU1_DI1_PIN03 = 1,
+  IMX_IOMUXC_EIM_DA12_ALT2_IPU2_CSI1_VSYNC = 2,
+  IMX_IOMUXC_EIM_DA12_ALT5_GPIO3_IO12 = 5,
+  IMX_IOMUXC_EIM_DA12_ALT7_SRC_BOOT_CFG12 = 7,
+} IMX_IOMUXC_EIM_DA12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA13_ALT0_EIM_AD13 = 0,
+  IMX_IOMUXC_EIM_DA13_ALT1_IPU1_DI1_D0_CS = 1,
+  IMX_IOMUXC_EIM_DA13_ALT5_GPIO3_IO13 = 5,
+  IMX_IOMUXC_EIM_DA13_ALT7_SRC_BOOT_CFG13 = 7,
+} IMX_IOMUXC_EIM_DA13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA14_ALT0_EIM_AD14 = 0,
+  IMX_IOMUXC_EIM_DA14_ALT1_IPU1_DI1_D1_CS = 1,
+  IMX_IOMUXC_EIM_DA14_ALT5_GPIO3_IO14 = 5,
+  IMX_IOMUXC_EIM_DA14_ALT7_SRC_BOOT_CFG14 = 7,
+} IMX_IOMUXC_EIM_DA14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA15_ALT0_EIM_AD15 = 0,
+  IMX_IOMUXC_EIM_DA15_ALT1_IPU1_DI1_PIN01 = 1,
+  IMX_IOMUXC_EIM_DA15_ALT2_IPU1_DI1_PIN04 = 2,
+  IMX_IOMUXC_EIM_DA15_ALT5_GPIO3_IO15 = 5,
+  IMX_IOMUXC_EIM_DA15_ALT7_SRC_BOOT_CFG15 = 7,
+} IMX_IOMUXC_EIM_DA15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D16_ALT0_EIM_DATA16 = 0,
+  IMX_IOMUXC_EIM_D16_ALT1_ECSPI1_SCLK = 1,
+  IMX_IOMUXC_EIM_D16_ALT2_IPU1_DI0_PIN05 = 2,
+  IMX_IOMUXC_EIM_D16_ALT3_IPU2_CSI1_DATA18 = 3,
+  IMX_IOMUXC_EIM_D16_ALT4_HDMI_TX_DDC_SDA = 4,
+  IMX_IOMUXC_EIM_D16_ALT5_GPIO3_IO16 = 5,
+  IMX_IOMUXC_EIM_D16_ALT6_I2C2_SDA = 6,
+} IMX_IOMUXC_EIM_D16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D17_ALT0_EIM_DATA17 = 0,
+  IMX_IOMUXC_EIM_D17_ALT1_ECSPI1_MISO = 1,
+  IMX_IOMUXC_EIM_D17_ALT2_IPU1_DI0_PIN06 = 2,
+  IMX_IOMUXC_EIM_D17_ALT3_IPU2_CSI1_PIXCLK = 3,
+  IMX_IOMUXC_EIM_D17_ALT4_DCIC1_OUT = 4,
+  IMX_IOMUXC_EIM_D17_ALT5_GPIO3_IO17 = 5,
+  IMX_IOMUXC_EIM_D17_ALT6_I2C3_SCL = 6,
+} IMX_IOMUXC_EIM_D17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D18_ALT0_EIM_DATA18 = 0,
+  IMX_IOMUXC_EIM_D18_ALT1_ECSPI1_MOSI = 1,
+  IMX_IOMUXC_EIM_D18_ALT2_IPU1_DI0_PIN07 = 2,
+  IMX_IOMUXC_EIM_D18_ALT3_IPU2_CSI1_DATA17 = 3,
+  IMX_IOMUXC_EIM_D18_ALT4_IPU1_DI1_D0_CS = 4,
+  IMX_IOMUXC_EIM_D18_ALT5_GPIO3_IO18 = 5,
+  IMX_IOMUXC_EIM_D18_ALT6_I2C3_SDA = 6,
+} IMX_IOMUXC_EIM_D18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D19_ALT0_EIM_DATA19 = 0,
+  IMX_IOMUXC_EIM_D19_ALT1_ECSPI1_SS1 = 1,
+  IMX_IOMUXC_EIM_D19_ALT2_IPU1_DI0_PIN08 = 2,
+  IMX_IOMUXC_EIM_D19_ALT3_IPU2_CSI1_DATA16 = 3,
+  IMX_IOMUXC_EIM_D19_ALT4_UART1_CTS_B = 4,
+  IMX_IOMUXC_EIM_D19_ALT5_GPIO3_IO19 = 5,
+  IMX_IOMUXC_EIM_D19_ALT6_EPIT1_OUT = 6,
+} IMX_IOMUXC_EIM_D19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D20_ALT0_EIM_DATA20 = 0,
+  IMX_IOMUXC_EIM_D20_ALT1_ECSPI4_SS0 = 1,
+  IMX_IOMUXC_EIM_D20_ALT2_IPU1_DI0_PIN16 = 2,
+  IMX_IOMUXC_EIM_D20_ALT3_IPU2_CSI1_DATA15 = 3,
+  IMX_IOMUXC_EIM_D20_ALT4_UART1_RTS_B = 4,
+  IMX_IOMUXC_EIM_D20_ALT5_GPIO3_IO20 = 5,
+  IMX_IOMUXC_EIM_D20_ALT6_EPIT2_OUT = 6,
+} IMX_IOMUXC_EIM_D20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D21_ALT0_EIM_DATA21 = 0,
+  IMX_IOMUXC_EIM_D21_ALT1_ECSPI4_SCLK = 1,
+  IMX_IOMUXC_EIM_D21_ALT2_IPU1_DI0_PIN17 = 2,
+  IMX_IOMUXC_EIM_D21_ALT3_IPU2_CSI1_DATA11 = 3,
+  IMX_IOMUXC_EIM_D21_ALT4_USB_OTG_OC = 4,
+  IMX_IOMUXC_EIM_D21_ALT5_GPIO3_IO21 = 5,
+  IMX_IOMUXC_EIM_D21_ALT6_I2C1_SCL = 6,
+  IMX_IOMUXC_EIM_D21_ALT7_SPDIF_IN = 7,
+} IMX_IOMUXC_EIM_D21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D22_ALT0_EIM_DATA22 = 0,
+  IMX_IOMUXC_EIM_D22_ALT1_ECSPI4_MISO = 1,
+  IMX_IOMUXC_EIM_D22_ALT2_IPU1_DI0_PIN01 = 2,
+  IMX_IOMUXC_EIM_D22_ALT3_IPU2_CSI1_DATA10 = 3,
+  IMX_IOMUXC_EIM_D22_ALT4_USB_OTG_PWR = 4,
+  IMX_IOMUXC_EIM_D22_ALT5_GPIO3_IO22 = 5,
+  IMX_IOMUXC_EIM_D22_ALT6_SPDIF_OUT = 6,
+} IMX_IOMUXC_EIM_D22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D23_ALT0_EIM_DATA23 = 0,
+  IMX_IOMUXC_EIM_D23_ALT1_IPU1_DI0_D0_CS = 1,
+  IMX_IOMUXC_EIM_D23_ALT2_UART3_CTS_B = 2,
+  IMX_IOMUXC_EIM_D23_ALT3_UART1_DCD_B = 3,
+  IMX_IOMUXC_EIM_D23_ALT4_IPU2_CSI1_DATA_EN = 4,
+  IMX_IOMUXC_EIM_D23_ALT5_GPIO3_IO23 = 5,
+  IMX_IOMUXC_EIM_D23_ALT6_IPU1_DI1_PIN02 = 6,
+  IMX_IOMUXC_EIM_D23_ALT7_IPU1_DI1_PIN14 = 7,
+} IMX_IOMUXC_EIM_D23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D24_ALT0_EIM_DATA24 = 0,
+  IMX_IOMUXC_EIM_D24_ALT1_ECSPI4_SS2 = 1,
+  IMX_IOMUXC_EIM_D24_ALT2_UART3_TX_DATA = 2,
+  IMX_IOMUXC_EIM_D24_ALT3_ECSPI1_SS2 = 3,
+  IMX_IOMUXC_EIM_D24_ALT4_ECSPI2_SS2 = 4,
+  IMX_IOMUXC_EIM_D24_ALT5_GPIO3_IO24 = 5,
+  IMX_IOMUXC_EIM_D24_ALT6_AUD5_RXFS = 6,
+  IMX_IOMUXC_EIM_D24_ALT7_UART1_DTR_B = 7,
+} IMX_IOMUXC_EIM_D24_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D25_ALT0_EIM_DATA25 = 0,
+  IMX_IOMUXC_EIM_D25_ALT1_ECSPI4_SS3 = 1,
+  IMX_IOMUXC_EIM_D25_ALT2_UART3_RX_DATA = 2,
+  IMX_IOMUXC_EIM_D25_ALT3_ECSPI1_SS3 = 3,
+  IMX_IOMUXC_EIM_D25_ALT4_ECSPI2_SS3 = 4,
+  IMX_IOMUXC_EIM_D25_ALT5_GPIO3_IO25 = 5,
+  IMX_IOMUXC_EIM_D25_ALT6_AUD5_RXC = 6,
+  IMX_IOMUXC_EIM_D25_ALT7_UART1_DSR_B = 7,
+} IMX_IOMUXC_EIM_D25_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D26_ALT0_EIM_DATA26 = 0,
+  IMX_IOMUXC_EIM_D26_ALT1_IPU1_DI1_PIN11 = 1,
+  IMX_IOMUXC_EIM_D26_ALT2_IPU1_CSI0_DATA01 = 2,
+  IMX_IOMUXC_EIM_D26_ALT3_IPU2_CSI1_DATA14 = 3,
+  IMX_IOMUXC_EIM_D26_ALT4_UART2_TX_DATA = 4,
+  IMX_IOMUXC_EIM_D26_ALT5_GPIO3_IO26 = 5,
+  IMX_IOMUXC_EIM_D26_ALT6_IPU1_SISG2 = 6,
+  IMX_IOMUXC_EIM_D26_ALT7_IPU1_DISP1_DATA22 = 7,
+} IMX_IOMUXC_EIM_D26_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D27_ALT0_EIM_DATA27 = 0,
+  IMX_IOMUXC_EIM_D27_ALT1_IPU1_DI1_PIN13 = 1,
+  IMX_IOMUXC_EIM_D27_ALT2_IPU1_CSI0_DATA00 = 2,
+  IMX_IOMUXC_EIM_D27_ALT3_IPU2_CSI1_DATA13 = 3,
+  IMX_IOMUXC_EIM_D27_ALT4_UART2_RX_DATA = 4,
+  IMX_IOMUXC_EIM_D27_ALT5_GPIO3_IO27 = 5,
+  IMX_IOMUXC_EIM_D27_ALT6_IPU1_SISG3 = 6,
+  IMX_IOMUXC_EIM_D27_ALT7_IPU1_DISP1_DATA23 = 7,
+} IMX_IOMUXC_EIM_D27_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D28_ALT0_EIM_DATA28 = 0,
+  IMX_IOMUXC_EIM_D28_ALT1_I2C1_SDA = 1,
+  IMX_IOMUXC_EIM_D28_ALT2_ECSPI4_MOSI = 2,
+  IMX_IOMUXC_EIM_D28_ALT3_IPU2_CSI1_DATA12 = 3,
+  IMX_IOMUXC_EIM_D28_ALT4_UART2_CTS_B = 4,
+  IMX_IOMUXC_EIM_D28_ALT5_GPIO3_IO28 = 5,
+  IMX_IOMUXC_EIM_D28_ALT6_IPU1_EXT_TRIG = 6,
+  IMX_IOMUXC_EIM_D28_ALT7_IPU1_DI0_PIN13 = 7,
+} IMX_IOMUXC_EIM_D28_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D29_ALT0_EIM_DATA29 = 0,
+  IMX_IOMUXC_EIM_D29_ALT1_IPU1_DI1_PIN15 = 1,
+  IMX_IOMUXC_EIM_D29_ALT2_ECSPI4_SS0 = 2,
+  IMX_IOMUXC_EIM_D29_ALT4_UART2_RTS_B = 4,
+  IMX_IOMUXC_EIM_D29_ALT5_GPIO3_IO29 = 5,
+  IMX_IOMUXC_EIM_D29_ALT6_IPU2_CSI1_VSYNC = 6,
+  IMX_IOMUXC_EIM_D29_ALT7_IPU1_DI0_PIN14 = 7,
+} IMX_IOMUXC_EIM_D29_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D30_ALT0_EIM_DATA30 = 0,
+  IMX_IOMUXC_EIM_D30_ALT1_IPU1_DISP1_DATA21 = 1,
+  IMX_IOMUXC_EIM_D30_ALT2_IPU1_DI0_PIN11 = 2,
+  IMX_IOMUXC_EIM_D30_ALT3_IPU1_CSI0_DATA03 = 3,
+  IMX_IOMUXC_EIM_D30_ALT4_UART3_CTS_B = 4,
+  IMX_IOMUXC_EIM_D30_ALT5_GPIO3_IO30 = 5,
+  IMX_IOMUXC_EIM_D30_ALT6_USB_H1_OC = 6,
+} IMX_IOMUXC_EIM_D30_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D31_ALT0_EIM_DATA31 = 0,
+  IMX_IOMUXC_EIM_D31_ALT1_IPU1_DISP1_DATA20 = 1,
+  IMX_IOMUXC_EIM_D31_ALT2_IPU1_DI0_PIN12 = 2,
+  IMX_IOMUXC_EIM_D31_ALT3_IPU1_CSI0_DATA02 = 3,
+  IMX_IOMUXC_EIM_D31_ALT4_UART3_RTS_B = 4,
+  IMX_IOMUXC_EIM_D31_ALT5_GPIO3_IO31 = 5,
+  IMX_IOMUXC_EIM_D31_ALT6_USB_H1_PWR = 6,
+} IMX_IOMUXC_EIM_D31_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_19_ALT0_KEY_COL5 = 0,
+  IMX_IOMUXC_GPIO_19_ALT1_ENET_1588_EVENT0_OUT = 1,
+  IMX_IOMUXC_GPIO_19_ALT2_SPDIF_OUT = 2,
+  IMX_IOMUXC_GPIO_19_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_GPIO_19_ALT4_ECSPI1_RDY = 4,
+  IMX_IOMUXC_GPIO_19_ALT5_GPIO4_IO05 = 5,
+  IMX_IOMUXC_GPIO_19_ALT6_ENET_TX_ER = 6,
+} IMX_IOMUXC_GPIO_19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL0_ALT0_ECSPI1_SCLK = 0,
+  IMX_IOMUXC_KEY_COL0_ALT1_ENET_RX_DATA3 = 1,
+  IMX_IOMUXC_KEY_COL0_ALT2_AUD5_TXC = 2,
+  IMX_IOMUXC_KEY_COL0_ALT3_KEY_COL0 = 3,
+  IMX_IOMUXC_KEY_COL0_ALT4_UART4_TX_DATA = 4,
+  IMX_IOMUXC_KEY_COL0_ALT5_GPIO4_IO06 = 5,
+  IMX_IOMUXC_KEY_COL0_ALT6_DCIC1_OUT = 6,
+} IMX_IOMUXC_KEY_COL0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW0_ALT0_ECSPI1_MOSI = 0,
+  IMX_IOMUXC_KEY_ROW0_ALT1_ENET_TX_DATA3 = 1,
+  IMX_IOMUXC_KEY_ROW0_ALT2_AUD5_TXD = 2,
+  IMX_IOMUXC_KEY_ROW0_ALT3_KEY_ROW0 = 3,
+  IMX_IOMUXC_KEY_ROW0_ALT4_UART4_RX_DATA = 4,
+  IMX_IOMUXC_KEY_ROW0_ALT5_GPIO4_IO07 = 5,
+  IMX_IOMUXC_KEY_ROW0_ALT6_DCIC2_OUT = 6,
+} IMX_IOMUXC_KEY_ROW0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL1_ALT0_ECSPI1_MISO = 0,
+  IMX_IOMUXC_KEY_COL1_ALT1_ENET_MDIO = 1,
+  IMX_IOMUXC_KEY_COL1_ALT2_AUD5_TXFS = 2,
+  IMX_IOMUXC_KEY_COL1_ALT3_KEY_COL1 = 3,
+  IMX_IOMUXC_KEY_COL1_ALT4_UART5_TX_DATA = 4,
+  IMX_IOMUXC_KEY_COL1_ALT5_GPIO4_IO08 = 5,
+  IMX_IOMUXC_KEY_COL1_ALT6_SD1_VSELECT = 6,
+} IMX_IOMUXC_KEY_COL1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW1_ALT0_ECSPI1_SS0 = 0,
+  IMX_IOMUXC_KEY_ROW1_ALT1_ENET_COL = 1,
+  IMX_IOMUXC_KEY_ROW1_ALT2_AUD5_RXD = 2,
+  IMX_IOMUXC_KEY_ROW1_ALT3_KEY_ROW1 = 3,
+  IMX_IOMUXC_KEY_ROW1_ALT4_UART5_RX_DATA = 4,
+  IMX_IOMUXC_KEY_ROW1_ALT5_GPIO4_IO09 = 5,
+  IMX_IOMUXC_KEY_ROW1_ALT6_SD2_VSELECT = 6,
+} IMX_IOMUXC_KEY_ROW1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL2_ALT0_ECSPI1_SS1 = 0,
+  IMX_IOMUXC_KEY_COL2_ALT1_ENET_RX_DATA2 = 1,
+  IMX_IOMUXC_KEY_COL2_ALT2_FLEXCAN1_TX = 2,
+  IMX_IOMUXC_KEY_COL2_ALT3_KEY_COL2 = 3,
+  IMX_IOMUXC_KEY_COL2_ALT4_ENET_MDC = 4,
+  IMX_IOMUXC_KEY_COL2_ALT5_GPIO4_IO10 = 5,
+  IMX_IOMUXC_KEY_COL2_ALT6_USB_H1_PWR_CTL_WAKE = 6,
+} IMX_IOMUXC_KEY_COL2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW2_ALT0_ECSPI1_SS2 = 0,
+  IMX_IOMUXC_KEY_ROW2_ALT1_ENET_TX_DATA2 = 1,
+  IMX_IOMUXC_KEY_ROW2_ALT2_FLEXCAN1_RX = 2,
+  IMX_IOMUXC_KEY_ROW2_ALT3_KEY_ROW2 = 3,
+  IMX_IOMUXC_KEY_ROW2_ALT4_SD2_VSELECT = 4,
+  IMX_IOMUXC_KEY_ROW2_ALT5_GPIO4_IO11 = 5,
+  IMX_IOMUXC_KEY_ROW2_ALT6_HDMI_TX_CEC_LINE = 6,
+} IMX_IOMUXC_KEY_ROW2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL3_ALT0_ECSPI1_SS3 = 0,
+  IMX_IOMUXC_KEY_COL3_ALT1_ENET_CRS = 1,
+  IMX_IOMUXC_KEY_COL3_ALT2_HDMI_TX_DDC_SCL = 2,
+  IMX_IOMUXC_KEY_COL3_ALT3_KEY_COL3 = 3,
+  IMX_IOMUXC_KEY_COL3_ALT4_I2C2_SCL = 4,
+  IMX_IOMUXC_KEY_COL3_ALT5_GPIO4_IO12 = 5,
+  IMX_IOMUXC_KEY_COL3_ALT6_SPDIF_IN = 6,
+} IMX_IOMUXC_KEY_COL3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW3_ALT0_XTALOSC_OSC32K_32K_OUT = 0,
+  IMX_IOMUXC_KEY_ROW3_ALT1_ASRC_EXT_CLK = 1,
+  IMX_IOMUXC_KEY_ROW3_ALT2_HDMI_TX_DDC_SDA = 2,
+  IMX_IOMUXC_KEY_ROW3_ALT3_KEY_ROW3 = 3,
+  IMX_IOMUXC_KEY_ROW3_ALT4_I2C2_SDA = 4,
+  IMX_IOMUXC_KEY_ROW3_ALT5_GPIO4_IO13 = 5,
+  IMX_IOMUXC_KEY_ROW3_ALT6_SD1_VSELECT = 6,
+} IMX_IOMUXC_KEY_ROW3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL4_ALT0_FLEXCAN2_TX = 0,
+  IMX_IOMUXC_KEY_COL4_ALT1_IPU1_SISG4 = 1,
+  IMX_IOMUXC_KEY_COL4_ALT2_USB_OTG_OC = 2,
+  IMX_IOMUXC_KEY_COL4_ALT3_KEY_COL4 = 3,
+  IMX_IOMUXC_KEY_COL4_ALT4_UART5_RTS_B = 4,
+  IMX_IOMUXC_KEY_COL4_ALT5_GPIO4_IO14 = 5,
+} IMX_IOMUXC_KEY_COL4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW4_ALT0_FLEXCAN2_RX = 0,
+  IMX_IOMUXC_KEY_ROW4_ALT1_IPU1_SISG5 = 1,
+  IMX_IOMUXC_KEY_ROW4_ALT2_USB_OTG_PWR = 2,
+  IMX_IOMUXC_KEY_ROW4_ALT3_KEY_ROW4 = 3,
+  IMX_IOMUXC_KEY_ROW4_ALT4_UART5_CTS_B = 4,
+  IMX_IOMUXC_KEY_ROW4_ALT5_GPIO4_IO15 = 5,
+} IMX_IOMUXC_KEY_ROW4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_DISP_CLK_ALT0_IPU1_DI0_DISP_CLK = 0,
+  IMX_IOMUXC_DI0_DISP_CLK_ALT1_IPU2_DI0_DISP_CLK = 1,
+  IMX_IOMUXC_DI0_DISP_CLK_ALT5_GPIO4_IO16 = 5,
+} IMX_IOMUXC_DI0_DISP_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN15_ALT0_IPU1_DI0_PIN15 = 0,
+  IMX_IOMUXC_DI0_PIN15_ALT1_IPU2_DI0_PIN15 = 1,
+  IMX_IOMUXC_DI0_PIN15_ALT2_AUD6_TXC = 2,
+  IMX_IOMUXC_DI0_PIN15_ALT5_GPIO4_IO17 = 5,
+} IMX_IOMUXC_DI0_PIN15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN2_ALT0_IPU1_DI0_PIN02 = 0,
+  IMX_IOMUXC_DI0_PIN2_ALT1_IPU2_DI0_PIN02 = 1,
+  IMX_IOMUXC_DI0_PIN2_ALT2_AUD6_TXD = 2,
+  IMX_IOMUXC_DI0_PIN2_ALT5_GPIO4_IO18 = 5,
+} IMX_IOMUXC_DI0_PIN2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN3_ALT0_IPU1_DI0_PIN03 = 0,
+  IMX_IOMUXC_DI0_PIN3_ALT1_IPU2_DI0_PIN03 = 1,
+  IMX_IOMUXC_DI0_PIN3_ALT2_AUD6_TXFS = 2,
+  IMX_IOMUXC_DI0_PIN3_ALT5_GPIO4_IO19 = 5,
+} IMX_IOMUXC_DI0_PIN3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN4_ALT0_IPU1_DI0_PIN04 = 0,
+  IMX_IOMUXC_DI0_PIN4_ALT1_IPU2_DI0_PIN04 = 1,
+  IMX_IOMUXC_DI0_PIN4_ALT2_AUD6_RXD = 2,
+  IMX_IOMUXC_DI0_PIN4_ALT3_SD1_WP = 3,
+  IMX_IOMUXC_DI0_PIN4_ALT5_GPIO4_IO20 = 5,
+} IMX_IOMUXC_DI0_PIN4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT0_ALT0_IPU1_DISP0_DATA00 = 0,
+  IMX_IOMUXC_DISP0_DAT0_ALT1_IPU2_DISP0_DATA00 = 1,
+  IMX_IOMUXC_DISP0_DAT0_ALT2_ECSPI3_SCLK = 2,
+  IMX_IOMUXC_DISP0_DAT0_ALT5_GPIO4_IO21 = 5,
+} IMX_IOMUXC_DISP0_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT1_ALT0_IPU1_DISP0_DATA01 = 0,
+  IMX_IOMUXC_DISP0_DAT1_ALT1_IPU2_DISP0_DATA01 = 1,
+  IMX_IOMUXC_DISP0_DAT1_ALT2_ECSPI3_MOSI = 2,
+  IMX_IOMUXC_DISP0_DAT1_ALT5_GPIO4_IO22 = 5,
+} IMX_IOMUXC_DISP0_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT2_ALT0_IPU1_DISP0_DATA02 = 0,
+  IMX_IOMUXC_DISP0_DAT2_ALT1_IPU2_DISP0_DATA02 = 1,
+  IMX_IOMUXC_DISP0_DAT2_ALT2_ECSPI3_MISO = 2,
+  IMX_IOMUXC_DISP0_DAT2_ALT5_GPIO4_IO23 = 5,
+} IMX_IOMUXC_DISP0_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT3_ALT0_IPU1_DISP0_DATA03 = 0,
+  IMX_IOMUXC_DISP0_DAT3_ALT1_IPU2_DISP0_DATA03 = 1,
+  IMX_IOMUXC_DISP0_DAT3_ALT2_ECSPI3_SS0 = 2,
+  IMX_IOMUXC_DISP0_DAT3_ALT5_GPIO4_IO24 = 5,
+} IMX_IOMUXC_DISP0_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT4_ALT0_IPU1_DISP0_DATA04 = 0,
+  IMX_IOMUXC_DISP0_DAT4_ALT1_IPU2_DISP0_DATA04 = 1,
+  IMX_IOMUXC_DISP0_DAT4_ALT2_ECSPI3_SS1 = 2,
+  IMX_IOMUXC_DISP0_DAT4_ALT5_GPIO4_IO25 = 5,
+} IMX_IOMUXC_DISP0_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT5_ALT0_IPU1_DISP0_DATA05 = 0,
+  IMX_IOMUXC_DISP0_DAT5_ALT1_IPU2_DISP0_DATA05 = 1,
+  IMX_IOMUXC_DISP0_DAT5_ALT2_ECSPI3_SS2 = 2,
+  IMX_IOMUXC_DISP0_DAT5_ALT3_AUD6_RXFS = 3,
+  IMX_IOMUXC_DISP0_DAT5_ALT5_GPIO4_IO26 = 5,
+} IMX_IOMUXC_DISP0_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT6_ALT0_IPU1_DISP0_DATA06 = 0,
+  IMX_IOMUXC_DISP0_DAT6_ALT1_IPU2_DISP0_DATA06 = 1,
+  IMX_IOMUXC_DISP0_DAT6_ALT2_ECSPI3_SS3 = 2,
+  IMX_IOMUXC_DISP0_DAT6_ALT3_AUD6_RXC = 3,
+  IMX_IOMUXC_DISP0_DAT6_ALT5_GPIO4_IO27 = 5,
+} IMX_IOMUXC_DISP0_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT7_ALT0_IPU1_DISP0_DATA07 = 0,
+  IMX_IOMUXC_DISP0_DAT7_ALT1_IPU2_DISP0_DATA07 = 1,
+  IMX_IOMUXC_DISP0_DAT7_ALT2_ECSPI3_RDY = 2,
+  IMX_IOMUXC_DISP0_DAT7_ALT5_GPIO4_IO28 = 5,
+} IMX_IOMUXC_DISP0_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT8_ALT0_IPU1_DISP0_DATA08 = 0,
+  IMX_IOMUXC_DISP0_DAT8_ALT1_IPU2_DISP0_DATA08 = 1,
+  IMX_IOMUXC_DISP0_DAT8_ALT2_PWM1_OUT = 2,
+  IMX_IOMUXC_DISP0_DAT8_ALT3_WDOG1_B = 3,
+  IMX_IOMUXC_DISP0_DAT8_ALT5_GPIO4_IO29 = 5,
+} IMX_IOMUXC_DISP0_DAT8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT9_ALT0_IPU1_DISP0_DATA09 = 0,
+  IMX_IOMUXC_DISP0_DAT9_ALT1_IPU2_DISP0_DATA09 = 1,
+  IMX_IOMUXC_DISP0_DAT9_ALT2_PWM2_OUT = 2,
+  IMX_IOMUXC_DISP0_DAT9_ALT3_WDOG2_B = 3,
+  IMX_IOMUXC_DISP0_DAT9_ALT5_GPIO4_IO30 = 5,
+} IMX_IOMUXC_DISP0_DAT9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT10_ALT0_IPU1_DISP0_DATA10 = 0,
+  IMX_IOMUXC_DISP0_DAT10_ALT1_IPU2_DISP0_DATA10 = 1,
+  IMX_IOMUXC_DISP0_DAT10_ALT5_GPIO4_IO31 = 5,
+} IMX_IOMUXC_DISP0_DAT10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_WAIT_ALT0_EIM_WAIT_B = 0,
+  IMX_IOMUXC_EIM_WAIT_ALT1_EIM_DTACK_B = 1,
+  IMX_IOMUXC_EIM_WAIT_ALT5_GPIO5_IO00 = 5,
+  IMX_IOMUXC_EIM_WAIT_ALT7_SRC_BOOT_CFG25 = 7,
+} IMX_IOMUXC_EIM_WAIT_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A25_ALT0_EIM_ADDR25 = 0,
+  IMX_IOMUXC_EIM_A25_ALT1_ECSPI4_SS1 = 1,
+  IMX_IOMUXC_EIM_A25_ALT2_ECSPI2_RDY = 2,
+  IMX_IOMUXC_EIM_A25_ALT3_IPU1_DI1_PIN12 = 3,
+  IMX_IOMUXC_EIM_A25_ALT4_IPU1_DI0_D1_CS = 4,
+  IMX_IOMUXC_EIM_A25_ALT5_GPIO5_IO02 = 5,
+  IMX_IOMUXC_EIM_A25_ALT6_HDMI_TX_CEC_LINE = 6,
+} IMX_IOMUXC_EIM_A25_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A24_ALT0_EIM_ADDR24 = 0,
+  IMX_IOMUXC_EIM_A24_ALT1_IPU1_DISP1_DATA19 = 1,
+  IMX_IOMUXC_EIM_A24_ALT2_IPU2_CSI1_DATA19 = 2,
+  IMX_IOMUXC_EIM_A24_ALT3_IPU2_SISG2 = 3,
+  IMX_IOMUXC_EIM_A24_ALT4_IPU1_SISG2 = 4,
+  IMX_IOMUXC_EIM_A24_ALT5_GPIO5_IO04 = 5,
+  IMX_IOMUXC_EIM_A24_ALT7_SRC_BOOT_CFG24 = 7,
+} IMX_IOMUXC_EIM_A24_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT11_ALT0_IPU1_DISP0_DATA11 = 0,
+  IMX_IOMUXC_DISP0_DAT11_ALT1_IPU2_DISP0_DATA11 = 1,
+  IMX_IOMUXC_DISP0_DAT11_ALT5_GPIO5_IO05 = 5,
+} IMX_IOMUXC_DISP0_DAT11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT12_ALT0_IPU1_DISP0_DATA12 = 0,
+  IMX_IOMUXC_DISP0_DAT12_ALT1_IPU2_DISP0_DATA12 = 1,
+  IMX_IOMUXC_DISP0_DAT12_ALT5_GPIO5_IO06 = 5,
+} IMX_IOMUXC_DISP0_DAT12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT13_ALT0_IPU1_DISP0_DATA13 = 0,
+  IMX_IOMUXC_DISP0_DAT13_ALT1_IPU2_DISP0_DATA13 = 1,
+  IMX_IOMUXC_DISP0_DAT13_ALT3_AUD5_RXFS = 3,
+  IMX_IOMUXC_DISP0_DAT13_ALT5_GPIO5_IO07 = 5,
+} IMX_IOMUXC_DISP0_DAT13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT14_ALT0_IPU1_DISP0_DATA14 = 0,
+  IMX_IOMUXC_DISP0_DAT14_ALT1_IPU2_DISP0_DATA14 = 1,
+  IMX_IOMUXC_DISP0_DAT14_ALT3_AUD5_RXC = 3,
+  IMX_IOMUXC_DISP0_DAT14_ALT5_GPIO5_IO08 = 5,
+} IMX_IOMUXC_DISP0_DAT14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT15_ALT0_IPU1_DISP0_DATA15 = 0,
+  IMX_IOMUXC_DISP0_DAT15_ALT1_IPU2_DISP0_DATA15 = 1,
+  IMX_IOMUXC_DISP0_DAT15_ALT2_ECSPI1_SS1 = 2,
+  IMX_IOMUXC_DISP0_DAT15_ALT3_ECSPI2_SS1 = 3,
+  IMX_IOMUXC_DISP0_DAT15_ALT5_GPIO5_IO09 = 5,
+} IMX_IOMUXC_DISP0_DAT15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT16_ALT0_IPU1_DISP0_DATA16 = 0,
+  IMX_IOMUXC_DISP0_DAT16_ALT1_IPU2_DISP0_DATA16 = 1,
+  IMX_IOMUXC_DISP0_DAT16_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_DISP0_DAT16_ALT3_AUD5_TXC = 3,
+  IMX_IOMUXC_DISP0_DAT16_ALT4_SDMA_EXT_EVENT0 = 4,
+  IMX_IOMUXC_DISP0_DAT16_ALT5_GPIO5_IO10 = 5,
+} IMX_IOMUXC_DISP0_DAT16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT17_ALT0_IPU1_DISP0_DATA17 = 0,
+  IMX_IOMUXC_DISP0_DAT17_ALT1_IPU2_DISP0_DATA17 = 1,
+  IMX_IOMUXC_DISP0_DAT17_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_DISP0_DAT17_ALT3_AUD5_TXD = 3,
+  IMX_IOMUXC_DISP0_DAT17_ALT4_SDMA_EXT_EVENT1 = 4,
+  IMX_IOMUXC_DISP0_DAT17_ALT5_GPIO5_IO11 = 5,
+} IMX_IOMUXC_DISP0_DAT17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT18_ALT0_IPU1_DISP0_DATA18 = 0,
+  IMX_IOMUXC_DISP0_DAT18_ALT1_IPU2_DISP0_DATA18 = 1,
+  IMX_IOMUXC_DISP0_DAT18_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_DISP0_DAT18_ALT3_AUD5_TXFS = 3,
+  IMX_IOMUXC_DISP0_DAT18_ALT4_AUD4_RXFS = 4,
+  IMX_IOMUXC_DISP0_DAT18_ALT5_GPIO5_IO12 = 5,
+  IMX_IOMUXC_DISP0_DAT18_ALT7_EIM_CS2_B = 7,
+} IMX_IOMUXC_DISP0_DAT18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT19_ALT0_IPU1_DISP0_DATA19 = 0,
+  IMX_IOMUXC_DISP0_DAT19_ALT1_IPU2_DISP0_DATA19 = 1,
+  IMX_IOMUXC_DISP0_DAT19_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_DISP0_DAT19_ALT3_AUD5_RXD = 3,
+  IMX_IOMUXC_DISP0_DAT19_ALT4_AUD4_RXC = 4,
+  IMX_IOMUXC_DISP0_DAT19_ALT5_GPIO5_IO13 = 5,
+  IMX_IOMUXC_DISP0_DAT19_ALT7_EIM_CS3_B = 7,
+} IMX_IOMUXC_DISP0_DAT19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT20_ALT0_IPU1_DISP0_DATA20 = 0,
+  IMX_IOMUXC_DISP0_DAT20_ALT1_IPU2_DISP0_DATA20 = 1,
+  IMX_IOMUXC_DISP0_DAT20_ALT2_ECSPI1_SCLK = 2,
+  IMX_IOMUXC_DISP0_DAT20_ALT3_AUD4_TXC = 3,
+  IMX_IOMUXC_DISP0_DAT20_ALT5_GPIO5_IO14 = 5,
+} IMX_IOMUXC_DISP0_DAT20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT21_ALT0_IPU1_DISP0_DATA21 = 0,
+  IMX_IOMUXC_DISP0_DAT21_ALT1_IPU2_DISP0_DATA21 = 1,
+  IMX_IOMUXC_DISP0_DAT21_ALT2_ECSPI1_MOSI = 2,
+  IMX_IOMUXC_DISP0_DAT21_ALT3_AUD4_TXD = 3,
+  IMX_IOMUXC_DISP0_DAT21_ALT5_GPIO5_IO15 = 5,
+} IMX_IOMUXC_DISP0_DAT21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT22_ALT0_IPU1_DISP0_DATA22 = 0,
+  IMX_IOMUXC_DISP0_DAT22_ALT1_IPU2_DISP0_DATA22 = 1,
+  IMX_IOMUXC_DISP0_DAT22_ALT2_ECSPI1_MISO = 2,
+  IMX_IOMUXC_DISP0_DAT22_ALT3_AUD4_TXFS = 3,
+  IMX_IOMUXC_DISP0_DAT22_ALT5_GPIO5_IO16 = 5,
+} IMX_IOMUXC_DISP0_DAT22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT23_ALT0_IPU1_DISP0_DATA23 = 0,
+  IMX_IOMUXC_DISP0_DAT23_ALT1_IPU2_DISP0_DATA23 = 1,
+  IMX_IOMUXC_DISP0_DAT23_ALT2_ECSPI1_SS0 = 2,
+  IMX_IOMUXC_DISP0_DAT23_ALT3_AUD4_RXD = 3,
+  IMX_IOMUXC_DISP0_DAT23_ALT5_GPIO5_IO17 = 5,
+} IMX_IOMUXC_DISP0_DAT23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_PIXCLK_ALT0_IPU1_CSI0_PIXCLK = 0,
+  IMX_IOMUXC_CSI0_PIXCLK_ALT5_GPIO5_IO18 = 5,
+  IMX_IOMUXC_CSI0_PIXCLK_ALT7_ARM_EVENTO = 7,
+} IMX_IOMUXC_CSI0_PIXCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_MCLK_ALT0_IPU1_CSI0_HSYNC = 0,
+  IMX_IOMUXC_CSI0_MCLK_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_CSI0_MCLK_ALT5_GPIO5_IO19 = 5,
+  IMX_IOMUXC_CSI0_MCLK_ALT7_ARM_TRACE_CTL = 7,
+} IMX_IOMUXC_CSI0_MCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DATA_EN_ALT0_IPU1_CSI0_DATA_EN = 0,
+  IMX_IOMUXC_CSI0_DATA_EN_ALT1_EIM_DATA00 = 1,
+  IMX_IOMUXC_CSI0_DATA_EN_ALT5_GPIO5_IO20 = 5,
+  IMX_IOMUXC_CSI0_DATA_EN_ALT7_ARM_TRACE_CLK = 7,
+} IMX_IOMUXC_CSI0_DATA_EN_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_VSYNC_ALT0_IPU1_CSI0_VSYNC = 0,
+  IMX_IOMUXC_CSI0_VSYNC_ALT1_EIM_DATA01 = 1,
+  IMX_IOMUXC_CSI0_VSYNC_ALT5_GPIO5_IO21 = 5,
+  IMX_IOMUXC_CSI0_VSYNC_ALT7_ARM_TRACE00 = 7,
+} IMX_IOMUXC_CSI0_VSYNC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT4_ALT0_IPU1_CSI0_DATA04 = 0,
+  IMX_IOMUXC_CSI0_DAT4_ALT1_EIM_DATA02 = 1,
+  IMX_IOMUXC_CSI0_DAT4_ALT2_ECSPI1_SCLK = 2,
+  IMX_IOMUXC_CSI0_DAT4_ALT3_KEY_COL5 = 3,
+  IMX_IOMUXC_CSI0_DAT4_ALT4_AUD3_TXC = 4,
+  IMX_IOMUXC_CSI0_DAT4_ALT5_GPIO5_IO22 = 5,
+  IMX_IOMUXC_CSI0_DAT4_ALT7_ARM_TRACE01 = 7,
+} IMX_IOMUXC_CSI0_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT5_ALT0_IPU1_CSI0_DATA05 = 0,
+  IMX_IOMUXC_CSI0_DAT5_ALT1_EIM_DATA03 = 1,
+  IMX_IOMUXC_CSI0_DAT5_ALT2_ECSPI1_MOSI = 2,
+  IMX_IOMUXC_CSI0_DAT5_ALT3_KEY_ROW5 = 3,
+  IMX_IOMUXC_CSI0_DAT5_ALT4_AUD3_TXD = 4,
+  IMX_IOMUXC_CSI0_DAT5_ALT5_GPIO5_IO23 = 5,
+  IMX_IOMUXC_CSI0_DAT5_ALT7_ARM_TRACE02 = 7,
+} IMX_IOMUXC_CSI0_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT6_ALT0_IPU1_CSI0_DATA06 = 0,
+  IMX_IOMUXC_CSI0_DAT6_ALT1_EIM_DATA04 = 1,
+  IMX_IOMUXC_CSI0_DAT6_ALT2_ECSPI1_MISO = 2,
+  IMX_IOMUXC_CSI0_DAT6_ALT3_KEY_COL6 = 3,
+  IMX_IOMUXC_CSI0_DAT6_ALT4_AUD3_TXFS = 4,
+  IMX_IOMUXC_CSI0_DAT6_ALT5_GPIO5_IO24 = 5,
+  IMX_IOMUXC_CSI0_DAT6_ALT7_ARM_TRACE03 = 7,
+} IMX_IOMUXC_CSI0_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT7_ALT0_IPU1_CSI0_DATA07 = 0,
+  IMX_IOMUXC_CSI0_DAT7_ALT1_EIM_DATA05 = 1,
+  IMX_IOMUXC_CSI0_DAT7_ALT2_ECSPI1_SS0 = 2,
+  IMX_IOMUXC_CSI0_DAT7_ALT3_KEY_ROW6 = 3,
+  IMX_IOMUXC_CSI0_DAT7_ALT4_AUD3_RXD = 4,
+  IMX_IOMUXC_CSI0_DAT7_ALT5_GPIO5_IO25 = 5,
+  IMX_IOMUXC_CSI0_DAT7_ALT7_ARM_TRACE04 = 7,
+} IMX_IOMUXC_CSI0_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT8_ALT0_IPU1_CSI0_DATA08 = 0,
+  IMX_IOMUXC_CSI0_DAT8_ALT1_EIM_DATA06 = 1,
+  IMX_IOMUXC_CSI0_DAT8_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_CSI0_DAT8_ALT3_KEY_COL7 = 3,
+  IMX_IOMUXC_CSI0_DAT8_ALT4_I2C1_SDA = 4,
+  IMX_IOMUXC_CSI0_DAT8_ALT5_GPIO5_IO26 = 5,
+  IMX_IOMUXC_CSI0_DAT8_ALT7_ARM_TRACE05 = 7,
+} IMX_IOMUXC_CSI0_DAT8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT9_ALT0_IPU1_CSI0_DATA09 = 0,
+  IMX_IOMUXC_CSI0_DAT9_ALT1_EIM_DATA07 = 1,
+  IMX_IOMUXC_CSI0_DAT9_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_CSI0_DAT9_ALT3_KEY_ROW7 = 3,
+  IMX_IOMUXC_CSI0_DAT9_ALT4_I2C1_SCL = 4,
+  IMX_IOMUXC_CSI0_DAT9_ALT5_GPIO5_IO27 = 5,
+  IMX_IOMUXC_CSI0_DAT9_ALT7_ARM_TRACE06 = 7,
+} IMX_IOMUXC_CSI0_DAT9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT10_ALT0_IPU1_CSI0_DATA10 = 0,
+  IMX_IOMUXC_CSI0_DAT10_ALT1_AUD3_RXC = 1,
+  IMX_IOMUXC_CSI0_DAT10_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_CSI0_DAT10_ALT3_UART1_TX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT10_ALT5_GPIO5_IO28 = 5,
+  IMX_IOMUXC_CSI0_DAT10_ALT7_ARM_TRACE07 = 7,
+} IMX_IOMUXC_CSI0_DAT10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT11_ALT0_IPU1_CSI0_DATA11 = 0,
+  IMX_IOMUXC_CSI0_DAT11_ALT1_AUD3_RXFS = 1,
+  IMX_IOMUXC_CSI0_DAT11_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_CSI0_DAT11_ALT3_UART1_RX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT11_ALT5_GPIO5_IO29 = 5,
+  IMX_IOMUXC_CSI0_DAT11_ALT7_ARM_TRACE08 = 7,
+} IMX_IOMUXC_CSI0_DAT11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT12_ALT0_IPU1_CSI0_DATA12 = 0,
+  IMX_IOMUXC_CSI0_DAT12_ALT1_EIM_DATA08 = 1,
+  IMX_IOMUXC_CSI0_DAT12_ALT3_UART4_TX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT12_ALT5_GPIO5_IO30 = 5,
+  IMX_IOMUXC_CSI0_DAT12_ALT7_ARM_TRACE09 = 7,
+} IMX_IOMUXC_CSI0_DAT12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT13_ALT0_IPU1_CSI0_DATA13 = 0,
+  IMX_IOMUXC_CSI0_DAT13_ALT1_EIM_DATA09 = 1,
+  IMX_IOMUXC_CSI0_DAT13_ALT3_UART4_RX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT13_ALT5_GPIO5_IO31 = 5,
+  IMX_IOMUXC_CSI0_DAT13_ALT7_ARM_TRACE10 = 7,
+} IMX_IOMUXC_CSI0_DAT13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT14_ALT0_IPU1_CSI0_DATA14 = 0,
+  IMX_IOMUXC_CSI0_DAT14_ALT1_EIM_DATA10 = 1,
+  IMX_IOMUXC_CSI0_DAT14_ALT3_UART5_TX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT14_ALT5_GPIO6_IO00 = 5,
+  IMX_IOMUXC_CSI0_DAT14_ALT7_ARM_TRACE11 = 7,
+} IMX_IOMUXC_CSI0_DAT14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT15_ALT0_IPU1_CSI0_DATA15 = 0,
+  IMX_IOMUXC_CSI0_DAT15_ALT1_EIM_DATA11 = 1,
+  IMX_IOMUXC_CSI0_DAT15_ALT3_UART5_RX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT15_ALT5_GPIO6_IO01 = 5,
+  IMX_IOMUXC_CSI0_DAT15_ALT7_ARM_TRACE12 = 7,
+} IMX_IOMUXC_CSI0_DAT15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT16_ALT0_IPU1_CSI0_DATA16 = 0,
+  IMX_IOMUXC_CSI0_DAT16_ALT1_EIM_DATA12 = 1,
+  IMX_IOMUXC_CSI0_DAT16_ALT3_UART4_RTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT16_ALT5_GPIO6_IO02 = 5,
+  IMX_IOMUXC_CSI0_DAT16_ALT7_ARM_TRACE13 = 7,
+} IMX_IOMUXC_CSI0_DAT16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT17_ALT0_IPU1_CSI0_DATA17 = 0,
+  IMX_IOMUXC_CSI0_DAT17_ALT1_EIM_DATA13 = 1,
+  IMX_IOMUXC_CSI0_DAT17_ALT3_UART4_CTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT17_ALT5_GPIO6_IO03 = 5,
+  IMX_IOMUXC_CSI0_DAT17_ALT7_ARM_TRACE14 = 7,
+} IMX_IOMUXC_CSI0_DAT17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT18_ALT0_IPU1_CSI0_DATA18 = 0,
+  IMX_IOMUXC_CSI0_DAT18_ALT1_EIM_DATA14 = 1,
+  IMX_IOMUXC_CSI0_DAT18_ALT3_UART5_RTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT18_ALT5_GPIO6_IO04 = 5,
+  IMX_IOMUXC_CSI0_DAT18_ALT7_ARM_TRACE15 = 7,
+} IMX_IOMUXC_CSI0_DAT18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT19_ALT0_IPU1_CSI0_DATA19 = 0,
+  IMX_IOMUXC_CSI0_DAT19_ALT1_EIM_DATA15 = 1,
+  IMX_IOMUXC_CSI0_DAT19_ALT3_UART5_CTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT19_ALT5_GPIO6_IO05 = 5,
+} IMX_IOMUXC_CSI0_DAT19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A23_ALT0_EIM_ADDR23 = 0,
+  IMX_IOMUXC_EIM_A23_ALT1_IPU1_DISP1_DATA18 = 1,
+  IMX_IOMUXC_EIM_A23_ALT2_IPU2_CSI1_DATA18 = 2,
+  IMX_IOMUXC_EIM_A23_ALT3_IPU2_SISG3 = 3,
+  IMX_IOMUXC_EIM_A23_ALT4_IPU1_SISG3 = 4,
+  IMX_IOMUXC_EIM_A23_ALT5_GPIO6_IO06 = 5,
+  IMX_IOMUXC_EIM_A23_ALT7_SRC_BOOT_CFG23 = 7,
+} IMX_IOMUXC_EIM_A23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CLE_ALT0_NAND_CLE = 0,
+  IMX_IOMUXC_NANDF_CLE_ALT1_IPU2_SISG4 = 1,
+  IMX_IOMUXC_NANDF_CLE_ALT5_GPIO6_IO07 = 5,
+} IMX_IOMUXC_NANDF_CLE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_ALE_ALT0_NAND_ALE = 0,
+  IMX_IOMUXC_NANDF_ALE_ALT1_SD4_RESET = 1,
+  IMX_IOMUXC_NANDF_ALE_ALT5_GPIO6_IO08 = 5,
+} IMX_IOMUXC_NANDF_ALE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_WP_B_ALT0_NAND_WP_B = 0,
+  IMX_IOMUXC_NANDF_WP_B_ALT1_IPU2_SISG5 = 1,
+  IMX_IOMUXC_NANDF_WP_B_ALT5_GPIO6_IO09 = 5,
+} IMX_IOMUXC_NANDF_WP_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_RB0_ALT0_NAND_READY_B = 0,
+  IMX_IOMUXC_NANDF_RB0_ALT1_IPU2_DI0_PIN01 = 1,
+  IMX_IOMUXC_NANDF_RB0_ALT5_GPIO6_IO10 = 5,
+} IMX_IOMUXC_NANDF_RB0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS0_ALT0_NAND_CE0_B = 0,
+  IMX_IOMUXC_NANDF_CS0_ALT5_GPIO6_IO11 = 5,
+} IMX_IOMUXC_NANDF_CS0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS1_ALT0_NAND_CE1_B = 0,
+  IMX_IOMUXC_NANDF_CS1_ALT1_SD4_VSELECT = 1,
+  IMX_IOMUXC_NANDF_CS1_ALT2_SD3_VSELECT = 2,
+  IMX_IOMUXC_NANDF_CS1_ALT5_GPIO6_IO14 = 5,
+} IMX_IOMUXC_NANDF_CS1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS2_ALT0_NAND_CE2_B = 0,
+  IMX_IOMUXC_NANDF_CS2_ALT1_IPU1_SISG0 = 1,
+  IMX_IOMUXC_NANDF_CS2_ALT2_ESAI_TX0 = 2,
+  IMX_IOMUXC_NANDF_CS2_ALT3_EIM_CRE = 3,
+  IMX_IOMUXC_NANDF_CS2_ALT4_CCM_CLKO2 = 4,
+  IMX_IOMUXC_NANDF_CS2_ALT5_GPIO6_IO15 = 5,
+  IMX_IOMUXC_NANDF_CS2_ALT6_IPU2_SISG0 = 6,
+} IMX_IOMUXC_NANDF_CS2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS3_ALT0_NAND_CE3_B = 0,
+  IMX_IOMUXC_NANDF_CS3_ALT1_IPU1_SISG1 = 1,
+  IMX_IOMUXC_NANDF_CS3_ALT2_ESAI_TX1 = 2,
+  IMX_IOMUXC_NANDF_CS3_ALT3_EIM_ADDR26 = 3,
+  IMX_IOMUXC_NANDF_CS3_ALT5_GPIO6_IO16 = 5,
+  IMX_IOMUXC_NANDF_CS3_ALT6_IPU2_SISG1 = 6,
+} IMX_IOMUXC_NANDF_CS3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT7_ALT0_SD3_DATA7 = 0,
+  IMX_IOMUXC_SD3_DAT7_ALT1_UART1_TX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT7_ALT5_GPIO6_IO17 = 5,
+} IMX_IOMUXC_SD3_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT6_ALT0_SD3_DATA6 = 0,
+  IMX_IOMUXC_SD3_DAT6_ALT1_UART1_RX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT6_ALT5_GPIO6_IO18 = 5,
+} IMX_IOMUXC_SD3_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TXC_ALT0_USB_H2_DATA = 0,
+  IMX_IOMUXC_RGMII_TXC_ALT1_RGMII_TXC = 1,
+  IMX_IOMUXC_RGMII_TXC_ALT2_SPDIF_EXT_CLK = 2,
+  IMX_IOMUXC_RGMII_TXC_ALT5_GPIO6_IO19 = 5,
+  IMX_IOMUXC_RGMII_TXC_ALT7_XTALOSC_REF_CLK_24M = 7,
+} IMX_IOMUXC_RGMII_TXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD0_ALT0_HSI_TX_READY = 0,
+  IMX_IOMUXC_RGMII_TD0_ALT1_RGMII_TD0 = 1,
+  IMX_IOMUXC_RGMII_TD0_ALT5_GPIO6_IO20 = 5,
+} IMX_IOMUXC_RGMII_TD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD1_ALT0_HSI_RX_FLAG = 0,
+  IMX_IOMUXC_RGMII_TD1_ALT1_RGMII_TD1 = 1,
+  IMX_IOMUXC_RGMII_TD1_ALT5_GPIO6_IO21 = 5,
+} IMX_IOMUXC_RGMII_TD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD2_ALT0_HSI_RX_DATA = 0,
+  IMX_IOMUXC_RGMII_TD2_ALT1_RGMII_TD2 = 1,
+  IMX_IOMUXC_RGMII_TD2_ALT5_GPIO6_IO22 = 5,
+} IMX_IOMUXC_RGMII_TD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD3_ALT0_HSI_RX_WAKE = 0,
+  IMX_IOMUXC_RGMII_TD3_ALT1_RGMII_TD3 = 1,
+  IMX_IOMUXC_RGMII_TD3_ALT5_GPIO6_IO23 = 5,
+} IMX_IOMUXC_RGMII_TD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RX_CTL_ALT0_USB_H3_DATA = 0,
+  IMX_IOMUXC_RGMII_RX_CTL_ALT1_RGMII_RX_CTL = 1,
+  IMX_IOMUXC_RGMII_RX_CTL_ALT5_GPIO6_IO24 = 5,
+} IMX_IOMUXC_RGMII_RX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD0_ALT0_HSI_RX_READY = 0,
+  IMX_IOMUXC_RGMII_RD0_ALT1_RGMII_RD0 = 1,
+  IMX_IOMUXC_RGMII_RD0_ALT5_GPIO6_IO25 = 5,
+} IMX_IOMUXC_RGMII_RD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TX_CTL_ALT0_USB_H2_STROBE = 0,
+  IMX_IOMUXC_RGMII_TX_CTL_ALT1_RGMII_TX_CTL = 1,
+  IMX_IOMUXC_RGMII_TX_CTL_ALT5_GPIO6_IO26 = 5,
+  IMX_IOMUXC_RGMII_TX_CTL_ALT7_ENET_REF_CLK = 7,
+} IMX_IOMUXC_RGMII_TX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD1_ALT0_HSI_TX_FLAG = 0,
+  IMX_IOMUXC_RGMII_RD1_ALT1_RGMII_RD1 = 1,
+  IMX_IOMUXC_RGMII_RD1_ALT5_GPIO6_IO27 = 5,
+} IMX_IOMUXC_RGMII_RD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD2_ALT0_HSI_TX_DATA = 0,
+  IMX_IOMUXC_RGMII_RD2_ALT1_RGMII_RD2 = 1,
+  IMX_IOMUXC_RGMII_RD2_ALT5_GPIO6_IO28 = 5,
+} IMX_IOMUXC_RGMII_RD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD3_ALT0_HSI_TX_WAKE = 0,
+  IMX_IOMUXC_RGMII_RD3_ALT1_RGMII_RD3 = 1,
+  IMX_IOMUXC_RGMII_RD3_ALT5_GPIO6_IO29 = 5,
+} IMX_IOMUXC_RGMII_RD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RXC_ALT0_USB_H3_STROBE = 0,
+  IMX_IOMUXC_RGMII_RXC_ALT1_RGMII_RXC = 1,
+  IMX_IOMUXC_RGMII_RXC_ALT5_GPIO6_IO30 = 5,
+} IMX_IOMUXC_RGMII_RXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_BCLK_ALT0_EIM_BCLK = 0,
+  IMX_IOMUXC_EIM_BCLK_ALT1_IPU1_DI1_PIN16 = 1,
+  IMX_IOMUXC_EIM_BCLK_ALT5_GPIO6_IO31 = 5,
+} IMX_IOMUXC_EIM_BCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT5_ALT0_SD3_DATA5 = 0,
+  IMX_IOMUXC_SD3_DAT5_ALT1_UART2_TX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT5_ALT5_GPIO7_IO00 = 5,
+} IMX_IOMUXC_SD3_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT4_ALT0_SD3_DATA4 = 0,
+  IMX_IOMUXC_SD3_DAT4_ALT1_UART2_RX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT4_ALT5_GPIO7_IO01 = 5,
+} IMX_IOMUXC_SD3_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_CMD_ALT0_SD3_CMD = 0,
+  IMX_IOMUXC_SD3_CMD_ALT1_UART2_CTS_B = 1,
+  IMX_IOMUXC_SD3_CMD_ALT2_FLEXCAN1_TX = 2,
+  IMX_IOMUXC_SD3_CMD_ALT5_GPIO7_IO02 = 5,
+} IMX_IOMUXC_SD3_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_CLK_ALT0_SD3_CLK = 0,
+  IMX_IOMUXC_SD3_CLK_ALT1_UART2_RTS_B = 1,
+  IMX_IOMUXC_SD3_CLK_ALT2_FLEXCAN1_RX = 2,
+  IMX_IOMUXC_SD3_CLK_ALT5_GPIO7_IO03 = 5,
+} IMX_IOMUXC_SD3_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT0_ALT0_SD3_DATA0 = 0,
+  IMX_IOMUXC_SD3_DAT0_ALT1_UART1_CTS_B = 1,
+  IMX_IOMUXC_SD3_DAT0_ALT2_FLEXCAN2_TX = 2,
+  IMX_IOMUXC_SD3_DAT0_ALT5_GPIO7_IO04 = 5,
+} IMX_IOMUXC_SD3_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT1_ALT0_SD3_DATA1 = 0,
+  IMX_IOMUXC_SD3_DAT1_ALT1_UART1_RTS_B = 1,
+  IMX_IOMUXC_SD3_DAT1_ALT2_FLEXCAN2_RX = 2,
+  IMX_IOMUXC_SD3_DAT1_ALT5_GPIO7_IO05 = 5,
+} IMX_IOMUXC_SD3_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT2_ALT0_SD3_DATA2 = 0,
+  IMX_IOMUXC_SD3_DAT2_ALT5_GPIO7_IO06 = 5,
+} IMX_IOMUXC_SD3_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT3_ALT0_SD3_DATA3 = 0,
+  IMX_IOMUXC_SD3_DAT3_ALT1_UART3_CTS_B = 1,
+  IMX_IOMUXC_SD3_DAT3_ALT5_GPIO7_IO07 = 5,
+} IMX_IOMUXC_SD3_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_RST_ALT0_SD3_RESET = 0,
+  IMX_IOMUXC_SD3_RST_ALT1_UART3_RTS_B = 1,
+  IMX_IOMUXC_SD3_RST_ALT5_GPIO7_IO08 = 5,
+} IMX_IOMUXC_SD3_RST_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_CMD_ALT0_SD4_CMD = 0,
+  IMX_IOMUXC_SD4_CMD_ALT1_NAND_RE_B = 1,
+  IMX_IOMUXC_SD4_CMD_ALT2_UART3_TX_DATA = 2,
+  IMX_IOMUXC_SD4_CMD_ALT5_GPIO7_IO09 = 5,
+} IMX_IOMUXC_SD4_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_CLK_ALT0_SD4_CLK = 0,
+  IMX_IOMUXC_SD4_CLK_ALT1_NAND_WE_B = 1,
+  IMX_IOMUXC_SD4_CLK_ALT2_UART3_RX_DATA = 2,
+  IMX_IOMUXC_SD4_CLK_ALT5_GPIO7_IO10 = 5,
+} IMX_IOMUXC_SD4_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_16_ALT0_ESAI_TX3_RX2 = 0,
+  IMX_IOMUXC_GPIO_16_ALT1_ENET_1588_EVENT2_IN = 1,
+  IMX_IOMUXC_GPIO_16_ALT2_ENET_REF_CLK = 2,
+  IMX_IOMUXC_GPIO_16_ALT3_SD1_LCTL = 3,
+  IMX_IOMUXC_GPIO_16_ALT4_SPDIF_IN = 4,
+  IMX_IOMUXC_GPIO_16_ALT5_GPIO7_IO11 = 5,
+  IMX_IOMUXC_GPIO_16_ALT6_I2C3_SDA = 6,
+  IMX_IOMUXC_GPIO_16_ALT7_JTAG_DE_B = 7,
+} IMX_IOMUXC_GPIO_16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_17_ALT0_ESAI_TX0 = 0,
+  IMX_IOMUXC_GPIO_17_ALT1_ENET_1588_EVENT3_IN = 1,
+  IMX_IOMUXC_GPIO_17_ALT2_CCM_PMIC_READY = 2,
+  IMX_IOMUXC_GPIO_17_ALT3_SDMA_EXT_EVENT0 = 3,
+  IMX_IOMUXC_GPIO_17_ALT4_SPDIF_OUT = 4,
+  IMX_IOMUXC_GPIO_17_ALT5_GPIO7_IO12 = 5,
+} IMX_IOMUXC_GPIO_17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_18_ALT0_ESAI_TX1 = 0,
+  IMX_IOMUXC_GPIO_18_ALT1_ENET_RX_CLK = 1,
+  IMX_IOMUXC_GPIO_18_ALT2_SD3_VSELECT = 2,
+  IMX_IOMUXC_GPIO_18_ALT3_SDMA_EXT_EVENT1 = 3,
+  IMX_IOMUXC_GPIO_18_ALT4_ASRC_EXT_CLK = 4,
+  IMX_IOMUXC_GPIO_18_ALT5_GPIO7_IO13 = 5,
+  IMX_IOMUXC_GPIO_18_ALT6_SNVS_VIO_5_CTL = 6,
+} IMX_IOMUXC_GPIO_18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ECSPI1_MISO_EIM_DATA17_ALT1 = 0,
+  IMX_IOMUXC_ECSPI1_MISO_DISP0_DATA22_ALT2 = 1,
+  IMX_IOMUXC_ECSPI1_MISO_KEY_COL1_ALT0 = 2,
+  IMX_IOMUXC_ECSPI1_MISO_CSI0_DATA06_ALT2 = 3,
+} IMX_IOMUXC_ECSPI1_MISO_SELECT_INPUT;
+
+typedef enum {
+  IMX_IOMUXC_ECSPI2_MISO_EIM_OE_B_ALT2 = 0,
+  IMX_IOMUXC_ECSPI2_MISO_DISP0_DATA17_ALT2 = 1,
+  IMX_IOMUXC_ECSPI2_MISO_CSI0_DATA10_ALT2 = 2,
+} IMX_IOMUXC_ECSPI2_MISO_SELECT_INPUT;
+
+#endif // _IMX6_IOMUX_DQP_H_
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h
new file mode 100644
index 000000000000..99ee9ccf3558
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h
@@ -0,0 +1,1875 @@
+/** @file
+*
+*  Header defining iMX6 Solo and Dual Lite Muxing definitions
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+#ifndef _IMX6_IOMUX_SDL_H_
+#define _IMX6_IOMUX_SDL_H_
+
+// SELECT INPUT defines
+#define EIM_DATA21_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D21 for I2C1_SCL
+#define CSI0_DAT9_ALT4 0x1 // Selecting ALT4 mode of pad CSI0_DAT9 for I2C1_SCL
+
+#define EIM_DATA28_ALT1 0x0 // Selecting ALT1 mode of pad EIM_D28 for I2C1_SDA
+#define CSI0_DAT8_ALT4 0x1 // Selecting ALT4 mode of pad CSI0_DAT8 for I2C1_SDA
+
+#define EIM_EB2_B_ALT6 0x0 // Selecting ALT6 mode of pad EIM_EB2 for I2C2_SCL
+#define KEY_COL3_ALT4 0x1 // Selecting ALT4 mode of pad KEY_COL3 for I2C2_SCL
+
+#define EIM_DATA16_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D16 for I2C2_SDA
+#define KEY_ROW3_ALT4 0x1 // Selecting ALT4 mode of pad KEY_ROW3 for I2C2_SDA
+
+#define EIM_DATA17_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D17 for I2C3_SCL
+#define GPIO03_ALT2 0x1 // Selecting ALT2 mode of pad GPIO_3 for I2C3_SCL
+#define GPIO05_ALT6 0x2 // Selecting ALT6 mode of pad GPIO_5 for I2C3_SCL
+
+#define EIM_DATA18_ALT6 0x0 // Selecting ALT6 mode of pad EIM_D18 for I2C3_SDA
+#define GPIO06_ALT2 0x1 // Selecting ALT2 mode of pad GPIO_6 for I2C3_SDA
+#define GPIO16_ALT6 0x2 // Selecting ALT6 mode of pad GPIO_16 for I2C3_SDA
+
+#define ENET_TX_EN_ALT9  0x0 // Selecting ALT9 mode of pad ENET_TX_EN for I2C4_SCL
+#define GPIO07_ALT8      0x1 // Selecting ALT8 mode of pad GPIO_7 for I2C4_SCL
+#define NAND_WP_B_ALT9   0x2 // Selecting ALT9 mode of pad NANDF_WP_B for I2C4_SCL
+
+#define ENET_TX_DATA1_ALT9  0x0 // Selecting ALT9 mode of pad ENET_TXD1 for I2C4_SDA
+#define GPIO08_ALT8         0x1 // Selecting ALT9 mode of pad GPIO_8 for I2C4_SDA
+#define NAND_CS3_B_ALT9     0x2 // Selecting ALT9 mode of pad NANDF_CS3 for I2C4_SDA
+
+#define DISP0_DATA19_ALT3 0
+#define KEY_ROW1_ALT2 1
+
+#define DISP0_DATA17_ALT3 0
+#define KEY_ROW0_ALT2 1
+
+#define DISP0_DATA16_ALT3 0
+#define KEY_COL0_ALT2 1
+
+#define DISP0_DATA18_ALT3 0
+#define KEY_COL1_ALT2 1
+
+#define EIM_DATA21_ALT4 0
+#define KEY_COL4_ALT2 1
+
+#define EIM_DATA30_ALT6 0
+#define GPIO03_ALT6 1
+
+#define RGMII_TX_CTL_ALT7 0
+#define GPIO16_ALT2 1
+
+#define CSI0_DATA10_ALT3 0 // Selecting ALT3 mode of pad CSI0_DAT10 for UART1_TX_DATA.
+#define CSI0_DATA11_ALT3 1 // Selecting ALT3 mode of pad CSI0_DAT11 for UART1_RX_DATA.
+#define SD3_DATA7_ALT1 2 // Selecting ALT1 mode of pad SD3_DAT7 for UART1_TX_DATA.
+#define SD3_DATA6_ALT1 3 // Selecting ALT1 mode of pad SD3_DAT6 for UART1_RX_DATA.
+
+#define EIM_DATA26_ALT4 0 // Selecting ALT4 mode of pad EIM_D26 for UART2_TX_DATA.
+#define EIM_DATA27_ALT4 1 // Selecting ALT4 mode of pad EIM_D27 for UART2_RX_DATA.
+#define GPIO07_ALT4 2 // Selecting ALT4 mode of pad GPIO_7 for UART2_TX_DATA.
+#define GPIO08_ALT4 3 // Selecting ALT4 mode of pad GPIO_8 for UART2_RX_DATA.
+#define SD3_DATA5_ALT1 4 // Selecting ALT1 mode of pad SD3_DAT5 for UART2_TX_DATA.
+#define SD3_DATA4_ALT1 5 // Selecting ALT1 mode of pad SD3_DAT4 for UART2_RX_DATA.
+#define SD4_DATA4_ALT2 6 // Selecting ALT2 mode of pad SD4_DAT4 for UART2_RX_DATA.
+#define SD4_DATA7_ALT2 7 // Selecting ALT2 mode of pad SD4_DAT7 for UART2_TX_DATA.
+
+#define EIM_DATA24_ALT2 0 // Selecting ALT2 mode of pad EIM_D24 for UART3_TX_DATA.
+#define EIM_DATA25_ALT2 1 // Selecting ALT2 mode of pad EIM_D25 for UART3_RX_DATA.
+#define SD4_CMD_ALT2 2 // Selecting ALT2 mode of pad SD4_CMD for UART3_TX_DATA.
+#define SD4_CLK_ALT2 3 // Selecting ALT2 mode of pad SD4_CLK for UART3_RX_DATA.
+
+typedef enum {
+  IMX_PAD_GPIO_0 = _IMX_PAD (0x5DC, 0x20C), // CCM_CLKO1
+  IMX_PAD_GPIO_1 = _IMX_PAD (0x5E0, 0x210), // ESAI_RX_CLK
+  IMX_PAD_GPIO_2 = _IMX_PAD (0x5F4, 0x224), // ESAI_TX_FS
+  IMX_PAD_GPIO_3 = _IMX_PAD (0x5F8, 0x228), // ESAI_RX_HF_CLK
+  IMX_PAD_GPIO_4 = _IMX_PAD (0x5FC, 0x22C), // ESAI_TX_HF_CLK
+  IMX_PAD_GPIO_5 = _IMX_PAD (0x600, 0x230), // ESAI_TX2_RX3
+  IMX_PAD_GPIO_6 = _IMX_PAD (0x604, 0x234), // ESAI_TX_CLK
+  IMX_PAD_GPIO_7 = _IMX_PAD (0x608, 0x238), // ESAI_TX4_RX1
+  IMX_PAD_GPIO_8 = _IMX_PAD (0x60C, 0x23C), // ESAI_TX5_RX0
+  IMX_PAD_GPIO_9 = _IMX_PAD (0x610, 0x240), // ESAI_RX_FS
+  IMX_PAD_SD2_CLK = _IMX_PAD (0x6DC, 0x2F4), // SD2_CLK
+  IMX_PAD_SD2_CMD = _IMX_PAD (0x6E0, 0x2F8), // SD2_CMD
+  IMX_PAD_SD2_DAT3 = _IMX_PAD (0x6F0, 0x308), // SD2_DATA3
+  IMX_PAD_SD2_DAT2 = _IMX_PAD (0x6EC, 0x304), // SD2_DATA2
+  IMX_PAD_SD2_DAT1 = _IMX_PAD (0x6E8, 0x300), // SD2_DATA1
+  IMX_PAD_SD2_DAT0 = _IMX_PAD (0x6E4, 0x2FC), // SD2_DATA0
+  IMX_PAD_SD1_DAT0 = _IMX_PAD (0x6CC, 0x2E4), // SD1_DATA0
+  IMX_PAD_SD1_DAT1 = _IMX_PAD (0x6D0, 0x2E8), // SD1_DATA1
+  IMX_PAD_SD1_CMD = _IMX_PAD (0x6C8, 0x2E0), // SD1_CMD
+  IMX_PAD_SD1_DAT2 = _IMX_PAD (0x6D4, 0x2EC), // SD1_DATA2
+  IMX_PAD_SD1_CLK = _IMX_PAD (0x6C4, 0x2DC), // SD1_CLK
+  IMX_PAD_SD1_DAT3 = _IMX_PAD (0x6D8, 0x2F0), // SD1_DATA3
+  IMX_PAD_ENET_MDIO = _IMX_PAD (0x5BC, 0x1EC), // ENET_MDIO
+  IMX_PAD_ENET_REF_CLK = _IMX_PAD (0x5C0, 0x1F0), // ENET_TX_CLK
+  IMX_PAD_ENET_RX_ER = _IMX_PAD (0x5C4, 0x1F4), // USB_OTG_ID
+  IMX_PAD_ENET_CRS_DV = _IMX_PAD (0x5B4, 0x1E4), // ENET_RX_EN
+  IMX_PAD_ENET_RXD1 = _IMX_PAD (0x5CC, 0x1FC), // MLB_SIG
+  IMX_PAD_ENET_RXD0 = _IMX_PAD (0x5C8, 0x1F8), // ENET_RX_DATA0
+  IMX_PAD_ENET_TX_EN = _IMX_PAD (0x5D0, 0x200), // ENET_TX_EN
+  IMX_PAD_ENET_TXD1 = _IMX_PAD (0x5D8, 0x208), // MLB_CLK
+  IMX_PAD_ENET_TXD0 = _IMX_PAD (0x5D4, 0x204), // ENET_TX_DATA0
+  IMX_PAD_ENET_MDC = _IMX_PAD (0x5B8, 0x1E8), // MLB_DATA
+  IMX_PAD_NANDF_D0 = _IMX_PAD (0x66C, 0x284), // NAND_DATA00
+  IMX_PAD_NANDF_D1 = _IMX_PAD (0x670, 0x288), // NAND_DATA01
+  IMX_PAD_NANDF_D2 = _IMX_PAD (0x674, 0x28C), // NAND_DATA02
+  IMX_PAD_NANDF_D3 = _IMX_PAD (0x678, 0x290), // NAND_DATA03
+  IMX_PAD_NANDF_D4 = _IMX_PAD (0x67C, 0x294), // NAND_DATA04
+  IMX_PAD_NANDF_D5 = _IMX_PAD (0x680, 0x298), // NAND_DATA05
+  IMX_PAD_NANDF_D6 = _IMX_PAD (0x684, 0x29C), // NAND_DATA06
+  IMX_PAD_NANDF_D7 = _IMX_PAD (0x688, 0x2A0), // NAND_DATA07
+  IMX_PAD_SD4_DAT0 = _IMX_PAD (0x728, 0x340), // SD4_DATA0
+  IMX_PAD_SD4_DAT1 = _IMX_PAD (0x72C, 0x344), // SD4_DATA1
+  IMX_PAD_SD4_DAT2 = _IMX_PAD (0x730, 0x348), // SD4_DATA2
+  IMX_PAD_SD4_DAT3 = _IMX_PAD (0x734, 0x34C), // SD4_DATA3
+  IMX_PAD_SD4_DAT4 = _IMX_PAD (0x738, 0x350), // SD4_DATA4
+  IMX_PAD_SD4_DAT5 = _IMX_PAD (0x73C, 0x354), // SD4_DATA5
+  IMX_PAD_SD4_DAT6 = _IMX_PAD (0x740, 0x358), // SD4_DATA6
+  IMX_PAD_SD4_DAT7 = _IMX_PAD (0x744, 0x35C), // SD4_DATA7
+  IMX_PAD_EIM_A22 = _IMX_PAD (0x4F8, 0x128), // EIM_ADDR22
+  IMX_PAD_EIM_A21 = _IMX_PAD (0x4F4, 0x124), // EIM_ADDR21
+  IMX_PAD_EIM_A20 = _IMX_PAD (0x4F0, 0x120), // EIM_ADDR20
+  IMX_PAD_EIM_A19 = _IMX_PAD (0x4EC, 0x11C), // EIM_ADDR19
+  IMX_PAD_EIM_A18 = _IMX_PAD (0x4E8, 0x118), // EIM_ADDR18
+  IMX_PAD_EIM_A17 = _IMX_PAD (0x4E4, 0x114), // EIM_ADDR17
+  IMX_PAD_EIM_A16 = _IMX_PAD (0x4E0, 0x110), // EIM_ADDR16
+  IMX_PAD_EIM_CS0 = _IMX_PAD (0x50C, 0x13C), // EIM_CS0_B
+  IMX_PAD_EIM_CS1 = _IMX_PAD (0x510, 0x140), // EIM_CS1_B
+  IMX_PAD_EIM_OE = _IMX_PAD (0x5A8, 0x1D8), // EIM_OE_B
+  IMX_PAD_EIM_RW = _IMX_PAD (0x5AC, 0x1DC), // EIM_RW
+  IMX_PAD_EIM_LBA = _IMX_PAD (0x5A4, 0x1D4), // EIM_LBA_B
+  IMX_PAD_EIM_EB0 = _IMX_PAD (0x594, 0x1C4), // EIM_EB0_B
+  IMX_PAD_EIM_EB1 = _IMX_PAD (0x598, 0x1C8), // EIM_EB1_B
+  IMX_PAD_EIM_EB2 = _IMX_PAD (0x59C, 0x1CC), // EIM_EB2_B
+  IMX_PAD_EIM_EB3 = _IMX_PAD (0x5A0, 0x1D0), // EIM_EB3_B
+  IMX_PAD_EIM_DA0 = _IMX_PAD (0x554, 0x184), // EIM_AD00
+  IMX_PAD_EIM_DA1 = _IMX_PAD (0x558, 0x188), // EIM_AD01
+  IMX_PAD_EIM_DA2 = _IMX_PAD (0x574, 0x1A4), // EIM_AD02
+  IMX_PAD_EIM_DA3 = _IMX_PAD (0x578, 0x1A8), // EIM_AD03
+  IMX_PAD_EIM_DA4 = _IMX_PAD (0x57C, 0x1AC), // EIM_AD04
+  IMX_PAD_EIM_DA5 = _IMX_PAD (0x580, 0x1B0), // EIM_AD05
+  IMX_PAD_EIM_DA6 = _IMX_PAD (0x584, 0x1B4), // EIM_AD06
+  IMX_PAD_EIM_DA7 = _IMX_PAD (0x588, 0x1B8), // EIM_AD07
+  IMX_PAD_EIM_DA8 = _IMX_PAD (0x58C, 0x1BC), // EIM_AD08
+  IMX_PAD_EIM_DA9 = _IMX_PAD (0x590, 0x1C0), // EIM_AD09
+  IMX_PAD_EIM_DA10 = _IMX_PAD (0x55C, 0x18C), // EIM_AD10
+  IMX_PAD_EIM_DA11 = _IMX_PAD (0x560, 0x190), // EIM_AD11
+  IMX_PAD_EIM_DA12 = _IMX_PAD (0x564, 0x194), // EIM_AD12
+  IMX_PAD_EIM_DA13 = _IMX_PAD (0x568, 0x198), // EIM_AD13
+  IMX_PAD_EIM_DA14 = _IMX_PAD (0x56C, 0x19C), // EIM_AD14
+  IMX_PAD_EIM_DA15 = _IMX_PAD (0x570, 0x1A0), // EIM_AD15
+  IMX_PAD_EIM_D16 = _IMX_PAD (0x514, 0x144), // EIM_DATA16
+  IMX_PAD_EIM_D17 = _IMX_PAD (0x518, 0x148), // EIM_DATA17
+  IMX_PAD_EIM_D18 = _IMX_PAD (0x51C, 0x14C), // EIM_DATA18
+  IMX_PAD_EIM_D19 = _IMX_PAD (0x520, 0x150), // EIM_DATA19
+  IMX_PAD_EIM_D20 = _IMX_PAD (0x524, 0x154), // EIM_DATA20
+  IMX_PAD_EIM_D21 = _IMX_PAD (0x528, 0x158), // EIM_DATA21
+  IMX_PAD_EIM_D22 = _IMX_PAD (0x52C, 0x15C), // EIM_DATA22
+  IMX_PAD_EIM_D23 = _IMX_PAD (0x530, 0x160), // EIM_DATA23
+  IMX_PAD_EIM_D24 = _IMX_PAD (0x534, 0x164), // EIM_DATA24
+  IMX_PAD_EIM_D25 = _IMX_PAD (0x538, 0x168), // EIM_DATA25
+  IMX_PAD_EIM_D26 = _IMX_PAD (0x53C, 0x16C), // EIM_DATA26
+  IMX_PAD_EIM_D27 = _IMX_PAD (0x540, 0x170), // EIM_DATA27
+  IMX_PAD_EIM_D28 = _IMX_PAD (0x544, 0x174), // EIM_DATA28
+  IMX_PAD_EIM_D29 = _IMX_PAD (0x548, 0x178), // EIM_DATA29
+  IMX_PAD_EIM_D30 = _IMX_PAD (0x54C, 0x17C), // EIM_DATA30
+  IMX_PAD_EIM_D31 = _IMX_PAD (0x550, 0x180), // EIM_DATA31
+  IMX_PAD_GPIO_19 = _IMX_PAD (0x5F0, 0x220), // KEY_COL5
+  IMX_PAD_KEY_COL0 = _IMX_PAD (0x62C, 0x244), // ECSPI1_SCLK
+  IMX_PAD_KEY_ROW0 = _IMX_PAD (0x640, 0x258), // ECSPI1_MOSI
+  IMX_PAD_KEY_COL1 = _IMX_PAD (0x630, 0x248), // ECSPI1_MISO
+  IMX_PAD_KEY_ROW1 = _IMX_PAD (0x644, 0x25C), // ECSPI1_SS0
+  IMX_PAD_KEY_COL2 = _IMX_PAD (0x634, 0x24C), // ECSPI1_SS1
+  IMX_PAD_KEY_ROW2 = _IMX_PAD (0x648, 0x260), // ECSPI1_SS2
+  IMX_PAD_KEY_COL3 = _IMX_PAD (0x638, 0x250), // ECSPI1_SS3
+  IMX_PAD_KEY_ROW3 = _IMX_PAD (0x64C, 0x264), // ASRC_EXT_CLK
+  IMX_PAD_KEY_COL4 = _IMX_PAD (0x63C, 0x254), // FLEXCAN2_TX
+  IMX_PAD_KEY_ROW4 = _IMX_PAD (0x650, 0x268), // FLEXCAN2_RX
+  IMX_PAD_DI0_DISP_CLK = _IMX_PAD (0x3B0, 0x9C), // IPU1_DI0_DISP_CLK
+  IMX_PAD_DI0_PIN15 = _IMX_PAD (0x3B4, 0xA0), // IPU1_DI0_PIN15
+  IMX_PAD_DI0_PIN2 = _IMX_PAD (0x3B8, 0xA4), // IPU1_DI0_PIN02
+  IMX_PAD_DI0_PIN3 = _IMX_PAD (0x3BC, 0xA8), // IPU1_DI0_PIN03
+  IMX_PAD_DI0_PIN4 = _IMX_PAD (0x3C0, 0xAC), // IPU1_DI0_PIN04
+  IMX_PAD_DISP0_DAT0 = _IMX_PAD (0x3C4, 0xB0), // IPU1_DISP0_DATA00
+  IMX_PAD_DISP0_DAT1 = _IMX_PAD (0x3C8, 0xB4), // IPU1_DISP0_DATA01
+  IMX_PAD_DISP0_DAT2 = _IMX_PAD (0x3F4, 0xE0), // IPU1_DISP0_DATA02
+  IMX_PAD_DISP0_DAT3 = _IMX_PAD (0x408, 0xF4), // IPU1_DISP0_DATA03
+  IMX_PAD_DISP0_DAT4 = _IMX_PAD (0x40C, 0xF8), // IPU1_DISP0_DATA04
+  IMX_PAD_DISP0_DAT5 = _IMX_PAD (0x410, 0xFC), // IPU1_DISP0_DATA05
+  IMX_PAD_DISP0_DAT6 = _IMX_PAD (0x414, 0x100), // IPU1_DISP0_DATA06
+  IMX_PAD_DISP0_DAT7 = _IMX_PAD (0x418, 0x104), // IPU1_DISP0_DATA07
+  IMX_PAD_DISP0_DAT8 = _IMX_PAD (0x41C, 0x108), // IPU1_DISP0_DATA08
+  IMX_PAD_DISP0_DAT9 = _IMX_PAD (0x420, 0x10C), // IPU1_DISP0_DATA09
+  IMX_PAD_DISP0_DAT10 = _IMX_PAD (0x3CC, 0xB8), // IPU1_DISP0_DATA10
+  IMX_PAD_EIM_WAIT = _IMX_PAD (0x5B0, 0x1E0), // EIM_WAIT_B
+  IMX_PAD_EIM_A25 = _IMX_PAD (0x504, 0x134), // EIM_ADDR25
+  IMX_PAD_EIM_A24 = _IMX_PAD (0x500, 0x130), // EIM_ADDR24
+  IMX_PAD_DISP0_DAT11 = _IMX_PAD (0x3D0, 0xBC), // IPU1_DISP0_DATA11
+  IMX_PAD_DISP0_DAT12 = _IMX_PAD (0x3D4, 0xC0), // IPU1_DISP0_DATA12
+  IMX_PAD_DISP0_DAT13 = _IMX_PAD (0x3D8, 0xC4), // IPU1_DISP0_DATA13
+  IMX_PAD_DISP0_DAT14 = _IMX_PAD (0x3DC, 0xC8), // IPU1_DISP0_DATA14
+  IMX_PAD_DISP0_DAT15 = _IMX_PAD (0x3E0, 0xCC), // IPU1_DISP0_DATA15
+  IMX_PAD_DISP0_DAT16 = _IMX_PAD (0x3E4, 0xD0), // IPU1_DISP0_DATA16
+  IMX_PAD_DISP0_DAT17 = _IMX_PAD (0x3E8, 0xD4), // IPU1_DISP0_DATA17
+  IMX_PAD_DISP0_DAT18 = _IMX_PAD (0x3EC, 0xD8), // IPU1_DISP0_DATA18
+  IMX_PAD_DISP0_DAT19 = _IMX_PAD (0x3F0, 0xDC), // IPU1_DISP0_DATA19
+  IMX_PAD_DISP0_DAT20 = _IMX_PAD (0x3F8, 0xE4), // IPU1_DISP0_DATA20
+  IMX_PAD_DISP0_DAT21 = _IMX_PAD (0x3FC, 0xE8), // IPU1_DISP0_DATA21
+  IMX_PAD_DISP0_DAT22 = _IMX_PAD (0x400, 0xEC), // IPU1_DISP0_DATA22
+  IMX_PAD_DISP0_DAT23 = _IMX_PAD (0x404, 0xF0), // IPU1_DISP0_DATA23
+  IMX_PAD_CSI0_PIXCLK = _IMX_PAD (0x3A8, 0x94), // IPU1_CSI0_PIXCLK
+  IMX_PAD_CSI0_MCLK = _IMX_PAD (0x3A4, 0x90), // IPU1_CSI0_HSYNC
+  IMX_PAD_CSI0_DATA_EN = _IMX_PAD (0x3A0, 0x8C), // IPU1_CSI0_DATA_EN
+  IMX_PAD_CSI0_VSYNC = _IMX_PAD (0x3AC, 0x98), // IPU1_CSI0_VSYNC
+  IMX_PAD_CSI0_DAT4 = _IMX_PAD (0x388, 0x74), // IPU1_CSI0_DATA04
+  IMX_PAD_CSI0_DAT5 = _IMX_PAD (0x38C, 0x78), // IPU1_CSI0_DATA05
+  IMX_PAD_CSI0_DAT6 = _IMX_PAD (0x390, 0x7C), // IPU1_CSI0_DATA06
+  IMX_PAD_CSI0_DAT7 = _IMX_PAD (0x394, 0x80), // IPU1_CSI0_DATA07
+  IMX_PAD_CSI0_DAT8 = _IMX_PAD (0x398, 0x84), // IPU1_CSI0_DATA08
+  IMX_PAD_CSI0_DAT9 = _IMX_PAD (0x39C, 0x88), // IPU1_CSI0_DATA09
+  IMX_PAD_CSI0_DAT10 = _IMX_PAD (0x360, 0x4C), // IPU1_CSI0_DATA10
+  IMX_PAD_CSI0_DAT11 = _IMX_PAD (0x364, 0x50), // IPU1_CSI0_DATA11
+  IMX_PAD_CSI0_DAT12 = _IMX_PAD (0x368, 0x54), // IPU1_CSI0_DATA12
+  IMX_PAD_CSI0_DAT13 = _IMX_PAD (0x36C, 0x58), // IPU1_CSI0_DATA13
+  IMX_PAD_CSI0_DAT14 = _IMX_PAD (0x370, 0x5C), // IPU1_CSI0_DATA14
+  IMX_PAD_CSI0_DAT15 = _IMX_PAD (0x374, 0x60), // IPU1_CSI0_DATA15
+  IMX_PAD_CSI0_DAT16 = _IMX_PAD (0x378, 0x64), // IPU1_CSI0_DATA16
+  IMX_PAD_CSI0_DAT17 = _IMX_PAD (0x37C, 0x68), // IPU1_CSI0_DATA17
+  IMX_PAD_CSI0_DAT18 = _IMX_PAD (0x380, 0x6C), // IPU1_CSI0_DATA18
+  IMX_PAD_CSI0_DAT19 = _IMX_PAD (0x384, 0x70), // IPU1_CSI0_DATA19
+  IMX_PAD_EIM_A23 = _IMX_PAD (0x4FC, 0x12C), // EIM_ADDR23
+  IMX_PAD_NANDF_CLE = _IMX_PAD (0x658, 0x270), // NAND_CLE
+  IMX_PAD_NANDF_ALE = _IMX_PAD (0x654, 0x26C), // NAND_ALE
+  IMX_PAD_NANDF_WP_B = _IMX_PAD (0x690, 0x2A8), // NAND_WP_B
+  IMX_PAD_NANDF_RB0 = _IMX_PAD (0x68C, 0x2A4), // NAND_READY_B
+  IMX_PAD_NANDF_CS0 = _IMX_PAD (0x65C, 0x274), // NAND_CE0_B
+  IMX_PAD_NANDF_CS1 = _IMX_PAD (0x660, 0x278), // NAND_CE1_B
+  IMX_PAD_NANDF_CS2 = _IMX_PAD (0x664, 0x27C), // NAND_CE2_B
+  IMX_PAD_NANDF_CS3 = _IMX_PAD (0x668, 0x280), // NAND_CE3_B
+  IMX_PAD_SD3_DAT7 = _IMX_PAD (0x718, 0x330), // SD3_DATA7
+  IMX_PAD_SD3_DAT6 = _IMX_PAD (0x714, 0x32C), // SD3_DATA6
+  IMX_PAD_RGMII_TXC = _IMX_PAD (0x6C0, 0x2D8), // USB_H2_DATA
+  IMX_PAD_RGMII_TD0 = _IMX_PAD (0x6AC, 0x2C4), // HSI_TX_READY
+  IMX_PAD_RGMII_TD1 = _IMX_PAD (0x6B0, 0x2C8), // HSI_RX_FLAG
+  IMX_PAD_RGMII_TD2 = _IMX_PAD (0x6B4, 0x2CC), // HSI_RX_DATA
+  IMX_PAD_RGMII_TD3 = _IMX_PAD (0x6B8, 0x2D0), // HSI_RX_WAKE
+  IMX_PAD_RGMII_RX_CTL = _IMX_PAD (0x6A4, 0x2BC), // USB_H3_DATA
+  IMX_PAD_RGMII_RD0 = _IMX_PAD (0x694, 0x2AC), // HSI_RX_READY
+  IMX_PAD_RGMII_TX_CTL = _IMX_PAD (0x6BC, 0x2D4), // USB_H2_STROBE
+  IMX_PAD_RGMII_RD1 = _IMX_PAD (0x698, 0x2B0), // HSI_TX_FLAG
+  IMX_PAD_RGMII_RD2 = _IMX_PAD (0x69C, 0x2B4), // HSI_TX_DATA
+  IMX_PAD_RGMII_RD3 = _IMX_PAD (0x6A0, 0x2B8), // HSI_TX_WAKE
+  IMX_PAD_RGMII_RXC = _IMX_PAD (0x6A8, 0x2C0), // USB_H3_STROBE
+  IMX_PAD_EIM_BCLK = _IMX_PAD (0x508, 0x138), // EIM_BCLK
+  IMX_PAD_SD3_DAT5 = _IMX_PAD (0x710, 0x328), // SD3_DATA5
+  IMX_PAD_SD3_DAT4 = _IMX_PAD (0x70C, 0x324), // SD3_DATA4
+  IMX_PAD_SD3_CMD = _IMX_PAD (0x6F8, 0x310), // SD3_CMD
+  IMX_PAD_SD3_CLK = _IMX_PAD (0x6F4, 0x30C), // SD3_CLK
+  IMX_PAD_SD3_DAT0 = _IMX_PAD (0x6FC, 0x314), // SD3_DATA0
+  IMX_PAD_SD3_DAT1 = _IMX_PAD (0x700, 0x318), // SD3_DATA1
+  IMX_PAD_SD3_DAT2 = _IMX_PAD (0x704, 0x31C), // SD3_DATA2
+  IMX_PAD_SD3_DAT3 = _IMX_PAD (0x708, 0x320), // SD3_DATA3
+  IMX_PAD_SD3_RST = _IMX_PAD (0x71C, 0x334), // SD3_RESET
+  IMX_PAD_SD4_CMD = _IMX_PAD (0x724, 0x33C), // SD4_CMD
+  IMX_PAD_SD4_CLK = _IMX_PAD (0x720, 0x338), // SD4_CLK
+  IMX_PAD_GPIO_16 = _IMX_PAD (0x5E4, 0x214), // ESAI_TX3_RX2
+  IMX_PAD_GPIO_17 = _IMX_PAD (0x5E8, 0x218), // ESAI_TX0
+  IMX_PAD_GPIO_18 = _IMX_PAD (0x5EC, 0x21C), // ESAI_TX1
+} IMX_PAD;
+
+// Alternate function numbers
+typedef enum {
+  IMX_IOMUXC_GPIO_0_ALT0_CCM_CLKO1 = 0,
+  IMX_IOMUXC_GPIO_0_ALT2_KEY_COL5 = 2,
+  IMX_IOMUXC_GPIO_0_ALT3_ASRC_EXT_CLK = 3,
+  IMX_IOMUXC_GPIO_0_ALT4_EPIT1_OUT = 4,
+  IMX_IOMUXC_GPIO_0_ALT5_GPIO1_IO00 = 5,
+  IMX_IOMUXC_GPIO_0_ALT6_USB_H1_PWR = 6,
+  IMX_IOMUXC_GPIO_0_ALT7_SNVS_VIO_5 = 7,
+} IMX_IOMUXC_GPIO_0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_1_ALT0_ESAI_RX_CLK = 0,
+  IMX_IOMUXC_GPIO_1_ALT1_WDOG2_B = 1,
+  IMX_IOMUXC_GPIO_1_ALT2_KEY_ROW5 = 2,
+  IMX_IOMUXC_GPIO_1_ALT3_USB_OTG_ID = 3,
+  IMX_IOMUXC_GPIO_1_ALT4_PWM2_OUT = 4,
+  IMX_IOMUXC_GPIO_1_ALT5_GPIO1_IO01 = 5,
+  IMX_IOMUXC_GPIO_1_ALT6_SD1_CD_B = 6, // in
+} IMX_IOMUXC_GPIO_1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_2_ALT0_ESAI_TX_FS = 0,
+  IMX_IOMUXC_GPIO_2_ALT2_KEY_ROW6 = 2,
+  IMX_IOMUXC_GPIO_2_ALT5_GPIO1_IO02 = 5,
+  IMX_IOMUXC_GPIO_2_ALT6_SD2_WP = 6,
+  IMX_IOMUXC_GPIO_2_ALT7_MLB_DATA = 7,
+} IMX_IOMUXC_GPIO_2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_3_ALT0_ESAI_RX_HF_CLK = 0,
+  IMX_IOMUXC_GPIO_3_ALT2_I2C3_SCL = 2,
+  IMX_IOMUXC_GPIO_3_ALT3_XTALOSC_REF_CLK_24M = 3,
+  IMX_IOMUXC_GPIO_3_ALT4_CCM_CLKO2 = 4,
+  IMX_IOMUXC_GPIO_3_ALT5_GPIO1_IO03 = 5,
+  IMX_IOMUXC_GPIO_3_ALT6_USB_H1_OC = 6,
+  IMX_IOMUXC_GPIO_3_ALT7_MLB_CLK = 7,
+} IMX_IOMUXC_GPIO_3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_4_ALT0_ESAI_TX_HF_CLK = 0,
+  IMX_IOMUXC_GPIO_4_ALT2_KEY_COL7 = 2,
+  IMX_IOMUXC_GPIO_4_ALT5_GPIO1_IO04 = 5,
+  IMX_IOMUXC_GPIO_4_ALT6_SD2_CD_B = 6,
+} IMX_IOMUXC_GPIO_4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_5_ALT0_ESAI_TX2_RX3 = 0,
+  IMX_IOMUXC_GPIO_5_ALT2_KEY_ROW7 = 2,
+  IMX_IOMUXC_GPIO_5_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_GPIO_5_ALT5_GPIO1_IO05 = 5,
+  IMX_IOMUXC_GPIO_5_ALT6_I2C3_SCL = 6,
+  IMX_IOMUXC_GPIO_5_ALT7_ARM_EVENTI = 7,
+} IMX_IOMUXC_GPIO_5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_6_ALT0_ESAI_TX_CLK = 0,
+  IMX_IOMUXC_GPIO_6_ALT2_I2C3_SDA = 2,
+  IMX_IOMUXC_GPIO_6_ALT5_GPIO1_IO06 = 5,
+  IMX_IOMUXC_GPIO_6_ALT6_SD2_LCTL = 6,
+  IMX_IOMUXC_GPIO_6_ALT7_MLB_SIG = 7,
+} IMX_IOMUXC_GPIO_6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_7_ALT0_ESAI_TX4_RX1 = 0,
+  IMX_IOMUXC_GPIO_7_ALT1_ECSPI5_RDY = 1,
+  IMX_IOMUXC_GPIO_7_ALT2_EPIT1_OUT = 2,
+  IMX_IOMUXC_GPIO_7_ALT3_FLEXCAN1_TX = 3,
+  IMX_IOMUXC_GPIO_7_ALT4_UART2_TX_DATA = 4,
+  IMX_IOMUXC_GPIO_7_ALT5_GPIO1_IO07 = 5,
+  IMX_IOMUXC_GPIO_7_ALT6_SPDIF_LOCK = 6,
+  IMX_IOMUXC_GPIO_7_ALT7_USB_OTG_HOST_MODE = 7,
+} IMX_IOMUXC_GPIO_7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_8_ALT0_ESAI_TX5_RX0 = 0,
+  IMX_IOMUXC_GPIO_8_ALT1_XTALOSC_REF_CLK_32K = 1,
+  IMX_IOMUXC_GPIO_8_ALT2_EPIT2_OUT = 2,
+  IMX_IOMUXC_GPIO_8_ALT3_FLEXCAN1_RX = 3,
+  IMX_IOMUXC_GPIO_8_ALT4_UART2_RX_DATA = 4,
+  IMX_IOMUXC_GPIO_8_ALT5_GPIO1_IO08 = 5,
+  IMX_IOMUXC_GPIO_8_ALT6_SPDIF_SR_CLK = 6,
+  IMX_IOMUXC_GPIO_8_ALT7_USB_OTG_PWR_CTL_WAKE = 7,
+} IMX_IOMUXC_GPIO_8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_9_ALT0_ESAI_RX_FS = 0,
+  IMX_IOMUXC_GPIO_9_ALT1_WDOG1_B = 1,
+  IMX_IOMUXC_GPIO_9_ALT2_KEY_COL6 = 2,
+  IMX_IOMUXC_GPIO_9_ALT3_CCM_REF_EN_B = 3,
+  IMX_IOMUXC_GPIO_9_ALT4_PWM1_OUT = 4,
+  IMX_IOMUXC_GPIO_9_ALT5_GPIO1_IO09 = 5,
+  IMX_IOMUXC_GPIO_9_ALT6_SD1_WP = 6,
+} IMX_IOMUXC_GPIO_9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_CLK_ALT0_SD2_CLK = 0,
+  IMX_IOMUXC_SD2_CLK_ALT1_ECSPI5_SCLK = 1,
+  IMX_IOMUXC_SD2_CLK_ALT2_KEY_COL5 = 2,
+  IMX_IOMUXC_SD2_CLK_ALT3_AUD4_RXFS = 3,
+  IMX_IOMUXC_SD2_CLK_ALT5_GPIO1_IO10 = 5,
+} IMX_IOMUXC_SD2_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_CMD_ALT0_SD2_CMD = 0,
+  IMX_IOMUXC_SD2_CMD_ALT1_ECSPI5_MOSI = 1,
+  IMX_IOMUXC_SD2_CMD_ALT2_KEY_ROW5 = 2,
+  IMX_IOMUXC_SD2_CMD_ALT3_AUD4_RXC = 3,
+  IMX_IOMUXC_SD2_CMD_ALT5_GPIO1_IO11 = 5,
+} IMX_IOMUXC_SD2_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT3_ALT0_SD2_DATA3 = 0,
+  IMX_IOMUXC_SD2_DAT3_ALT1_ECSPI5_SS3 = 1,
+  IMX_IOMUXC_SD2_DAT3_ALT2_KEY_COL6 = 2,
+  IMX_IOMUXC_SD2_DAT3_ALT3_AUD4_TXC = 3,
+  IMX_IOMUXC_SD2_DAT3_ALT5_GPIO1_IO12 = 5,
+} IMX_IOMUXC_SD2_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT2_ALT0_SD2_DATA2 = 0,
+  IMX_IOMUXC_SD2_DAT2_ALT1_ECSPI5_SS1 = 1,
+  IMX_IOMUXC_SD2_DAT2_ALT2_EIM_CS3_B = 2,
+  IMX_IOMUXC_SD2_DAT2_ALT3_AUD4_TXD = 3,
+  IMX_IOMUXC_SD2_DAT2_ALT4_KEY_ROW6 = 4,
+  IMX_IOMUXC_SD2_DAT2_ALT5_GPIO1_IO13 = 5,
+} IMX_IOMUXC_SD2_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT1_ALT0_SD2_DATA1 = 0,
+  IMX_IOMUXC_SD2_DAT1_ALT1_ECSPI5_SS0 = 1,
+  IMX_IOMUXC_SD2_DAT1_ALT2_EIM_CS2_B = 2,
+  IMX_IOMUXC_SD2_DAT1_ALT3_AUD4_TXFS = 3,
+  IMX_IOMUXC_SD2_DAT1_ALT4_KEY_COL7 = 4,
+  IMX_IOMUXC_SD2_DAT1_ALT5_GPIO1_IO14 = 5,
+} IMX_IOMUXC_SD2_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DAT0_ALT0_SD2_DATA0 = 0,
+  IMX_IOMUXC_SD2_DAT0_ALT1_ECSPI5_MISO = 1,
+  IMX_IOMUXC_SD2_DAT0_ALT3_AUD4_RXD = 3,
+  IMX_IOMUXC_SD2_DAT0_ALT4_KEY_ROW7 = 4,
+  IMX_IOMUXC_SD2_DAT0_ALT5_GPIO1_IO15 = 5,
+  IMX_IOMUXC_SD2_DAT0_ALT6_DCIC2_OUT = 6,
+} IMX_IOMUXC_SD2_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT0_ALT0_SD1_DATA0 = 0,
+  IMX_IOMUXC_SD1_DAT0_ALT1_ECSPI5_MISO = 1,
+  IMX_IOMUXC_SD1_DAT0_ALT3_GPT_CAPTURE1 = 3,
+  IMX_IOMUXC_SD1_DAT0_ALT5_GPIO1_IO16 = 5,
+} IMX_IOMUXC_SD1_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT1_ALT0_SD1_DATA1 = 0,
+  IMX_IOMUXC_SD1_DAT1_ALT1_ECSPI5_SS0 = 1,
+  IMX_IOMUXC_SD1_DAT1_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_SD1_DAT1_ALT3_GPT_CAPTURE2 = 3,
+  IMX_IOMUXC_SD1_DAT1_ALT5_GPIO1_IO17 = 5,
+} IMX_IOMUXC_SD1_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_CMD_ALT0_SD1_CMD = 0, // in and out
+  IMX_IOMUXC_SD1_CMD_ALT1_ECSPI5_MOSI = 1,
+  IMX_IOMUXC_SD1_CMD_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_SD1_CMD_ALT3_GPT_COMPARE1 = 3,
+  IMX_IOMUXC_SD1_CMD_ALT5_GPIO1_IO18 = 5,
+} IMX_IOMUXC_SD1_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT2_ALT0_SD1_DATA2 = 0,
+  IMX_IOMUXC_SD1_DAT2_ALT1_ECSPI5_SS1 = 1,
+  IMX_IOMUXC_SD1_DAT2_ALT2_GPT_COMPARE2 = 2,
+  IMX_IOMUXC_SD1_DAT2_ALT3_PWM2_OUT = 3,
+  IMX_IOMUXC_SD1_DAT2_ALT4_WDOG1_B = 4,
+  IMX_IOMUXC_SD1_DAT2_ALT5_GPIO1_IO19 = 5,
+  IMX_IOMUXC_SD1_DAT2_ALT6_WDOG1_RESET_B_DEB = 6,
+} IMX_IOMUXC_SD1_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_CLK_ALT0_SD1_CLK = 0, // out
+  IMX_IOMUXC_SD1_CLK_ALT1_ECSPI5_SCLK = 1,
+  IMX_IOMUXC_SD1_CLK_ALT2_XTALOSC_OSC32K_32K_OUT = 2,
+  IMX_IOMUXC_SD1_CLK_ALT3_GPT_CLKIN = 3,
+  IMX_IOMUXC_SD1_CLK_ALT5_GPIO1_IO20 = 5,
+} IMX_IOMUXC_SD1_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DAT3_ALT0_SD1_DATA3 = 0,
+  IMX_IOMUXC_SD1_DAT3_ALT1_ECSPI5_SS2 = 1,
+  IMX_IOMUXC_SD1_DAT3_ALT2_GPT_COMPARE3 = 2,
+  IMX_IOMUXC_SD1_DAT3_ALT3_PWM1_OUT = 3,
+  IMX_IOMUXC_SD1_DAT3_ALT4_WDOG2_B = 4,
+  IMX_IOMUXC_SD1_DAT3_ALT5_GPIO1_IO21 = 5,
+  IMX_IOMUXC_SD1_DAT3_ALT6_WDOG2_RESET_B_DEB = 6,
+} IMX_IOMUXC_SD1_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_MDIO_ALT1_ENET_MDIO = 1,
+  IMX_IOMUXC_ENET_MDIO_ALT2_ESAI_RX_CLK = 2,
+  IMX_IOMUXC_ENET_MDIO_ALT4_ENET_1588_EVENT1_OUT = 4,
+  IMX_IOMUXC_ENET_MDIO_ALT5_GPIO1_IO22 = 5,
+  IMX_IOMUXC_ENET_MDIO_ALT6_SPDIF_LOCK = 6,
+} IMX_IOMUXC_ENET_MDIO_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_REF_CLK_ALT1_ENET_TX_CLK = 1,
+  IMX_IOMUXC_ENET_REF_CLK_ALT2_ESAI_RX_FS = 2,
+  IMX_IOMUXC_ENET_REF_CLK_ALT5_GPIO1_IO23 = 5,
+  IMX_IOMUXC_ENET_REF_CLK_ALT6_SPDIF_SR_CLK = 6,
+} IMX_IOMUXC_ENET_REF_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_RX_ER_ALT0_USB_OTG_ID = 0,
+  IMX_IOMUXC_ENET_RX_ER_ALT1_ENET_RX_ER = 1,
+  IMX_IOMUXC_ENET_RX_ER_ALT2_ESAI_RX_HF_CLK = 2,
+  IMX_IOMUXC_ENET_RX_ER_ALT3_SPDIF_IN = 3,
+  IMX_IOMUXC_ENET_RX_ER_ALT4_ENET_1588_EVENT2_OUT = 4,
+  IMX_IOMUXC_ENET_RX_ER_ALT5_GPIO1_IO24 = 5,
+} IMX_IOMUXC_ENET_RX_ER_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_CRS_DV_ALT1_ENET_RX_EN = 1,
+  IMX_IOMUXC_ENET_CRS_DV_ALT2_ESAI_TX_CLK = 2,
+  IMX_IOMUXC_ENET_CRS_DV_ALT3_SPDIF_EXT_CLK = 3,
+  IMX_IOMUXC_ENET_CRS_DV_ALT5_GPIO1_IO25 = 5,
+} IMX_IOMUXC_ENET_CRS_DV_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_RXD1_ALT0_MLB_SIG = 0,
+  IMX_IOMUXC_ENET_RXD1_ALT1_ENET_RX_DATA1 = 1,
+  IMX_IOMUXC_ENET_RXD1_ALT2_ESAI_TX_FS = 2,
+  IMX_IOMUXC_ENET_RXD1_ALT4_ENET_1588_EVENT3_OUT = 4,
+  IMX_IOMUXC_ENET_RXD1_ALT5_GPIO1_IO26 = 5,
+} IMX_IOMUXC_ENET_RXD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_RXD0_ALT0_XTALOSC_OSC32K_32K_OUT = 0,
+  IMX_IOMUXC_ENET_RXD0_ALT1_ENET_RX_DATA0 = 1,
+  IMX_IOMUXC_ENET_RXD0_ALT2_ESAI_TX_HF_CLK = 2,
+  IMX_IOMUXC_ENET_RXD0_ALT3_SPDIF_OUT = 3,
+  IMX_IOMUXC_ENET_RXD0_ALT5_GPIO1_IO27 = 5,
+} IMX_IOMUXC_ENET_RXD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_TX_EN_ALT1_ENET_TX_EN = 1,
+  IMX_IOMUXC_ENET_TX_EN_ALT2_ESAI_TX3_RX2 = 2,
+  IMX_IOMUXC_ENET_TX_EN_ALT5_GPIO1_IO28 = 5,
+} IMX_IOMUXC_ENET_TX_EN_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_TXD1_ALT0_MLB_CLK = 0,
+  IMX_IOMUXC_ENET_TXD1_ALT1_ENET_TX_DATA1 = 1,
+  IMX_IOMUXC_ENET_TXD1_ALT2_ESAI_TX2_RX3 = 2,
+  IMX_IOMUXC_ENET_TXD1_ALT4_ENET_1588_EVENT0_IN = 4,
+  IMX_IOMUXC_ENET_TXD1_ALT5_GPIO1_IO29 = 5,
+} IMX_IOMUXC_ENET_TXD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_TXD0_ALT1_ENET_TX_DATA0 = 1,
+  IMX_IOMUXC_ENET_TXD0_ALT2_ESAI_TX4_RX1 = 2,
+  IMX_IOMUXC_ENET_TXD0_ALT5_GPIO1_IO30 = 5,
+} IMX_IOMUXC_ENET_TXD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET_MDC_ALT0_MLB_DATA = 0,
+  IMX_IOMUXC_ENET_MDC_ALT1_ENET_MDC = 1,
+  IMX_IOMUXC_ENET_MDC_ALT2_ESAI_TX5_RX0 = 2,
+  IMX_IOMUXC_ENET_MDC_ALT4_ENET_1588_EVENT1_IN = 4,
+  IMX_IOMUXC_ENET_MDC_ALT5_GPIO1_IO31 = 5,
+} IMX_IOMUXC_ENET_MDC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D0_ALT0_NAND_DATA00 = 0,
+  IMX_IOMUXC_NANDF_D0_ALT1_SD1_DATA4 = 1,
+  IMX_IOMUXC_NANDF_D0_ALT5_GPIO2_IO00 = 5,
+} IMX_IOMUXC_NANDF_D0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D1_ALT0_NAND_DATA01 = 0,
+  IMX_IOMUXC_NANDF_D1_ALT1_SD1_DATA5 = 1,
+  IMX_IOMUXC_NANDF_D1_ALT5_GPIO2_IO01 = 5,
+} IMX_IOMUXC_NANDF_D1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D2_ALT0_NAND_DATA02 = 0,
+  IMX_IOMUXC_NANDF_D2_ALT1_SD1_DATA6 = 1,
+  IMX_IOMUXC_NANDF_D2_ALT5_GPIO2_IO02 = 5,
+} IMX_IOMUXC_NANDF_D2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D3_ALT0_NAND_DATA03 = 0,
+  IMX_IOMUXC_NANDF_D3_ALT1_SD1_DATA7 = 1,
+  IMX_IOMUXC_NANDF_D3_ALT5_GPIO2_IO03 = 5,
+} IMX_IOMUXC_NANDF_D3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D4_ALT0_NAND_DATA04 = 0,
+  IMX_IOMUXC_NANDF_D4_ALT1_SD2_DATA4 = 1,
+  IMX_IOMUXC_NANDF_D4_ALT5_GPIO2_IO04 = 5,
+} IMX_IOMUXC_NANDF_D4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D5_ALT0_NAND_DATA05 = 0,
+  IMX_IOMUXC_NANDF_D5_ALT1_SD2_DATA5 = 1,
+  IMX_IOMUXC_NANDF_D5_ALT5_GPIO2_IO05 = 5,
+} IMX_IOMUXC_NANDF_D5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D6_ALT0_NAND_DATA06 = 0,
+  IMX_IOMUXC_NANDF_D6_ALT1_SD2_DATA6 = 1,
+  IMX_IOMUXC_NANDF_D6_ALT5_GPIO2_IO06 = 5,
+} IMX_IOMUXC_NANDF_D6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_D7_ALT0_NAND_DATA07 = 0,
+  IMX_IOMUXC_NANDF_D7_ALT1_SD2_DATA7 = 1,
+  IMX_IOMUXC_NANDF_D7_ALT5_GPIO2_IO07 = 5,
+} IMX_IOMUXC_NANDF_D7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT0_ALT1_SD4_DATA0 = 1,
+  IMX_IOMUXC_SD4_DAT0_ALT2_NAND_DQS = 2,
+  IMX_IOMUXC_SD4_DAT0_ALT5_GPIO2_IO08 = 5,
+} IMX_IOMUXC_SD4_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT1_ALT1_SD4_DATA1 = 1,
+  IMX_IOMUXC_SD4_DAT1_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_SD4_DAT1_ALT5_GPIO2_IO09 = 5,
+} IMX_IOMUXC_SD4_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT2_ALT1_SD4_DATA2 = 1,
+  IMX_IOMUXC_SD4_DAT2_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_SD4_DAT2_ALT5_GPIO2_IO10 = 5,
+} IMX_IOMUXC_SD4_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT3_ALT1_SD4_DATA3 = 1,
+  IMX_IOMUXC_SD4_DAT3_ALT5_GPIO2_IO11 = 5,
+} IMX_IOMUXC_SD4_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT4_ALT1_SD4_DATA4 = 1,
+  IMX_IOMUXC_SD4_DAT4_ALT2_UART2_RX_DATA = 2,
+  IMX_IOMUXC_SD4_DAT4_ALT5_GPIO2_IO12 = 5,
+} IMX_IOMUXC_SD4_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT5_ALT1_SD4_DATA5 = 1,
+  IMX_IOMUXC_SD4_DAT5_ALT2_UART2_RTS_B = 2,
+  IMX_IOMUXC_SD4_DAT5_ALT5_GPIO2_IO13 = 5,
+} IMX_IOMUXC_SD4_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT6_ALT1_SD4_DATA6 = 1,
+  IMX_IOMUXC_SD4_DAT6_ALT2_UART2_CTS_B = 2,
+  IMX_IOMUXC_SD4_DAT6_ALT5_GPIO2_IO14 = 5,
+} IMX_IOMUXC_SD4_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DAT7_ALT1_SD4_DATA7 = 1,
+  IMX_IOMUXC_SD4_DAT7_ALT2_UART2_TX_DATA = 2,
+  IMX_IOMUXC_SD4_DAT7_ALT5_GPIO2_IO15 = 5,
+} IMX_IOMUXC_SD4_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A22_ALT0_EIM_ADDR22 = 0,
+  IMX_IOMUXC_EIM_A22_ALT1_IPU1_DISP1_DATA17 = 1,
+  IMX_IOMUXC_EIM_A22_ALT2_IPU1_CSI1_DATA17 = 2,
+  IMX_IOMUXC_EIM_A22_ALT5_GPIO2_IO16 = 5,
+  IMX_IOMUXC_EIM_A22_ALT7_SRC_BOOT_CFG22 = 7,
+  IMX_IOMUXC_EIM_A22_ALT8_EPDC_GDSP = 8,
+} IMX_IOMUXC_EIM_A22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A21_ALT0_EIM_ADDR21 = 0,
+  IMX_IOMUXC_EIM_A21_ALT1_IPU1_DISP1_DATA16 = 1,
+  IMX_IOMUXC_EIM_A21_ALT2_IPU1_CSI1_DATA16 = 2,
+  IMX_IOMUXC_EIM_A21_ALT5_GPIO2_IO17 = 5,
+  IMX_IOMUXC_EIM_A21_ALT7_SRC_BOOT_CFG21 = 7,
+  IMX_IOMUXC_EIM_A21_ALT8_EPDC_GDCLK = 8
+} IMX_IOMUXC_EIM_A21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A20_ALT0_EIM_ADDR20 = 0,
+  IMX_IOMUXC_EIM_A20_ALT1_IPU1_DISP1_DATA15 = 1,
+  IMX_IOMUXC_EIM_A20_ALT2_IPU1_CSI1_DATA15 = 2,
+  IMX_IOMUXC_EIM_A20_ALT5_GPIO2_IO18 = 5,
+  IMX_IOMUXC_EIM_A20_ALT7_SRC_BOOT_CFG20 = 7,
+  IMX_IOMUXC_EIM_A20_ALT8_EPDC_PWR_CTRL2 = 8
+} IMX_IOMUXC_EIM_A20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A19_ALT0_EIM_ADDR19 = 0,
+  IMX_IOMUXC_EIM_A19_ALT1_IPU1_DISP1_DATA14 = 1,
+  IMX_IOMUXC_EIM_A19_ALT2_IPU1_CSI1_DATA14 = 2,
+  IMX_IOMUXC_EIM_A19_ALT5_GPIO2_IO19 = 5,
+  IMX_IOMUXC_EIM_A19_ALT7_SRC_BOOT_CFG19 = 7,
+  IMX_IOMUXC_EIM_A19_ALT8_EPDC_PWR_CTRL1 = 8
+} IMX_IOMUXC_EIM_A19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A18_ALT0_EIM_ADDR18 = 0,
+  IMX_IOMUXC_EIM_A18_ALT1_IPU1_DISP1_DATA13 = 1,
+  IMX_IOMUXC_EIM_A18_ALT2_IPU1_CSI1_DATA13 = 2,
+  IMX_IOMUXC_EIM_A18_ALT5_GPIO2_IO20 = 5,
+  IMX_IOMUXC_EIM_A18_ALT7_SRC_BOOT_CFG18 = 7,
+  IMX_IOMUXC_EIM_A18_ALT8_EPDC_PWR_CTRL0 = 8
+} IMX_IOMUXC_EIM_A18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A17_ALT0_EIM_ADDR17 = 0,
+  IMX_IOMUXC_EIM_A17_ALT1_IPU1_DISP1_DATA12 = 1,
+  IMX_IOMUXC_EIM_A17_ALT2_IPU1_CSI1_DATA12 = 2,
+  IMX_IOMUXC_EIM_A17_ALT5_GPIO2_IO21 = 5,
+  IMX_IOMUXC_EIM_A17_ALT7_SRC_BOOT_CFG17 = 7,
+  IMX_IOMUXC_EIM_A17_ALT8_EPDC_PWR_STAT = 8
+} IMX_IOMUXC_EIM_A17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A16_ALT0_EIM_ADDR16 = 0,
+  IMX_IOMUXC_EIM_A16_ALT1_IPU1_DI1_DISP_CLK = 1,
+  IMX_IOMUXC_EIM_A16_ALT2_IPU1_CSI1_PIXCLK = 2,
+  IMX_IOMUXC_EIM_A16_ALT5_GPIO2_IO22 = 5,
+  IMX_IOMUXC_EIM_A16_ALT7_SRC_BOOT_CFG16 = 7,
+  IMX_IOMUXC_EIM_A16_ALT8_EPDC_DATA00 = 8
+} IMX_IOMUXC_EIM_A16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_CS0_ALT0_EIM_CS0_B = 0,
+  IMX_IOMUXC_EIM_CS0_ALT1_IPU1_DI1_PIN05 = 1,
+  IMX_IOMUXC_EIM_CS0_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_EIM_CS0_ALT5_GPIO2_IO23 = 5,
+} IMX_IOMUXC_EIM_CS0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_CS1_ALT0_EIM_CS1_B = 0,
+  IMX_IOMUXC_EIM_CS1_ALT1_IPU1_DI1_PIN06 = 1,
+  IMX_IOMUXC_EIM_CS1_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_EIM_CS1_ALT5_GPIO2_IO24 = 5,
+} IMX_IOMUXC_EIM_CS1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_OE_ALT0_EIM_OE_B = 0,
+  IMX_IOMUXC_EIM_OE_ALT1_IPU1_DI1_PIN07 = 1,
+  IMX_IOMUXC_EIM_OE_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_EIM_OE_ALT5_GPIO2_IO25 = 5,
+} IMX_IOMUXC_EIM_OE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_RW_ALT0_EIM_RW = 0,
+  IMX_IOMUXC_EIM_RW_ALT1_IPU1_DI1_PIN08 = 1,
+  IMX_IOMUXC_EIM_RW_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_EIM_RW_ALT5_GPIO2_IO26 = 5,
+  IMX_IOMUXC_EIM_RW_ALT7_SRC_BOOT_CFG29 = 7,
+} IMX_IOMUXC_EIM_RW_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_LBA_ALT0_EIM_LBA_B = 0,
+  IMX_IOMUXC_EIM_LBA_ALT1_IPU1_DI1_PIN17 = 1,
+  IMX_IOMUXC_EIM_LBA_ALT2_ECSPI2_SS1 = 2,
+  IMX_IOMUXC_EIM_LBA_ALT5_GPIO2_IO27 = 5,
+  IMX_IOMUXC_EIM_LBA_ALT7_SRC_BOOT_CFG26 = 7,
+} IMX_IOMUXC_EIM_LBA_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB0_ALT0_EIM_EB0_B = 0,
+  IMX_IOMUXC_EIM_EB0_ALT1_IPU1_DISP1_DATA11 = 1,
+  IMX_IOMUXC_EIM_EB0_ALT2_IPU1_CSI1_DATA11 = 2,
+  IMX_IOMUXC_EIM_EB0_ALT4_CCM_PMIC_READY = 4,
+  IMX_IOMUXC_EIM_EB0_ALT5_GPIO2_IO28 = 5,
+  IMX_IOMUXC_EIM_EB0_ALT7_SRC_BOOT_CFG27 = 7,
+  IMX_IOMUXC_EIM_EB0_ALT8_EPDC_PWR_COM = 8
+} IMX_IOMUXC_EIM_EB0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB1_ALT0_EIM_EB1_B = 0,
+  IMX_IOMUXC_EIM_EB1_ALT1_IPU1_DISP1_DATA10 = 1,
+  IMX_IOMUXC_EIM_EB1_ALT2_IPU1_CSI1_DATA10 = 2,
+  IMX_IOMUXC_EIM_EB1_ALT5_GPIO2_IO29 = 5,
+  IMX_IOMUXC_EIM_EB1_ALT7_SRC_BOOT_CFG28 = 7,
+  IMX_IOMUXC_EIM_EB1_ALT8_EPDC_SDSHR = 8
+} IMX_IOMUXC_EIM_EB1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB2_ALT0_EIM_EB2_B = 0,
+  IMX_IOMUXC_EIM_EB2_ALT1_ECSPI1_SS0 = 1,
+  IMX_IOMUXC_EIM_EB2_ALT3_IPU1_CSI1_DATA19 = 3,
+  IMX_IOMUXC_EIM_EB2_ALT4_HDMI_TX_DDC_SCL = 4,
+  IMX_IOMUXC_EIM_EB2_ALT5_GPIO2_IO30 = 5,
+  IMX_IOMUXC_EIM_EB2_ALT6_I2C2_SCL = 6,
+  IMX_IOMUXC_EIM_EB2_ALT7_SRC_BOOT_CFG30 = 7,
+  IMX_IOMUXC_EIM_EB2_ALT8_EPDC_DATA05 = 8
+} IMX_IOMUXC_EIM_EB2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_EB3_ALT0_EIM_EB3_B = 0,
+  IMX_IOMUXC_EIM_EB3_ALT1_ECSPI4_RDY = 1,
+  IMX_IOMUXC_EIM_EB3_ALT2_UART3_RTS_B = 2,
+  IMX_IOMUXC_EIM_EB3_ALT3_UART1_RI_B = 3,
+  IMX_IOMUXC_EIM_EB3_ALT4_IPU1_CSI1_HSYNC = 4,
+  IMX_IOMUXC_EIM_EB3_ALT5_GPIO2_IO31 = 5,
+  IMX_IOMUXC_EIM_EB3_ALT6_IPU1_DI1_PIN03 = 6,
+  IMX_IOMUXC_EIM_EB3_ALT7_SRC_BOOT_CFG31 = 7,
+  IMX_IOMUXC_EIM_EB3_ALT8_EPDC_SDCE0 = 8,
+  IMX_IOMUXC_EIM_EB3_ALT9_EIM_ACLK_FREERUN = 9
+} IMX_IOMUXC_EIM_EB3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA0_ALT0_EIM_AD00 = 0,
+  IMX_IOMUXC_EIM_DA0_ALT1_IPU1_DISP1_DATA09 = 1,
+  IMX_IOMUXC_EIM_DA0_ALT2_IPU1_CSI1_DATA09 = 2,
+  IMX_IOMUXC_EIM_DA0_ALT5_GPIO3_IO00 = 5,
+  IMX_IOMUXC_EIM_DA0_ALT7_SRC_BOOT_CFG00 = 7,
+  IMX_IOMUXC_EIM_DA0_ALT8_EPDC_SDCLK_N = 8
+} IMX_IOMUXC_EIM_DA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA1_ALT0_EIM_AD01 = 0,
+  IMX_IOMUXC_EIM_DA1_ALT1_IPU1_DISP1_DATA08 = 1,
+  IMX_IOMUXC_EIM_DA1_ALT2_IPU1_CSI1_DATA08 = 2,
+  IMX_IOMUXC_EIM_DA1_ALT5_GPIO3_IO01 = 5,
+  IMX_IOMUXC_EIM_DA1_ALT7_SRC_BOOT_CFG01 = 7,
+  IMX_IOMUXC_EIM_DA1_ALT8_EPDC_SDLE = 8
+} IMX_IOMUXC_EIM_DA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA2_ALT0_EIM_AD02 = 0,
+  IMX_IOMUXC_EIM_DA2_ALT1_IPU1_DISP1_DATA07 = 1,
+  IMX_IOMUXC_EIM_DA2_ALT2_IPU1_CSI1_DATA07 = 2,
+  IMX_IOMUXC_EIM_DA2_ALT5_GPIO3_IO02 = 5,
+  IMX_IOMUXC_EIM_DA2_ALT7_SRC_BOOT_CFG02 = 7,
+  IMX_IOMUXC_EIM_DA2_ALT8_EPDC_BDR02 = 8
+} IMX_IOMUXC_EIM_DA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA3_ALT0_EIM_AD03 = 0,
+  IMX_IOMUXC_EIM_DA3_ALT1_IPU1_DISP1_DATA06 = 1,
+  IMX_IOMUXC_EIM_DA3_ALT2_IPU1_CSI1_DATA06 = 2,
+  IMX_IOMUXC_EIM_DA3_ALT5_GPIO3_IO03 = 5,
+  IMX_IOMUXC_EIM_DA3_ALT7_SRC_BOOT_CFG03 = 7,
+  IMX_IOMUXC_EIM_DA3_ALT8_EPDC_BDR1 = 8
+} IMX_IOMUXC_EIM_DA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA4_ALT0_EIM_AD04 = 0,
+  IMX_IOMUXC_EIM_DA4_ALT1_IPU1_DISP1_DATA05 = 1,
+  IMX_IOMUXC_EIM_DA4_ALT2_IPU1_CSI1_DATA05 = 2,
+  IMX_IOMUXC_EIM_DA4_ALT5_GPIO3_IO04 = 5,
+  IMX_IOMUXC_EIM_DA4_ALT7_SRC_BOOT_CFG04 = 7,
+  IMX_IOMUXC_EIM_DA4_ALT8_EPDC_SDCE0 = 8
+} IMX_IOMUXC_EIM_DA4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA5_ALT0_EIM_AD05 = 0,
+  IMX_IOMUXC_EIM_DA5_ALT1_IPU1_DISP1_DATA04 = 1,
+  IMX_IOMUXC_EIM_DA5_ALT2_IPU1_CSI1_DATA04 = 2,
+  IMX_IOMUXC_EIM_DA5_ALT5_GPIO3_IO05 = 5,
+  IMX_IOMUXC_EIM_DA5_ALT7_SRC_BOOT_CFG05 = 7,
+  IMX_IOMUXC_EIM_DA5_ALT8_EPDC_SDCE1 = 8
+} IMX_IOMUXC_EIM_DA5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA6_ALT0_EIM_AD06 = 0,
+  IMX_IOMUXC_EIM_DA6_ALT1_IPU1_DISP1_DATA03 = 1,
+  IMX_IOMUXC_EIM_DA6_ALT2_IPU1_CSI1_DATA03 = 2,
+  IMX_IOMUXC_EIM_DA6_ALT5_GPIO3_IO06 = 5,
+  IMX_IOMUXC_EIM_DA6_ALT7_SRC_BOOT_CFG06 = 7,
+  IMX_IOMUXC_EIM_DA6_ALT8_EPDC_SDCE2 = 8
+} IMX_IOMUXC_EIM_DA6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA7_ALT0_EIM_AD07 = 0,
+  IMX_IOMUXC_EIM_DA7_ALT1_IPU1_DISP1_DATA02 = 1,
+  IMX_IOMUXC_EIM_DA7_ALT2_IPU1_CSI1_DATA02 = 2,
+  IMX_IOMUXC_EIM_DA7_ALT5_GPIO3_IO07 = 5,
+  IMX_IOMUXC_EIM_DA7_ALT7_SRC_BOOT_CFG07 = 7,
+  IMX_IOMUXC_EIM_DA7_ALT8_EPDC_SDCE37 = 8
+} IMX_IOMUXC_EIM_DA7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA8_ALT0_EIM_AD08 = 0,
+  IMX_IOMUXC_EIM_DA8_ALT1_IPU1_DISP1_DATA01 = 1,
+  IMX_IOMUXC_EIM_DA8_ALT2_IPU1_CSI1_DATA01 = 2,
+  IMX_IOMUXC_EIM_DA8_ALT5_GPIO3_IO08 = 5,
+  IMX_IOMUXC_EIM_DA8_ALT7_SRC_BOOT_CFG08 = 7,
+  IMX_IOMUXC_EIM_DA8_ALT8_EPDC_SDCE4 = 8
+} IMX_IOMUXC_EIM_DA8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA9_ALT0_EIM_AD09 = 0,
+  IMX_IOMUXC_EIM_DA9_ALT1_IPU1_DISP1_DATA00 = 1,
+  IMX_IOMUXC_EIM_DA9_ALT2_IPU1_CSI1_DATA00 = 2,
+  IMX_IOMUXC_EIM_DA9_ALT5_GPIO3_IO09 = 5,
+  IMX_IOMUXC_EIM_DA9_ALT7_SRC_BOOT_CFG09 = 7,
+  IMX_IOMUXC_EIM_DA9_ALT8_EPDC_SDCE5 = 8
+} IMX_IOMUXC_EIM_DA9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA10_ALT0_EIM_AD10 = 0,
+  IMX_IOMUXC_EIM_DA10_ALT1_IPU1_DI1_PIN15 = 1,
+  IMX_IOMUXC_EIM_DA10_ALT2_IPU1_CSI1_DATA_EN = 2,
+  IMX_IOMUXC_EIM_DA10_ALT5_GPIO3_IO10 = 5,
+  IMX_IOMUXC_EIM_DA10_ALT7_SRC_BOOT_CFG10 = 7,
+  IMX_IOMUXC_EIM_DA10_ALT8_EPDC_DATA01 = 8
+} IMX_IOMUXC_EIM_DA10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA11_ALT0_EIM_AD11 = 0,
+  IMX_IOMUXC_EIM_DA11_ALT1_IPU1_DI1_PIN02 = 1,
+  IMX_IOMUXC_EIM_DA11_ALT2_IPU1_CSI1_HSYNC = 2,
+  IMX_IOMUXC_EIM_DA11_ALT5_GPIO3_IO11 = 5,
+  IMX_IOMUXC_EIM_DA11_ALT7_SRC_BOOT_CFG11 = 7,
+  IMX_IOMUXC_EIM_DA11_ALT8_EPDC_DATA03 = 8
+} IMX_IOMUXC_EIM_DA11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA12_ALT0_EIM_AD12 = 0,
+  IMX_IOMUXC_EIM_DA12_ALT1_IPU1_DI1_PIN03 = 1,
+  IMX_IOMUXC_EIM_DA12_ALT2_IPU1_CSI1_VSYNC = 2,
+  IMX_IOMUXC_EIM_DA12_ALT5_GPIO3_IO12 = 5,
+  IMX_IOMUXC_EIM_DA12_ALT7_SRC_BOOT_CFG12 = 7,
+  IMX_IOMUXC_EIM_DA12_ALT8_EPDC_DATA02 = 8
+} IMX_IOMUXC_EIM_DA12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA13_ALT0_EIM_AD13 = 0,
+  IMX_IOMUXC_EIM_DA13_ALT1_IPU1_DI1_D0_CS = 1,
+  IMX_IOMUXC_EIM_DA13_ALT5_GPIO3_IO13 = 5,
+  IMX_IOMUXC_EIM_DA13_ALT7_SRC_BOOT_CFG13 = 7,
+} IMX_IOMUXC_EIM_DA13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA14_ALT0_EIM_AD14 = 0,
+  IMX_IOMUXC_EIM_DA14_ALT1_IPU1_DI1_D1_CS = 1,
+  IMX_IOMUXC_EIM_DA14_ALT5_GPIO3_IO14 = 5,
+  IMX_IOMUXC_EIM_DA14_ALT7_SRC_BOOT_CFG14 = 7,
+} IMX_IOMUXC_EIM_DA14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_DA15_ALT0_EIM_AD15 = 0,
+  IMX_IOMUXC_EIM_DA15_ALT1_IPU1_DI1_PIN01 = 1,
+  IMX_IOMUXC_EIM_DA15_ALT2_IPU1_DI1_PIN04 = 2,
+  IMX_IOMUXC_EIM_DA15_ALT5_GPIO3_IO15 = 5,
+  IMX_IOMUXC_EIM_DA15_ALT7_SRC_BOOT_CFG15 = 7,
+} IMX_IOMUXC_EIM_DA15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D16_ALT0_EIM_DATA16 = 0,
+  IMX_IOMUXC_EIM_D16_ALT1_ECSPI1_SCLK = 1,
+  IMX_IOMUXC_EIM_D16_ALT2_IPU1_DI0_PIN05 = 2,
+  IMX_IOMUXC_EIM_D16_ALT3_IPU1_CSI1_DATA18 = 3,
+  IMX_IOMUXC_EIM_D16_ALT4_HDMI_TX_DDC_SDA = 4,
+  IMX_IOMUXC_EIM_D16_ALT5_GPIO3_IO16 = 5,
+  IMX_IOMUXC_EIM_D16_ALT6_I2C2_SDA = 6,
+  IMX_IOMUXC_EIM_D16_ALT8_EPDC_DATA10 = 8
+} IMX_IOMUXC_EIM_D16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D17_ALT0_EIM_DATA17 = 0,
+  IMX_IOMUXC_EIM_D17_ALT1_ECSPI1_MISO = 1,
+  IMX_IOMUXC_EIM_D17_ALT2_IPU1_DI0_PIN06 = 2,
+  IMX_IOMUXC_EIM_D17_ALT3_IPU1_CSI1_PIXCLK = 3,
+  IMX_IOMUXC_EIM_D17_ALT4_DCIC1_OUT = 4,
+  IMX_IOMUXC_EIM_D17_ALT5_GPIO3_IO17 = 5,
+  IMX_IOMUXC_EIM_D17_ALT6_I2C3_SCL = 6,
+  IMX_IOMUXC_EIM_D17_ALT8_EPDC_VCOM0 = 8
+} IMX_IOMUXC_EIM_D17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D18_ALT0_EIM_DATA18 = 0,
+  IMX_IOMUXC_EIM_D18_ALT1_ECSPI1_MOSI = 1,
+  IMX_IOMUXC_EIM_D18_ALT2_IPU1_DI0_PIN07 = 2,
+  IMX_IOMUXC_EIM_D18_ALT3_IPU1_CSI1_DATA17 = 3,
+  IMX_IOMUXC_EIM_D18_ALT4_IPU1_DI1_D0_CS = 4,
+  IMX_IOMUXC_EIM_D18_ALT5_GPIO3_IO18 = 5,
+  IMX_IOMUXC_EIM_D18_ALT6_I2C3_SDA = 6,
+  IMX_IOMUXC_EIM_D18_ALT8_EPDC_VCOM1 = 8
+} IMX_IOMUXC_EIM_D18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D19_ALT0_EIM_DATA19 = 0,
+  IMX_IOMUXC_EIM_D19_ALT1_ECSPI1_SS1 = 1,
+  IMX_IOMUXC_EIM_D19_ALT2_IPU1_DI0_PIN08 = 2,
+  IMX_IOMUXC_EIM_D19_ALT3_IPU1_CSI1_DATA16 = 3,
+  IMX_IOMUXC_EIM_D19_ALT4_UART1_CTS_B = 4,
+  IMX_IOMUXC_EIM_D19_ALT5_GPIO3_IO19 = 5,
+  IMX_IOMUXC_EIM_D19_ALT6_EPIT1_OUT = 6,
+  IMX_IOMUXC_EIM_D19_ALT8_EPDC_DATA12 = 8
+} IMX_IOMUXC_EIM_D19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D20_ALT0_EIM_DATA20 = 0,
+  IMX_IOMUXC_EIM_D20_ALT1_ECSPI4_SS0 = 1,
+  IMX_IOMUXC_EIM_D20_ALT2_IPU1_DI0_PIN16 = 2,
+  IMX_IOMUXC_EIM_D20_ALT3_IPU1_CSI1_DATA15 = 3,
+  IMX_IOMUXC_EIM_D20_ALT4_UART1_RTS_B = 4,
+  IMX_IOMUXC_EIM_D20_ALT5_GPIO3_IO20 = 5,
+  IMX_IOMUXC_EIM_D20_ALT6_EPIT2_OUT = 6
+} IMX_IOMUXC_EIM_D20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D21_ALT0_EIM_DATA21 = 0,
+  IMX_IOMUXC_EIM_D21_ALT1_ECSPI4_SCLK = 1,
+  IMX_IOMUXC_EIM_D21_ALT2_IPU1_DI0_PIN17 = 2,
+  IMX_IOMUXC_EIM_D21_ALT3_IPU1_CSI1_DATA11 = 3,
+  IMX_IOMUXC_EIM_D21_ALT4_USB_OTG_OC = 4,
+  IMX_IOMUXC_EIM_D21_ALT5_GPIO3_IO21 = 5,
+  IMX_IOMUXC_EIM_D21_ALT6_I2C1_SCL = 6,
+  IMX_IOMUXC_EIM_D21_ALT7_SPDIF_IN = 7,
+} IMX_IOMUXC_EIM_D21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D22_ALT0_EIM_DATA22 = 0,
+  IMX_IOMUXC_EIM_D22_ALT1_ECSPI4_MISO = 1,
+  IMX_IOMUXC_EIM_D22_ALT2_IPU1_DI0_PIN01 = 2,
+  IMX_IOMUXC_EIM_D22_ALT3_IPU1_CSI1_DATA10 = 3,
+  IMX_IOMUXC_EIM_D22_ALT4_USB_OTG_PWR = 4,
+  IMX_IOMUXC_EIM_D22_ALT5_GPIO3_IO22 = 5,
+  IMX_IOMUXC_EIM_D22_ALT6_SPDIF_OUT = 6,
+  IMX_IOMUXC_EIM_D22_ALT8_EPDC_SDCE6 = 8
+} IMX_IOMUXC_EIM_D22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D23_ALT0_EIM_DATA23 = 0,
+  IMX_IOMUXC_EIM_D23_ALT1_IPU1_DI0_D0_CS = 1,
+  IMX_IOMUXC_EIM_D23_ALT2_UART3_CTS_B = 2,
+  IMX_IOMUXC_EIM_D23_ALT3_UART1_DCD_B = 3,
+  IMX_IOMUXC_EIM_D23_ALT4_IPU1_CSI1_DATA_EN = 4,
+  IMX_IOMUXC_EIM_D23_ALT5_GPIO3_IO23 = 5,
+  IMX_IOMUXC_EIM_D23_ALT6_IPU1_DI1_PIN02 = 6,
+  IMX_IOMUXC_EIM_D23_ALT7_IPU1_DI1_PIN14 = 7,
+  IMX_IOMUXC_EIM_D23_ALT8_EPDC_DATA11 = 8
+} IMX_IOMUXC_EIM_D23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D24_ALT0_EIM_DATA24 = 0,
+  IMX_IOMUXC_EIM_D24_ALT1_ECSPI4_SS2 = 1,
+  IMX_IOMUXC_EIM_D24_ALT2_UART3_TX_DATA = 2,
+  IMX_IOMUXC_EIM_D24_ALT3_ECSPI1_SS2 = 3,
+  IMX_IOMUXC_EIM_D24_ALT4_ECSPI2_SS2 = 4,
+  IMX_IOMUXC_EIM_D24_ALT5_GPIO3_IO24 = 5,
+  IMX_IOMUXC_EIM_D24_ALT6_AUD5_RXFS = 6,
+  IMX_IOMUXC_EIM_D24_ALT7_UART1_DTR_B = 7,
+} IMX_IOMUXC_EIM_D24_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D25_ALT0_EIM_DATA25 = 0,
+  IMX_IOMUXC_EIM_D25_ALT1_ECSPI4_SS3 = 1,
+  IMX_IOMUXC_EIM_D25_ALT2_UART3_RX_DATA = 2,
+  IMX_IOMUXC_EIM_D25_ALT3_ECSPI1_SS3 = 3,
+  IMX_IOMUXC_EIM_D25_ALT4_ECSPI2_SS3 = 4,
+  IMX_IOMUXC_EIM_D25_ALT5_GPIO3_IO25 = 5,
+  IMX_IOMUXC_EIM_D25_ALT6_AUD5_RXC = 6,
+  IMX_IOMUXC_EIM_D25_ALT7_UART1_DSR_B = 7,
+} IMX_IOMUXC_EIM_D25_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D26_ALT0_EIM_DATA26 = 0,
+  IMX_IOMUXC_EIM_D26_ALT1_IPU1_DI1_PIN11 = 1,
+  IMX_IOMUXC_EIM_D26_ALT2_IPU1_CSI0_DATA01 = 2,
+  IMX_IOMUXC_EIM_D26_ALT3_IPU1_CSI1_DATA14 = 3,
+  IMX_IOMUXC_EIM_D26_ALT4_UART2_TX_DATA = 4,
+  IMX_IOMUXC_EIM_D26_ALT5_GPIO3_IO26 = 5,
+  IMX_IOMUXC_EIM_D26_ALT6_IPU1_SISG2 = 6,
+  IMX_IOMUXC_EIM_D26_ALT7_IPU1_DISP1_DATA22 = 7,
+  IMX_IOMUXC_EIM_D26_ALT8_EPDC_SDOE = 8
+} IMX_IOMUXC_EIM_D26_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D27_ALT0_EIM_DATA27 = 0,
+  IMX_IOMUXC_EIM_D27_ALT1_IPU1_DI1_PIN13 = 1,
+  IMX_IOMUXC_EIM_D27_ALT2_IPU1_CSI0_DATA00 = 2,
+  IMX_IOMUXC_EIM_D27_ALT3_IPU1_CSI1_DATA13 = 3,
+  IMX_IOMUXC_EIM_D27_ALT4_UART2_RX_DATA = 4,
+  IMX_IOMUXC_EIM_D27_ALT5_GPIO3_IO27 = 5,
+  IMX_IOMUXC_EIM_D27_ALT6_IPU1_SISG3 = 6,
+  IMX_IOMUXC_EIM_D27_ALT7_IPU1_DISP1_DATA23 = 7,
+  IMX_IOMUXC_EIM_D27_ALT8_EPDC_SDOE = 8
+} IMX_IOMUXC_EIM_D27_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D28_ALT0_EIM_DATA28 = 0,
+  IMX_IOMUXC_EIM_D28_ALT1_I2C1_SDA = 1,
+  IMX_IOMUXC_EIM_D28_ALT2_ECSPI4_MOSI = 2,
+  IMX_IOMUXC_EIM_D28_ALT3_IPU1_CSI1_DATA12 = 3,
+  IMX_IOMUXC_EIM_D28_ALT4_UART2_CTS_B = 4,
+  IMX_IOMUXC_EIM_D28_ALT5_GPIO3_IO28 = 5,
+  IMX_IOMUXC_EIM_D28_ALT6_IPU1_EXT_TRIG = 6,
+  IMX_IOMUXC_EIM_D28_ALT7_IPU1_DI0_PIN13 = 7,
+  IMX_IOMUXC_EIM_D28_ALT8_EPDC_PWR_CTRL3 = 8
+} IMX_IOMUXC_EIM_D28_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D29_ALT0_EIM_DATA29 = 0,
+  IMX_IOMUXC_EIM_D29_ALT1_IPU1_DI1_PIN15 = 1,
+  IMX_IOMUXC_EIM_D29_ALT2_ECSPI4_SS0 = 2,
+  IMX_IOMUXC_EIM_D29_ALT4_UART2_RTS_B = 4,
+  IMX_IOMUXC_EIM_D29_ALT5_GPIO3_IO29 = 5,
+  IMX_IOMUXC_EIM_D29_ALT6_IPU1_CSI1_VSYNC = 6,
+  IMX_IOMUXC_EIM_D29_ALT7_IPU1_DI0_PIN14 = 7,
+  IMX_IOMUXC_EIM_D29_ALT8_EPDC_PWR_WAKE = 8
+} IMX_IOMUXC_EIM_D29_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D30_ALT0_EIM_DATA30 = 0,
+  IMX_IOMUXC_EIM_D30_ALT1_IPU1_DISP1_DATA21 = 1,
+  IMX_IOMUXC_EIM_D30_ALT2_IPU1_DI0_PIN11 = 2,
+  IMX_IOMUXC_EIM_D30_ALT3_IPU1_CSI0_DATA03 = 3,
+  IMX_IOMUXC_EIM_D30_ALT4_UART3_CTS_B = 4,
+  IMX_IOMUXC_EIM_D30_ALT5_GPIO3_IO30 = 5,
+  IMX_IOMUXC_EIM_D30_ALT6_USB_H1_OC = 6,
+} IMX_IOMUXC_EIM_D30_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_D31_ALT0_EIM_DATA31 = 0,
+  IMX_IOMUXC_EIM_D31_ALT1_IPU1_DISP1_DATA20 = 1,
+  IMX_IOMUXC_EIM_D31_ALT2_IPU1_DI0_PIN12 = 2,
+  IMX_IOMUXC_EIM_D31_ALT3_IPU1_CSI0_DATA02 = 3,
+  IMX_IOMUXC_EIM_D31_ALT4_UART3_RTS_B = 4,
+  IMX_IOMUXC_EIM_D31_ALT5_GPIO3_IO31 = 5,
+  IMX_IOMUXC_EIM_D31_ALT6_USB_H1_PWR = 6,
+} IMX_IOMUXC_EIM_D31_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_19_ALT0_KEY_COL5 = 0,
+  IMX_IOMUXC_GPIO_19_ALT1_ENET_1588_EVENT0_OUT = 1,
+  IMX_IOMUXC_GPIO_19_ALT2_SPDIF_OUT = 2,
+  IMX_IOMUXC_GPIO_19_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_GPIO_19_ALT4_ECSPI1_RDY = 4,
+  IMX_IOMUXC_GPIO_19_ALT5_GPIO4_IO05 = 5,
+  IMX_IOMUXC_GPIO_19_ALT6_ENET_TX_ER = 6,
+} IMX_IOMUXC_GPIO_19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL0_ALT0_ECSPI1_SCLK = 0,
+  IMX_IOMUXC_KEY_COL0_ALT1_ENET_RX_DATA3 = 1,
+  IMX_IOMUXC_KEY_COL0_ALT2_AUD5_TXC = 2,
+  IMX_IOMUXC_KEY_COL0_ALT3_KEY_COL0 = 3,
+  IMX_IOMUXC_KEY_COL0_ALT4_UART4_TX_DATA = 4,
+  IMX_IOMUXC_KEY_COL0_ALT5_GPIO4_IO06 = 5,
+  IMX_IOMUXC_KEY_COL0_ALT6_DCIC1_OUT = 6,
+} IMX_IOMUXC_KEY_COL0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW0_ALT0_ECSPI1_MOSI = 0,
+  IMX_IOMUXC_KEY_ROW0_ALT1_ENET_TX_DATA3 = 1,
+  IMX_IOMUXC_KEY_ROW0_ALT2_AUD5_TXD = 2,
+  IMX_IOMUXC_KEY_ROW0_ALT3_KEY_ROW0 = 3,
+  IMX_IOMUXC_KEY_ROW0_ALT4_UART4_RX_DATA = 4,
+  IMX_IOMUXC_KEY_ROW0_ALT5_GPIO4_IO07 = 5,
+  IMX_IOMUXC_KEY_ROW0_ALT6_DCIC2_OUT = 6,
+} IMX_IOMUXC_KEY_ROW0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL1_ALT0_ECSPI1_MISO = 0,
+  IMX_IOMUXC_KEY_COL1_ALT1_ENET_MDIO = 1,
+  IMX_IOMUXC_KEY_COL1_ALT2_AUD5_TXFS = 2,
+  IMX_IOMUXC_KEY_COL1_ALT3_KEY_COL1 = 3,
+  IMX_IOMUXC_KEY_COL1_ALT4_UART5_TX_DATA = 4,
+  IMX_IOMUXC_KEY_COL1_ALT5_GPIO4_IO08 = 5,
+  IMX_IOMUXC_KEY_COL1_ALT6_SD1_VSELECT = 6,    // out
+} IMX_IOMUXC_KEY_COL1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW1_ALT0_ECSPI1_SS0 = 0,
+  IMX_IOMUXC_KEY_ROW1_ALT1_ENET_COL = 1,
+  IMX_IOMUXC_KEY_ROW1_ALT2_AUD5_RXD = 2,
+  IMX_IOMUXC_KEY_ROW1_ALT3_KEY_ROW1 = 3,
+  IMX_IOMUXC_KEY_ROW1_ALT4_UART5_RX_DATA = 4,
+  IMX_IOMUXC_KEY_ROW1_ALT5_GPIO4_IO09 = 5,
+  IMX_IOMUXC_KEY_ROW1_ALT6_SD2_VSELECT = 6,
+} IMX_IOMUXC_KEY_ROW1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL2_ALT0_ECSPI1_SS1 = 0,
+  IMX_IOMUXC_KEY_COL2_ALT1_ENET_RX_DATA2 = 1,
+  IMX_IOMUXC_KEY_COL2_ALT2_FLEXCAN1_TX = 2,
+  IMX_IOMUXC_KEY_COL2_ALT3_KEY_COL2 = 3,
+  IMX_IOMUXC_KEY_COL2_ALT4_ENET_MDC = 4,
+  IMX_IOMUXC_KEY_COL2_ALT5_GPIO4_IO10 = 5,
+  IMX_IOMUXC_KEY_COL2_ALT6_USB_H1_PWR_CTL_WAKE = 6,
+} IMX_IOMUXC_KEY_COL2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW2_ALT0_ECSPI1_SS2 = 0,
+  IMX_IOMUXC_KEY_ROW2_ALT1_ENET_TX_DATA2 = 1,
+  IMX_IOMUXC_KEY_ROW2_ALT2_FLEXCAN1_RX = 2,
+  IMX_IOMUXC_KEY_ROW2_ALT3_KEY_ROW2 = 3,
+  IMX_IOMUXC_KEY_ROW2_ALT4_SD2_VSELECT = 4,
+  IMX_IOMUXC_KEY_ROW2_ALT5_GPIO4_IO11 = 5,
+  IMX_IOMUXC_KEY_ROW2_ALT6_HDMI_TX_CEC_LINE = 6,
+} IMX_IOMUXC_KEY_ROW2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL3_ALT0_ECSPI1_SS3 = 0,
+  IMX_IOMUXC_KEY_COL3_ALT1_ENET_CRS = 1,
+  IMX_IOMUXC_KEY_COL3_ALT2_HDMI_TX_DDC_SCL = 2,
+  IMX_IOMUXC_KEY_COL3_ALT3_KEY_COL3 = 3,
+  IMX_IOMUXC_KEY_COL3_ALT4_I2C2_SCL = 4,
+  IMX_IOMUXC_KEY_COL3_ALT5_GPIO4_IO12 = 5,
+  IMX_IOMUXC_KEY_COL3_ALT6_SPDIF_IN = 6,
+} IMX_IOMUXC_KEY_COL3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW3_ALT0_XTALOSC_OSC32K_32K_OUT = 0,
+  IMX_IOMUXC_KEY_ROW3_ALT1_ASRC_EXT_CLK = 1,
+  IMX_IOMUXC_KEY_ROW3_ALT2_HDMI_TX_DDC_SDA = 2,
+  IMX_IOMUXC_KEY_ROW3_ALT3_KEY_ROW3 = 3,
+  IMX_IOMUXC_KEY_ROW3_ALT4_I2C2_SDA = 4,
+  IMX_IOMUXC_KEY_ROW3_ALT5_GPIO4_IO13 = 5,
+  IMX_IOMUXC_KEY_ROW3_ALT6_SD1_VSELECT = 6,
+} IMX_IOMUXC_KEY_ROW3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL4_ALT0_FLEXCAN2_TX = 0,
+  IMX_IOMUXC_KEY_COL4_ALT1_IPU1_SISG4 = 1,
+  IMX_IOMUXC_KEY_COL4_ALT2_USB_OTG_OC = 2,
+  IMX_IOMUXC_KEY_COL4_ALT3_KEY_COL4 = 3,
+  IMX_IOMUXC_KEY_COL4_ALT4_UART5_RTS_B = 4,
+  IMX_IOMUXC_KEY_COL4_ALT5_GPIO4_IO14 = 5,
+} IMX_IOMUXC_KEY_COL4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW4_ALT0_FLEXCAN2_RX = 0,
+  IMX_IOMUXC_KEY_ROW4_ALT1_IPU1_SISG5 = 1,
+  IMX_IOMUXC_KEY_ROW4_ALT2_USB_OTG_PWR = 2,
+  IMX_IOMUXC_KEY_ROW4_ALT3_KEY_ROW4 = 3,
+  IMX_IOMUXC_KEY_ROW4_ALT4_UART5_CTS_B = 4,
+  IMX_IOMUXC_KEY_ROW4_ALT5_GPIO4_IO15 = 5,
+} IMX_IOMUXC_KEY_ROW4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_DISP_CLK_ALT0_IPU1_DI0_DISP_CLK = 0,
+  IMX_IOMUXC_DI0_DISP_CLK_ALT5_GPIO4_IO16 = 5,
+} IMX_IOMUXC_DI0_DISP_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN15_ALT0_IPU1_DI0_PIN15 = 0,
+  IMX_IOMUXC_DI0_PIN15_ALT2_AUD6_TXC = 2,
+  IMX_IOMUXC_DI0_PIN15_ALT5_GPIO4_IO17 = 5,
+} IMX_IOMUXC_DI0_PIN15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN2_ALT0_IPU1_DI0_PIN02 = 0,
+  IMX_IOMUXC_DI0_PIN2_ALT2_AUD6_TXD = 2,
+  IMX_IOMUXC_DI0_PIN2_ALT5_GPIO4_IO18 = 5,
+} IMX_IOMUXC_DI0_PIN2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN3_ALT0_IPU1_DI0_PIN03 = 0,
+  IMX_IOMUXC_DI0_PIN3_ALT2_AUD6_TXFS = 2,
+  IMX_IOMUXC_DI0_PIN3_ALT5_GPIO4_IO19 = 5,
+} IMX_IOMUXC_DI0_PIN3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DI0_PIN4_ALT0_IPU1_DI0_PIN04 = 0,
+  IMX_IOMUXC_DI0_PIN4_ALT2_AUD6_RXD = 2,
+  IMX_IOMUXC_DI0_PIN4_ALT3_SD1_WP = 3,     // in
+  IMX_IOMUXC_DI0_PIN4_ALT5_GPIO4_IO20 = 5,
+} IMX_IOMUXC_DI0_PIN4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT0_ALT0_IPU1_DISP0_DATA00 = 0,
+  IMX_IOMUXC_DISP0_DAT0_ALT2_ECSPI3_SCLK = 2,
+  IMX_IOMUXC_DISP0_DAT0_ALT5_GPIO4_IO21 = 5,
+} IMX_IOMUXC_DISP0_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT1_ALT0_IPU1_DISP0_DATA01 = 0,
+  IMX_IOMUXC_DISP0_DAT1_ALT2_ECSPI3_MOSI = 2,
+  IMX_IOMUXC_DISP0_DAT1_ALT5_GPIO4_IO22 = 5,
+} IMX_IOMUXC_DISP0_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT2_ALT0_IPU1_DISP0_DATA02 = 0,
+  IMX_IOMUXC_DISP0_DAT2_ALT2_ECSPI3_MISO = 2,
+  IMX_IOMUXC_DISP0_DAT2_ALT5_GPIO4_IO23 = 5,
+} IMX_IOMUXC_DISP0_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT3_ALT0_IPU1_DISP0_DATA03 = 0,
+  IMX_IOMUXC_DISP0_DAT3_ALT2_ECSPI3_SS0 = 2,
+  IMX_IOMUXC_DISP0_DAT3_ALT5_GPIO4_IO24 = 5,
+} IMX_IOMUXC_DISP0_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT4_ALT0_IPU1_DISP0_DATA04 = 0,
+  IMX_IOMUXC_DISP0_DAT4_ALT2_ECSPI3_SS1 = 2,
+  IMX_IOMUXC_DISP0_DAT4_ALT5_GPIO4_IO25 = 5,
+} IMX_IOMUXC_DISP0_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT5_ALT0_IPU1_DISP0_DATA05 = 0,
+  IMX_IOMUXC_DISP0_DAT5_ALT2_ECSPI3_SS2 = 2,
+  IMX_IOMUXC_DISP0_DAT5_ALT3_AUD6_RXFS = 3,
+  IMX_IOMUXC_DISP0_DAT5_ALT5_GPIO4_IO26 = 5,
+} IMX_IOMUXC_DISP0_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT6_ALT0_IPU1_DISP0_DATA06 = 0,
+  IMX_IOMUXC_DISP0_DAT6_ALT2_ECSPI3_SS3 = 2,
+  IMX_IOMUXC_DISP0_DAT6_ALT3_AUD6_RXC = 3,
+  IMX_IOMUXC_DISP0_DAT6_ALT5_GPIO4_IO27 = 5,
+} IMX_IOMUXC_DISP0_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT7_ALT0_IPU1_DISP0_DATA07 = 0,
+  IMX_IOMUXC_DISP0_DAT7_ALT2_ECSPI3_RDY = 2,
+  IMX_IOMUXC_DISP0_DAT7_ALT5_GPIO4_IO28 = 5,
+} IMX_IOMUXC_DISP0_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT8_ALT0_IPU1_DISP0_DATA08 = 0,
+  IMX_IOMUXC_DISP0_DAT8_ALT2_PWM1_OUT = 2,
+  IMX_IOMUXC_DISP0_DAT8_ALT3_WDOG1_B = 3,
+  IMX_IOMUXC_DISP0_DAT8_ALT5_GPIO4_IO29 = 5,
+} IMX_IOMUXC_DISP0_DAT8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT9_ALT0_IPU1_DISP0_DATA09 = 0,
+  IMX_IOMUXC_DISP0_DAT9_ALT2_PWM2_OUT = 2,
+  IMX_IOMUXC_DISP0_DAT9_ALT3_WDOG2_B = 3,
+  IMX_IOMUXC_DISP0_DAT9_ALT5_GPIO4_IO30 = 5,
+} IMX_IOMUXC_DISP0_DAT9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT10_ALT0_IPU1_DISP0_DATA10 = 0,
+  IMX_IOMUXC_DISP0_DAT10_ALT5_GPIO4_IO31 = 5,
+} IMX_IOMUXC_DISP0_DAT10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_WAIT_ALT0_EIM_WAIT_B = 0,
+  IMX_IOMUXC_EIM_WAIT_ALT1_EIM_DTACK_B = 1,
+  IMX_IOMUXC_EIM_WAIT_ALT5_GPIO5_IO00 = 5,
+  IMX_IOMUXC_EIM_WAIT_ALT7_SRC_BOOT_CFG25 = 7,
+} IMX_IOMUXC_EIM_WAIT_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A25_ALT0_EIM_ADDR25 = 0,
+  IMX_IOMUXC_EIM_A25_ALT1_ECSPI4_SS1 = 1,
+  IMX_IOMUXC_EIM_A25_ALT2_ECSPI2_RDY = 2,
+  IMX_IOMUXC_EIM_A25_ALT3_IPU1_DI1_PIN12 = 3,
+  IMX_IOMUXC_EIM_A25_ALT4_IPU1_DI0_D1_CS = 4,
+  IMX_IOMUXC_EIM_A25_ALT5_GPIO5_IO02 = 5,
+  IMX_IOMUXC_EIM_A25_ALT6_HDMI_TX_CEC_LINE = 6,
+} IMX_IOMUXC_EIM_A25_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A24_ALT0_EIM_ADDR24 = 0,
+  IMX_IOMUXC_EIM_A24_ALT1_IPU1_DISP1_DATA19 = 1,
+  IMX_IOMUXC_EIM_A24_ALT2_IPU1_CSI1_DATA19 = 2,
+  IMX_IOMUXC_EIM_A24_ALT4_IPU1_SISG2 = 4,
+  IMX_IOMUXC_EIM_A24_ALT5_GPIO5_IO04 = 5,
+  IMX_IOMUXC_EIM_A24_ALT7_SRC_BOOT_CFG24 = 7,
+} IMX_IOMUXC_EIM_A24_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT11_ALT0_IPU1_DISP0_DATA11 = 0,
+  IMX_IOMUXC_DISP0_DAT11_ALT5_GPIO5_IO05 = 5,
+} IMX_IOMUXC_DISP0_DAT11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT12_ALT0_IPU1_DISP0_DATA12 = 0,
+  IMX_IOMUXC_DISP0_DAT12_ALT5_GPIO5_IO06 = 5,
+} IMX_IOMUXC_DISP0_DAT12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT13_ALT0_IPU1_DISP0_DATA13 = 0,
+  IMX_IOMUXC_DISP0_DAT13_ALT3_AUD5_RXFS = 3,
+  IMX_IOMUXC_DISP0_DAT13_ALT5_GPIO5_IO07 = 5,
+} IMX_IOMUXC_DISP0_DAT13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT14_ALT0_IPU1_DISP0_DATA14 = 0,
+  IMX_IOMUXC_DISP0_DAT14_ALT3_AUD5_RXC = 3,
+  IMX_IOMUXC_DISP0_DAT14_ALT5_GPIO5_IO08 = 5,
+} IMX_IOMUXC_DISP0_DAT14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT15_ALT0_IPU1_DISP0_DATA15 = 0,
+  IMX_IOMUXC_DISP0_DAT15_ALT2_ECSPI1_SS1 = 2,
+  IMX_IOMUXC_DISP0_DAT15_ALT3_ECSPI2_SS1 = 3,
+  IMX_IOMUXC_DISP0_DAT15_ALT5_GPIO5_IO09 = 5,
+} IMX_IOMUXC_DISP0_DAT15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT16_ALT0_IPU1_DISP0_DATA16 = 0,
+  IMX_IOMUXC_DISP0_DAT16_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_DISP0_DAT16_ALT3_AUD5_TXC = 3,
+  IMX_IOMUXC_DISP0_DAT16_ALT4_SDMA_EXT_EVENT0 = 4,
+  IMX_IOMUXC_DISP0_DAT16_ALT5_GPIO5_IO10 = 5,
+} IMX_IOMUXC_DISP0_DAT16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT17_ALT0_IPU1_DISP0_DATA17 = 0,
+  IMX_IOMUXC_DISP0_DAT17_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_DISP0_DAT17_ALT3_AUD5_TXD = 3,
+  IMX_IOMUXC_DISP0_DAT17_ALT4_SDMA_EXT_EVENT1 = 4,
+  IMX_IOMUXC_DISP0_DAT17_ALT5_GPIO5_IO11 = 5,
+} IMX_IOMUXC_DISP0_DAT17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT18_ALT0_IPU1_DISP0_DATA18 = 0,
+  IMX_IOMUXC_DISP0_DAT18_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_DISP0_DAT18_ALT3_AUD5_TXFS = 3,
+  IMX_IOMUXC_DISP0_DAT18_ALT4_AUD4_RXFS = 4,
+  IMX_IOMUXC_DISP0_DAT18_ALT5_GPIO5_IO12 = 5,
+  IMX_IOMUXC_DISP0_DAT18_ALT7_EIM_CS2_B = 7,
+} IMX_IOMUXC_DISP0_DAT18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT19_ALT0_IPU1_DISP0_DATA19 = 0,
+  IMX_IOMUXC_DISP0_DAT19_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_DISP0_DAT19_ALT3_AUD5_RXD = 3,
+  IMX_IOMUXC_DISP0_DAT19_ALT4_AUD4_RXC = 4,
+  IMX_IOMUXC_DISP0_DAT19_ALT5_GPIO5_IO13 = 5,
+  IMX_IOMUXC_DISP0_DAT19_ALT7_EIM_CS3_B = 7,
+} IMX_IOMUXC_DISP0_DAT19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT20_ALT0_IPU1_DISP0_DATA20 = 0,
+  IMX_IOMUXC_DISP0_DAT20_ALT2_ECSPI1_SCLK = 2,
+  IMX_IOMUXC_DISP0_DAT20_ALT3_AUD4_TXC = 3,
+  IMX_IOMUXC_DISP0_DAT20_ALT5_GPIO5_IO14 = 5,
+} IMX_IOMUXC_DISP0_DAT20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT21_ALT0_IPU1_DISP0_DATA21 = 0,
+  IMX_IOMUXC_DISP0_DAT21_ALT2_ECSPI1_MOSI = 2,
+  IMX_IOMUXC_DISP0_DAT21_ALT3_AUD4_TXD = 3,
+  IMX_IOMUXC_DISP0_DAT21_ALT5_GPIO5_IO15 = 5,
+} IMX_IOMUXC_DISP0_DAT21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT22_ALT0_IPU1_DISP0_DATA22 = 0,
+  IMX_IOMUXC_DISP0_DAT22_ALT2_ECSPI1_MISO = 2,
+  IMX_IOMUXC_DISP0_DAT22_ALT3_AUD4_TXFS = 3,
+  IMX_IOMUXC_DISP0_DAT22_ALT5_GPIO5_IO16 = 5,
+} IMX_IOMUXC_DISP0_DAT22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_DISP0_DAT23_ALT0_IPU1_DISP0_DATA23 = 0,
+  IMX_IOMUXC_DISP0_DAT23_ALT2_ECSPI1_SS0 = 2,
+  IMX_IOMUXC_DISP0_DAT23_ALT3_AUD4_RXD = 3,
+  IMX_IOMUXC_DISP0_DAT23_ALT5_GPIO5_IO17 = 5,
+} IMX_IOMUXC_DISP0_DAT23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_PIXCLK_ALT0_IPU1_CSI0_PIXCLK = 0,
+  IMX_IOMUXC_CSI0_PIXCLK_ALT5_GPIO5_IO18 = 5,
+  IMX_IOMUXC_CSI0_PIXCLK_ALT7_ARM_EVENTO = 7,
+} IMX_IOMUXC_CSI0_PIXCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_MCLK_ALT0_IPU1_CSI0_HSYNC = 0,
+  IMX_IOMUXC_CSI0_MCLK_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_CSI0_MCLK_ALT5_GPIO5_IO19 = 5,
+  IMX_IOMUXC_CSI0_MCLK_ALT7_ARM_TRACE_CTL = 7,
+} IMX_IOMUXC_CSI0_MCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DATA_EN_ALT0_IPU1_CSI0_DATA_EN = 0,
+  IMX_IOMUXC_CSI0_DATA_EN_ALT1_EIM_DATA00 = 1,
+  IMX_IOMUXC_CSI0_DATA_EN_ALT5_GPIO5_IO20 = 5,
+  IMX_IOMUXC_CSI0_DATA_EN_ALT7_ARM_TRACE_CLK = 7,
+} IMX_IOMUXC_CSI0_DATA_EN_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_VSYNC_ALT0_IPU1_CSI0_VSYNC = 0,
+  IMX_IOMUXC_CSI0_VSYNC_ALT1_EIM_DATA01 = 1,
+  IMX_IOMUXC_CSI0_VSYNC_ALT5_GPIO5_IO21 = 5,
+  IMX_IOMUXC_CSI0_VSYNC_ALT7_ARM_TRACE00 = 7,
+} IMX_IOMUXC_CSI0_VSYNC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT4_ALT0_IPU1_CSI0_DATA04 = 0,
+  IMX_IOMUXC_CSI0_DAT4_ALT1_EIM_DATA02 = 1,
+  IMX_IOMUXC_CSI0_DAT4_ALT2_ECSPI1_SCLK = 2,
+  IMX_IOMUXC_CSI0_DAT4_ALT3_KEY_COL5 = 3,
+  IMX_IOMUXC_CSI0_DAT4_ALT4_AUD3_TXC = 4,
+  IMX_IOMUXC_CSI0_DAT4_ALT5_GPIO5_IO22 = 5,
+  IMX_IOMUXC_CSI0_DAT4_ALT7_ARM_TRACE01 = 7,
+} IMX_IOMUXC_CSI0_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT5_ALT0_IPU1_CSI0_DATA05 = 0,
+  IMX_IOMUXC_CSI0_DAT5_ALT1_EIM_DATA03 = 1,
+  IMX_IOMUXC_CSI0_DAT5_ALT2_ECSPI1_MOSI = 2,
+  IMX_IOMUXC_CSI0_DAT5_ALT3_KEY_ROW5 = 3,
+  IMX_IOMUXC_CSI0_DAT5_ALT4_AUD3_TXD = 4,
+  IMX_IOMUXC_CSI0_DAT5_ALT5_GPIO5_IO23 = 5,
+  IMX_IOMUXC_CSI0_DAT5_ALT7_ARM_TRACE02 = 7,
+} IMX_IOMUXC_CSI0_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT6_ALT0_IPU1_CSI0_DATA06 = 0,
+  IMX_IOMUXC_CSI0_DAT6_ALT1_EIM_DATA04 = 1,
+  IMX_IOMUXC_CSI0_DAT6_ALT2_ECSPI1_MISO = 2,
+  IMX_IOMUXC_CSI0_DAT6_ALT3_KEY_COL6 = 3,
+  IMX_IOMUXC_CSI0_DAT6_ALT4_AUD3_TXFS = 4,
+  IMX_IOMUXC_CSI0_DAT6_ALT5_GPIO5_IO24 = 5,
+  IMX_IOMUXC_CSI0_DAT6_ALT7_ARM_TRACE03 = 7,
+} IMX_IOMUXC_CSI0_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT7_ALT0_IPU1_CSI0_DATA07 = 0,
+  IMX_IOMUXC_CSI0_DAT7_ALT1_EIM_DATA05 = 1,
+  IMX_IOMUXC_CSI0_DAT7_ALT2_ECSPI1_SS0 = 2,
+  IMX_IOMUXC_CSI0_DAT7_ALT3_KEY_ROW6 = 3,
+  IMX_IOMUXC_CSI0_DAT7_ALT4_AUD3_RXD = 4,
+  IMX_IOMUXC_CSI0_DAT7_ALT5_GPIO5_IO25 = 5,
+  IMX_IOMUXC_CSI0_DAT7_ALT7_ARM_TRACE04 = 7,
+} IMX_IOMUXC_CSI0_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT8_ALT0_IPU1_CSI0_DATA08 = 0,
+  IMX_IOMUXC_CSI0_DAT8_ALT1_EIM_DATA06 = 1,
+  IMX_IOMUXC_CSI0_DAT8_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_CSI0_DAT8_ALT3_KEY_COL7 = 3,
+  IMX_IOMUXC_CSI0_DAT8_ALT4_I2C1_SDA = 4,
+  IMX_IOMUXC_CSI0_DAT8_ALT5_GPIO5_IO26 = 5,
+  IMX_IOMUXC_CSI0_DAT8_ALT7_ARM_TRACE05 = 7,
+} IMX_IOMUXC_CSI0_DAT8_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT9_ALT0_IPU1_CSI0_DATA09 = 0,
+  IMX_IOMUXC_CSI0_DAT9_ALT1_EIM_DATA07 = 1,
+  IMX_IOMUXC_CSI0_DAT9_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_CSI0_DAT9_ALT3_KEY_ROW7 = 3,
+  IMX_IOMUXC_CSI0_DAT9_ALT4_I2C1_SCL = 4,
+  IMX_IOMUXC_CSI0_DAT9_ALT5_GPIO5_IO27 = 5,
+  IMX_IOMUXC_CSI0_DAT9_ALT7_ARM_TRACE06 = 7,
+} IMX_IOMUXC_CSI0_DAT9_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT10_ALT0_IPU1_CSI0_DATA10 = 0,
+  IMX_IOMUXC_CSI0_DAT10_ALT1_AUD3_RXC = 1,
+  IMX_IOMUXC_CSI0_DAT10_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_CSI0_DAT10_ALT3_UART1_TX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT10_ALT5_GPIO5_IO28 = 5,
+  IMX_IOMUXC_CSI0_DAT10_ALT7_ARM_TRACE07 = 7,
+} IMX_IOMUXC_CSI0_DAT10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT11_ALT0_IPU1_CSI0_DATA11 = 0,
+  IMX_IOMUXC_CSI0_DAT11_ALT1_AUD3_RXFS = 1,
+  IMX_IOMUXC_CSI0_DAT11_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_CSI0_DAT11_ALT3_UART1_RX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT11_ALT5_GPIO5_IO29 = 5,
+  IMX_IOMUXC_CSI0_DAT11_ALT7_ARM_TRACE08 = 7,
+} IMX_IOMUXC_CSI0_DAT11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT12_ALT0_IPU1_CSI0_DATA12 = 0,
+  IMX_IOMUXC_CSI0_DAT12_ALT1_EIM_DATA08 = 1,
+  IMX_IOMUXC_CSI0_DAT12_ALT3_UART4_TX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT12_ALT5_GPIO5_IO30 = 5,
+  IMX_IOMUXC_CSI0_DAT12_ALT7_ARM_TRACE09 = 7,
+} IMX_IOMUXC_CSI0_DAT12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT13_ALT0_IPU1_CSI0_DATA13 = 0,
+  IMX_IOMUXC_CSI0_DAT13_ALT1_EIM_DATA09 = 1,
+  IMX_IOMUXC_CSI0_DAT13_ALT3_UART4_RX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT13_ALT5_GPIO5_IO31 = 5,
+  IMX_IOMUXC_CSI0_DAT13_ALT7_ARM_TRACE10 = 7,
+} IMX_IOMUXC_CSI0_DAT13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT14_ALT0_IPU1_CSI0_DATA14 = 0,
+  IMX_IOMUXC_CSI0_DAT14_ALT1_EIM_DATA10 = 1,
+  IMX_IOMUXC_CSI0_DAT14_ALT3_UART5_TX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT14_ALT5_GPIO6_IO00 = 5,
+  IMX_IOMUXC_CSI0_DAT14_ALT7_ARM_TRACE11 = 7,
+} IMX_IOMUXC_CSI0_DAT14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT15_ALT0_IPU1_CSI0_DATA15 = 0,
+  IMX_IOMUXC_CSI0_DAT15_ALT1_EIM_DATA11 = 1,
+  IMX_IOMUXC_CSI0_DAT15_ALT3_UART5_RX_DATA = 3,
+  IMX_IOMUXC_CSI0_DAT15_ALT5_GPIO6_IO01 = 5,
+  IMX_IOMUXC_CSI0_DAT15_ALT7_ARM_TRACE12 = 7,
+} IMX_IOMUXC_CSI0_DAT15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT16_ALT0_IPU1_CSI0_DATA16 = 0,
+  IMX_IOMUXC_CSI0_DAT16_ALT1_EIM_DATA12 = 1,
+  IMX_IOMUXC_CSI0_DAT16_ALT3_UART4_RTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT16_ALT5_GPIO6_IO02 = 5,
+  IMX_IOMUXC_CSI0_DAT16_ALT7_ARM_TRACE13 = 7,
+} IMX_IOMUXC_CSI0_DAT16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT17_ALT0_IPU1_CSI0_DATA17 = 0,
+  IMX_IOMUXC_CSI0_DAT17_ALT1_EIM_DATA13 = 1,
+  IMX_IOMUXC_CSI0_DAT17_ALT3_UART4_CTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT17_ALT5_GPIO6_IO03 = 5,
+  IMX_IOMUXC_CSI0_DAT17_ALT7_ARM_TRACE14 = 7,
+} IMX_IOMUXC_CSI0_DAT17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT18_ALT0_IPU1_CSI0_DATA18 = 0,
+  IMX_IOMUXC_CSI0_DAT18_ALT1_EIM_DATA14 = 1,
+  IMX_IOMUXC_CSI0_DAT18_ALT3_UART5_RTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT18_ALT5_GPIO6_IO04 = 5,
+  IMX_IOMUXC_CSI0_DAT18_ALT7_ARM_TRACE15 = 7,
+} IMX_IOMUXC_CSI0_DAT18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI0_DAT19_ALT0_IPU1_CSI0_DATA19 = 0,
+  IMX_IOMUXC_CSI0_DAT19_ALT1_EIM_DATA15 = 1,
+  IMX_IOMUXC_CSI0_DAT19_ALT3_UART5_CTS_B = 3,
+  IMX_IOMUXC_CSI0_DAT19_ALT5_GPIO6_IO05 = 5,
+} IMX_IOMUXC_CSI0_DAT19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_A23_ALT0_EIM_ADDR23 = 0,
+  IMX_IOMUXC_EIM_A23_ALT1_IPU1_DISP1_DATA18 = 1,
+  IMX_IOMUXC_EIM_A23_ALT2_IPU1_CSI1_DATA18 = 2,
+  IMX_IOMUXC_EIM_A23_ALT4_IPU1_SISG3 = 4,
+  IMX_IOMUXC_EIM_A23_ALT5_GPIO6_IO06 = 5,
+  IMX_IOMUXC_EIM_A23_ALT7_SRC_BOOT_CFG23 = 7,
+  IMX_IOMUXC_EIM_A23_ALT8_EPDC_GDOE = 8
+} IMX_IOMUXC_EIM_A23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CLE_ALT0_NAND_CLE = 0,
+  IMX_IOMUXC_NANDF_CLE_ALT5_GPIO6_IO07 = 5,
+} IMX_IOMUXC_NANDF_CLE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_ALE_ALT0_NAND_ALE = 0,
+  IMX_IOMUXC_NANDF_ALE_ALT1_SD4_RESET = 1,
+  IMX_IOMUXC_NANDF_ALE_ALT5_GPIO6_IO08 = 5,
+} IMX_IOMUXC_NANDF_ALE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_WP_B_ALT0_NAND_WP_B = 0,
+  IMX_IOMUXC_NANDF_WP_B_ALT5_GPIO6_IO09 = 5,
+  IMX_IOMUXC_NANDF_WP_B_ALT9_I2C4_SCL = 9
+} IMX_IOMUXC_NANDF_WP_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_RB0_ALT0_NAND_READY_B = 0,
+  IMX_IOMUXC_NANDF_RB0_ALT5_GPIO6_IO10 = 5,
+} IMX_IOMUXC_NANDF_RB0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS0_ALT0_NAND_CE0_B = 0,
+  IMX_IOMUXC_NANDF_CS0_ALT5_GPIO6_IO11 = 5,
+} IMX_IOMUXC_NANDF_CS0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS1_ALT0_NAND_CE1_B = 0,
+  IMX_IOMUXC_NANDF_CS1_ALT1_SD4_VSELECT = 1,
+  IMX_IOMUXC_NANDF_CS1_ALT2_SD3_VSELECT = 2,
+  IMX_IOMUXC_NANDF_CS1_ALT5_GPIO6_IO14 = 5,
+} IMX_IOMUXC_NANDF_CS1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS2_ALT0_NAND_CE2_B = 0,
+  IMX_IOMUXC_NANDF_CS2_ALT1_IPU1_SISG0 = 1,
+  IMX_IOMUXC_NANDF_CS2_ALT2_ESAI_TX0 = 2,
+  IMX_IOMUXC_NANDF_CS2_ALT3_EIM_CRE = 3,
+  IMX_IOMUXC_NANDF_CS2_ALT4_CCM_CLKO2 = 4,
+  IMX_IOMUXC_NANDF_CS2_ALT5_GPIO6_IO15 = 5
+} IMX_IOMUXC_NANDF_CS2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NANDF_CS3_ALT0_NAND_CE3_B = 0,
+  IMX_IOMUXC_NANDF_CS3_ALT1_IPU1_SISG1 = 1,
+  IMX_IOMUXC_NANDF_CS3_ALT2_ESAI_TX1 = 2,
+  IMX_IOMUXC_NANDF_CS3_ALT3_EIM_ADDR26 = 3,
+  IMX_IOMUXC_NANDF_CS3_ALT5_GPIO6_IO16 = 5,
+  IMX_IOMUXC_NANDF_CS3_ALT6_I2C4_SDA = 9,
+} IMX_IOMUXC_NANDF_CS3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT7_ALT0_SD3_DATA7 = 0,
+  IMX_IOMUXC_SD3_DAT7_ALT1_UART1_TX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT7_ALT5_GPIO6_IO17 = 5,
+} IMX_IOMUXC_SD3_DAT7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT6_ALT0_SD3_DATA6 = 0,
+  IMX_IOMUXC_SD3_DAT6_ALT1_UART1_RX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT6_ALT5_GPIO6_IO18 = 5,
+} IMX_IOMUXC_SD3_DAT6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TXC_ALT0_USB_H2_DATA = 0,
+  IMX_IOMUXC_RGMII_TXC_ALT1_RGMII_TXC = 1,
+  IMX_IOMUXC_RGMII_TXC_ALT2_SPDIF_EXT_CLK = 2,
+  IMX_IOMUXC_RGMII_TXC_ALT5_GPIO6_IO19 = 5,
+  IMX_IOMUXC_RGMII_TXC_ALT7_XTALOSC_REF_CLK_24M = 7,
+} IMX_IOMUXC_RGMII_TXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD0_ALT0_HSI_TX_READY = 0,
+  IMX_IOMUXC_RGMII_TD0_ALT1_RGMII_TD0 = 1,
+  IMX_IOMUXC_RGMII_TD0_ALT5_GPIO6_IO20 = 5,
+} IMX_IOMUXC_RGMII_TD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD1_ALT0_HSI_RX_FLAG = 0,
+  IMX_IOMUXC_RGMII_TD1_ALT1_RGMII_TD1 = 1,
+  IMX_IOMUXC_RGMII_TD1_ALT5_GPIO6_IO21 = 5,
+} IMX_IOMUXC_RGMII_TD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD2_ALT0_HSI_RX_DATA = 0,
+  IMX_IOMUXC_RGMII_TD2_ALT1_RGMII_TD2 = 1,
+  IMX_IOMUXC_RGMII_TD2_ALT5_GPIO6_IO22 = 5,
+} IMX_IOMUXC_RGMII_TD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TD3_ALT0_HSI_RX_WAKE = 0,
+  IMX_IOMUXC_RGMII_TD3_ALT1_RGMII_TD3 = 1,
+  IMX_IOMUXC_RGMII_TD3_ALT5_GPIO6_IO23 = 5,
+} IMX_IOMUXC_RGMII_TD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RX_CTL_ALT0_USB_H3_DATA = 0,
+  IMX_IOMUXC_RGMII_RX_CTL_ALT1_RGMII_RX_CTL = 1,
+  IMX_IOMUXC_RGMII_RX_CTL_ALT5_GPIO6_IO24 = 5,
+} IMX_IOMUXC_RGMII_RX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD0_ALT0_HSI_RX_READY = 0,
+  IMX_IOMUXC_RGMII_RD0_ALT1_RGMII_RD0 = 1,
+  IMX_IOMUXC_RGMII_RD0_ALT5_GPIO6_IO25 = 5,
+} IMX_IOMUXC_RGMII_RD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_TX_CTL_ALT0_USB_H2_STROBE = 0,
+  IMX_IOMUXC_RGMII_TX_CTL_ALT1_RGMII_TX_CTL = 1,
+  IMX_IOMUXC_RGMII_TX_CTL_ALT5_GPIO6_IO26 = 5,
+  IMX_IOMUXC_RGMII_TX_CTL_ALT7_ENET_REF_CLK = 7,
+} IMX_IOMUXC_RGMII_TX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD1_ALT0_HSI_TX_FLAG = 0,
+  IMX_IOMUXC_RGMII_RD1_ALT1_RGMII_RD1 = 1,
+  IMX_IOMUXC_RGMII_RD1_ALT5_GPIO6_IO27 = 5,
+} IMX_IOMUXC_RGMII_RD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD2_ALT0_HSI_TX_DATA = 0,
+  IMX_IOMUXC_RGMII_RD2_ALT1_RGMII_RD2 = 1,
+  IMX_IOMUXC_RGMII_RD2_ALT5_GPIO6_IO28 = 5,
+} IMX_IOMUXC_RGMII_RD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RD3_ALT0_HSI_TX_WAKE = 0,
+  IMX_IOMUXC_RGMII_RD3_ALT1_RGMII_RD3 = 1,
+  IMX_IOMUXC_RGMII_RD3_ALT5_GPIO6_IO29 = 5,
+} IMX_IOMUXC_RGMII_RD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII_RXC_ALT0_USB_H3_STROBE = 0,
+  IMX_IOMUXC_RGMII_RXC_ALT1_RGMII_RXC = 1,
+  IMX_IOMUXC_RGMII_RXC_ALT5_GPIO6_IO30 = 5,
+} IMX_IOMUXC_RGMII_RXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_EIM_BCLK_ALT0_EIM_BCLK = 0,
+  IMX_IOMUXC_EIM_BCLK_ALT1_IPU1_DI1_PIN16 = 1,
+  IMX_IOMUXC_EIM_BCLK_ALT5_GPIO6_IO31 = 5,
+} IMX_IOMUXC_EIM_BCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT5_ALT0_SD3_DATA5 = 0,
+  IMX_IOMUXC_SD3_DAT5_ALT1_UART2_TX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT5_ALT5_GPIO7_IO00 = 5,
+} IMX_IOMUXC_SD3_DAT5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT4_ALT0_SD3_DATA4 = 0,
+  IMX_IOMUXC_SD3_DAT4_ALT1_UART2_RX_DATA = 1,
+  IMX_IOMUXC_SD3_DAT4_ALT5_GPIO7_IO01 = 5,
+} IMX_IOMUXC_SD3_DAT4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_CMD_ALT0_SD3_CMD = 0,
+  IMX_IOMUXC_SD3_CMD_ALT1_UART2_CTS_B = 1,
+  IMX_IOMUXC_SD3_CMD_ALT2_FLEXCAN1_TX = 2,
+  IMX_IOMUXC_SD3_CMD_ALT5_GPIO7_IO02 = 5,
+} IMX_IOMUXC_SD3_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_CLK_ALT0_SD3_CLK = 0,
+  IMX_IOMUXC_SD3_CLK_ALT1_UART2_RTS_B = 1,
+  IMX_IOMUXC_SD3_CLK_ALT2_FLEXCAN1_RX = 2,
+  IMX_IOMUXC_SD3_CLK_ALT5_GPIO7_IO03 = 5,
+} IMX_IOMUXC_SD3_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT0_ALT0_SD3_DATA0 = 0,
+  IMX_IOMUXC_SD3_DAT0_ALT1_UART1_CTS_B = 1,
+  IMX_IOMUXC_SD3_DAT0_ALT2_FLEXCAN2_TX = 2,
+  IMX_IOMUXC_SD3_DAT0_ALT5_GPIO7_IO04 = 5,
+} IMX_IOMUXC_SD3_DAT0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT1_ALT0_SD3_DATA1 = 0,
+  IMX_IOMUXC_SD3_DAT1_ALT1_UART1_RTS_B = 1,
+  IMX_IOMUXC_SD3_DAT1_ALT2_FLEXCAN2_RX = 2,
+  IMX_IOMUXC_SD3_DAT1_ALT5_GPIO7_IO05 = 5,
+} IMX_IOMUXC_SD3_DAT1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT2_ALT0_SD3_DATA2 = 0,
+  IMX_IOMUXC_SD3_DAT2_ALT5_GPIO7_IO06 = 5,
+} IMX_IOMUXC_SD3_DAT2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DAT3_ALT0_SD3_DATA3 = 0,
+  IMX_IOMUXC_SD3_DAT3_ALT1_UART3_CTS_B = 1,
+  IMX_IOMUXC_SD3_DAT3_ALT5_GPIO7_IO07 = 5,
+} IMX_IOMUXC_SD3_DAT3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_RST_ALT0_SD3_RESET = 0,
+  IMX_IOMUXC_SD3_RST_ALT1_UART3_RTS_B = 1,
+  IMX_IOMUXC_SD3_RST_ALT5_GPIO7_IO08 = 5,
+} IMX_IOMUXC_SD3_RST_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_CMD_ALT0_SD4_CMD = 0,
+  IMX_IOMUXC_SD4_CMD_ALT1_NAND_RE_B = 1,
+  IMX_IOMUXC_SD4_CMD_ALT2_UART3_TX_DATA = 2,
+  IMX_IOMUXC_SD4_CMD_ALT5_GPIO7_IO09 = 5,
+} IMX_IOMUXC_SD4_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_CLK_ALT0_SD4_CLK = 0,
+  IMX_IOMUXC_SD4_CLK_ALT1_NAND_WE_B = 1,
+  IMX_IOMUXC_SD4_CLK_ALT2_UART3_RX_DATA = 2,
+  IMX_IOMUXC_SD4_CLK_ALT5_GPIO7_IO10 = 5,
+} IMX_IOMUXC_SD4_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_16_ALT0_ESAI_TX3_RX2 = 0,
+  IMX_IOMUXC_GPIO_16_ALT1_ENET_1588_EVENT2_IN = 1,
+  IMX_IOMUXC_GPIO_16_ALT2_ENET_REF_CLK = 2,
+  IMX_IOMUXC_GPIO_16_ALT3_SD1_LCTL = 3,    // out LED
+  IMX_IOMUXC_GPIO_16_ALT4_SPDIF_IN = 4,
+  IMX_IOMUXC_GPIO_16_ALT5_GPIO7_IO11 = 5,
+  IMX_IOMUXC_GPIO_16_ALT6_I2C3_SDA = 6,
+  IMX_IOMUXC_GPIO_16_ALT7_JTAG_DE_B = 7,
+} IMX_IOMUXC_GPIO_16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_17_ALT0_ESAI_TX0 = 0,
+  IMX_IOMUXC_GPIO_17_ALT1_ENET_1588_EVENT3_IN = 1,
+  IMX_IOMUXC_GPIO_17_ALT2_CCM_PMIC_READY = 2,
+  IMX_IOMUXC_GPIO_17_ALT3_SDMA_EXT_EVENT0 = 3,
+  IMX_IOMUXC_GPIO_17_ALT4_SPDIF_OUT = 4,
+  IMX_IOMUXC_GPIO_17_ALT5_GPIO7_IO12 = 5,
+} IMX_IOMUXC_GPIO_17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO_18_ALT0_ESAI_TX1 = 0,
+  IMX_IOMUXC_GPIO_18_ALT1_ENET_RX_CLK = 1,
+  IMX_IOMUXC_GPIO_18_ALT2_SD3_VSELECT = 2,
+  IMX_IOMUXC_GPIO_18_ALT3_SDMA_EXT_EVENT1 = 3,
+  IMX_IOMUXC_GPIO_18_ALT4_ASRC_EXT_CLK = 4,
+  IMX_IOMUXC_GPIO_18_ALT5_GPIO7_IO13 = 5,
+  IMX_IOMUXC_GPIO_18_ALT6_SNVS_VIO_5_CTL = 6,
+} IMX_IOMUXC_GPIO_18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ECSPI1_MISO_EIM_DATA17_ALT1 = 0,
+  IMX_IOMUXC_ECSPI1_MISO_DISP0_DATA22_ALT2 = 1,
+  IMX_IOMUXC_ECSPI1_MISO_KEY_COL1_ALT0 = 2,
+  IMX_IOMUXC_ECSPI1_MISO_CSI0_DATA06_ALT2 = 3,
+} IMX_IOMUXC_ECSPI1_MISO_SELECT_INPUT;
+
+typedef enum {
+  IMX_IOMUXC_ECSPI2_MISO_EIM_OE_B_ALT2 = 0,
+  IMX_IOMUXC_ECSPI2_MISO_DISP0_DATA17_ALT2 = 1,
+  IMX_IOMUXC_ECSPI2_MISO_CSI0_DATA10_ALT2 = 2,
+} IMX_IOMUXC_ECSPI2_MISO_SELECT_INPUT;
+
+#endif // _IMX6_IOMUX_SDL_H_
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h
new file mode 100644
index 000000000000..d4df92bf4c24
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h
@@ -0,0 +1,2270 @@
+/** @file
+*
+*  Header defining IMX6 SoloX Muxing definitions
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+#ifndef _IMX6_IOMUX_SX_H_
+#define _IMX6_IOMUX_SX_H_
+
+// SELECT INPUT defines
+// IMX_PAD register defines.
+typedef enum {
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00)
+  IMX_PAD_GPIO1_IO00 = _IMX_PAD(0x35C, 0x14), // I2C1_SCL
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO01)
+  IMX_PAD_GPIO1_IO01 = _IMX_PAD(0x360, 0x18), // I2C1_SDA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO02)
+  IMX_PAD_GPIO1_IO02 = _IMX_PAD(0x364, 0x1C), // I2C2_SCL
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03)
+  IMX_PAD_GPIO1_IO03 = _IMX_PAD(0x368, 0x20), // I2C2_SDA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04)
+  IMX_PAD_GPIO1_IO04 = _IMX_PAD(0x36C, 0x24), // UART1_TX_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO05)
+  IMX_PAD_GPIO1_IO05 = _IMX_PAD(0x370, 0x28), // UART1_RX_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06)
+  IMX_PAD_GPIO1_IO06 = _IMX_PAD(0x374, 0x2C), // UART2_TX_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO07)
+  IMX_PAD_GPIO1_IO07 = _IMX_PAD(0x378, 0x30), // UART2_RX_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO08)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO08)
+  IMX_PAD_GPIO1_IO08 = _IMX_PAD(0x37C, 0x34), // USB_OTG1_OC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO09)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09)
+  IMX_PAD_GPIO1_IO09 = _IMX_PAD(0x380, 0x38), // USB_OTG1_PWR
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO10)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO10)
+  IMX_PAD_GPIO1_IO10 = _IMX_PAD(0x384, 0x3C), // USB_OTG1_ID
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO11)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO11)
+  IMX_PAD_GPIO1_IO11 = _IMX_PAD(0x388, 0x40), // USB_OTG2_OC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO12)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO12)
+  IMX_PAD_GPIO1_IO12 = _IMX_PAD(0x38C, 0x44), // USB_OTG2_PWR
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO13)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO13)
+  IMX_PAD_GPIO1_IO13 = _IMX_PAD(0x390, 0x48), // WDOG1_ANY
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA00)
+  IMX_PAD_CSI_DATA00 = _IMX_PAD(0x394, 0x4C), // CSI1_DATA02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA01)
+  IMX_PAD_CSI_DATA01 = _IMX_PAD(0x398, 0x50), // CSI1_DATA03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA02)
+  IMX_PAD_CSI_DATA02 = _IMX_PAD(0x39C, 0x54), // CSI1_DATA04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA03)
+  IMX_PAD_CSI_DATA03 = _IMX_PAD(0x3A0, 0x58), // CSI1_DATA05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA04)
+  IMX_PAD_CSI_DATA04 = _IMX_PAD(0x3A4, 0x5C), // CSI1_DATA06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA05)
+  IMX_PAD_CSI_DATA05 = _IMX_PAD(0x3A8, 0x60), // CSI1_DATA07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA06)
+  IMX_PAD_CSI_DATA06 = _IMX_PAD(0x3AC, 0x64), // CSI1_DATA08
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_DATA07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_DATA07)
+  IMX_PAD_CSI_DATA07 = _IMX_PAD(0x3B0, 0x68), // CSI1_DATA09
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_HSYNC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_HSYNC)
+  IMX_PAD_CSI_HSYNC = _IMX_PAD(0x3B4, 0x6C), // CSI1_HSYNC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_MCLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_MCLK)
+  IMX_PAD_CSI_MCLK = _IMX_PAD(0x3B8, 0x70), // CSI1_MCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_PIXCLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_PIXCLK)
+  IMX_PAD_CSI_PIXCLK = _IMX_PAD(0x3BC, 0x74), // CSI1_PIXCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_CSI_VSYNC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_CSI_VSYNC)
+  IMX_PAD_CSI_VSYNC = _IMX_PAD(0x3C0, 0x78), // CSI1_VSYNC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET1_COL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET1_COL)
+  IMX_PAD_ENET1_COL = _IMX_PAD(0x3C4, 0x7C), // ENET1_COL
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET1_CRS)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET1_CRS)
+  IMX_PAD_ENET1_CRS = _IMX_PAD(0x3C8, 0x80), // ENET1_CRS
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET1_MDC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET1_MDC)
+  IMX_PAD_ENET1_MDC = _IMX_PAD(0x3CC, 0x84), // ENET1_MDC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET1_MDIO)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET1_MDIO)
+  IMX_PAD_ENET1_MDIO = _IMX_PAD(0x3D0, 0x88), // ENET1_MDIO
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_CLK)
+  IMX_PAD_ENET1_RX_CLK = _IMX_PAD(0x3D4, 0x8C), // ENET1_RX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK)
+  IMX_PAD_ENET1_TX_CLK = _IMX_PAD(0x3D8, 0x90), // ENET1_TX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET2_COL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET2_COL)
+  IMX_PAD_ENET2_COL = _IMX_PAD(0x3DC, 0x94), // ENET2_COL
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET2_CRS)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET2_CRS)
+  IMX_PAD_ENET2_CRS = _IMX_PAD(0x3E0, 0x98), // ENET2_CRS
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_CLK)
+  IMX_PAD_ENET2_RX_CLK = _IMX_PAD(0x3E4, 0x9C), // ENET2_RX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_CLK)
+  IMX_PAD_ENET2_TX_CLK = _IMX_PAD(0x3E8, 0xA0), // ENET2_TX_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL0)
+  IMX_PAD_KEY_COL0 = _IMX_PAD(0x3EC, 0xA4), // KPP_COL0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL1)
+  IMX_PAD_KEY_COL1 = _IMX_PAD(0x3F0, 0xA8), // KPP_COL1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL2)
+  IMX_PAD_KEY_COL2 = _IMX_PAD(0x3F4, 0xAC), // KPP_COL2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL3)
+  IMX_PAD_KEY_COL3 = _IMX_PAD(0x3F8, 0xB0), // KPP_COL3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_COL4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_COL4)
+  IMX_PAD_KEY_COL4 = _IMX_PAD(0x3FC, 0xB4), // KPP_COL4
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0)
+  IMX_PAD_KEY_ROW0 = _IMX_PAD(0x400, 0xB8), // KPP_ROW0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1)
+  IMX_PAD_KEY_ROW1 = _IMX_PAD(0x404, 0xBC), // KPP_ROW1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2)
+  IMX_PAD_KEY_ROW2 = _IMX_PAD(0x408, 0xC0), // KPP_ROW2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3)
+  IMX_PAD_KEY_ROW3 = _IMX_PAD(0x40C, 0xC4), // KPP_ROW3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_KEY_ROW4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4)
+  IMX_PAD_KEY_ROW4 = _IMX_PAD(0x410, 0xC8), // KPP_ROW4
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_CLK)
+  IMX_PAD_LCD1_CLK = _IMX_PAD(0x414, 0xCC), // LCD1_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA00)
+  IMX_PAD_LCD1_DATA00 = _IMX_PAD(0x418, 0xD0), // LCD1_DATA00
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA01)
+  IMX_PAD_LCD1_DATA01 = _IMX_PAD(0x41C, 0xD4), // LCD1_DATA01
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA02)
+  IMX_PAD_LCD1_DATA02 = _IMX_PAD(0x420, 0xD8), // LCD1_DATA02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA03)
+  IMX_PAD_LCD1_DATA03 = _IMX_PAD(0x424, 0xDC), // LCD1_DATA03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA04)
+  IMX_PAD_LCD1_DATA04 = _IMX_PAD(0x428, 0xE0), // LCD1_DATA04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA05)
+  IMX_PAD_LCD1_DATA05 = _IMX_PAD(0x42C, 0xE4), // LCD1_DATA05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA06)
+  IMX_PAD_LCD1_DATA06 = _IMX_PAD(0x430, 0xE8), // LCD1_DATA06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA07)
+  IMX_PAD_LCD1_DATA07 = _IMX_PAD(0x434, 0xEC), // LCD1_DATA07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA08)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA08)
+  IMX_PAD_LCD1_DATA08 = _IMX_PAD(0x438, 0xF0), // LCD1_DATA08
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA09)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA09)
+  IMX_PAD_LCD1_DATA09 = _IMX_PAD(0x43C, 0xF4), // LCD1_DATA09
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA10)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA10)
+  IMX_PAD_LCD1_DATA10 = _IMX_PAD(0x440, 0xF8), // LCD1_DATA10
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA11)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA11)
+  IMX_PAD_LCD1_DATA11 = _IMX_PAD(0x444, 0xFC), // LCD1_DATA11
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA12)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA12)
+  IMX_PAD_LCD1_DATA12 = _IMX_PAD(0x448, 0x100), // LCD1_DATA12
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA13)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA13)
+  IMX_PAD_LCD1_DATA13 = _IMX_PAD(0x44C, 0x104), // LCD1_DATA13
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA14)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA14)
+  IMX_PAD_LCD1_DATA14 = _IMX_PAD(0x450, 0x108), // LCD1_DATA14
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA15)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA15)
+  IMX_PAD_LCD1_DATA15 = _IMX_PAD(0x454, 0x10C), // LCD1_DATA15
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA16)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA16)
+  IMX_PAD_LCD1_DATA16 = _IMX_PAD(0x458, 0x110), // LCD1_DATA16
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA17)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA17)
+  IMX_PAD_LCD1_DATA17 = _IMX_PAD(0x45C, 0x114), // LCD1_DATA17
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA18)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA18)
+  IMX_PAD_LCD1_DATA18 = _IMX_PAD(0x460, 0x118), // LCD1_DATA18
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA19)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA19)
+  IMX_PAD_LCD1_DATA19 = _IMX_PAD(0x464, 0x11C), // LCD1_DATA19
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA20)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA20)
+  IMX_PAD_LCD1_DATA20 = _IMX_PAD(0x468, 0x120), // LCD1_DATA20
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA21)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA21)
+  IMX_PAD_LCD1_DATA21 = _IMX_PAD(0x46C, 0x124), // LCD1_DATA21
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA22)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA22)
+  IMX_PAD_LCD1_DATA22 = _IMX_PAD(0x470, 0x128), // LCD1_DATA22
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_DATA23)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_DATA23)
+  IMX_PAD_LCD1_DATA23 = _IMX_PAD(0x474, 0x12C), // LCD1_DATA23
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_ENABLE)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_ENABLE)
+  IMX_PAD_LCD1_ENABLE = _IMX_PAD(0x478, 0x130), // LCD1_ENABLE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_HSYNC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_HSYNC)
+  IMX_PAD_LCD1_HSYNC = _IMX_PAD(0x47C, 0x134), // LCD1_HSYNC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_RESET)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_RESET)
+  IMX_PAD_LCD1_RESET = _IMX_PAD(0x480, 0x138), // LCD1_RESET
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_LCD1_VSYNC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_LCD1_VSYNC)
+  IMX_PAD_LCD1_VSYNC = _IMX_PAD(0x484, 0x13C), // LCD1_VSYNC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_ALE)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_ALE)
+  IMX_PAD_NAND_ALE = _IMX_PAD(0x488, 0x140), // NAND_ALE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CE0_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CE0_B)
+  IMX_PAD_NAND_CE0_B = _IMX_PAD(0x48C, 0x144), // NAND_CE0_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CE1_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B)
+  IMX_PAD_NAND_CE1_B = _IMX_PAD(0x490, 0x148), // NAND_CE1_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_CLE)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_CLE)
+  IMX_PAD_NAND_CLE = _IMX_PAD(0x494, 0x14C), // NAND_CLE
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA00)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA00)
+  IMX_PAD_NAND_DATA00 = _IMX_PAD(0x498, 0x150), // NAND_DATA00
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA01)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA01)
+  IMX_PAD_NAND_DATA01 = _IMX_PAD(0x49C, 0x154), // NAND_DATA01
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA02)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA02)
+  IMX_PAD_NAND_DATA02 = _IMX_PAD(0x4A0, 0x158), // NAND_DATA02
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA03)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA03)
+  IMX_PAD_NAND_DATA03 = _IMX_PAD(0x4A4, 0x15C), // NAND_DATA03
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA04)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA04)
+  IMX_PAD_NAND_DATA04 = _IMX_PAD(0x4A8, 0x160), // NAND_DATA04
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA05)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA05)
+  IMX_PAD_NAND_DATA05 = _IMX_PAD(0x4AC, 0x164), // NAND_DATA05
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA06)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA06)
+  IMX_PAD_NAND_DATA06 = _IMX_PAD(0x4B0, 0x168), // NAND_DATA06
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_DATA07)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_DATA07)
+  IMX_PAD_NAND_DATA07 = _IMX_PAD(0x4B4, 0x16C), // NAND_DATA07
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_RE_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_RE_B)
+  IMX_PAD_NAND_RE_B = _IMX_PAD(0x4B8, 0x170), // NAND_RE_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_READY_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_READY_B)
+  IMX_PAD_NAND_READY_B = _IMX_PAD(0x4BC, 0x174), // NAND_READY_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_WE_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_WE_B)
+  IMX_PAD_NAND_WE_B = _IMX_PAD(0x4C0, 0x178), // NAND_WE_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_NAND_WP_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_NAND_WP_B)
+  IMX_PAD_NAND_WP_B = _IMX_PAD(0x4C4, 0x17C), // NAND_WP_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_DATA0)
+  IMX_PAD_QSPI1A_DATA0 = _IMX_PAD(0x4C8, 0x180), // QSPI1A_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_DATA1)
+  IMX_PAD_QSPI1A_DATA1 = _IMX_PAD(0x4CC, 0x184), // QSPI1A_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_DATA2)
+  IMX_PAD_QSPI1A_DATA2 = _IMX_PAD(0x4D0, 0x188), // QSPI1A_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_DATA3)
+  IMX_PAD_QSPI1A_DATA3 = _IMX_PAD(0x4D4, 0x18C), // QSPI1A_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_DQS)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_DQS)
+  IMX_PAD_QSPI1A_DQS = _IMX_PAD(0x4D8, 0x190), // QSPI1A_DQS
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_SCLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_SCLK)
+  IMX_PAD_QSPI1A_SCLK = _IMX_PAD(0x4DC, 0x194), // QSPI1A_SCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_SS0_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_SS0_B)
+  IMX_PAD_QSPI1A_SS0_B = _IMX_PAD(0x4E0, 0x198), // QSPI1A_SS0_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1A_SS1_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1A_SS1_B)
+  IMX_PAD_QSPI1A_SS1_B = _IMX_PAD(0x4E4, 0x19C), // QSPI1A_SS1_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_DATA0)
+  IMX_PAD_QSPI1B_DATA0 = _IMX_PAD(0x4E8, 0x1A0), // QSPI1B_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_DATA1)
+  IMX_PAD_QSPI1B_DATA1 = _IMX_PAD(0x4EC, 0x1A4), // QSPI1B_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_DATA2)
+  IMX_PAD_QSPI1B_DATA2 = _IMX_PAD(0x4F0, 0x1A8), // QSPI1B_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_DATA3)
+  IMX_PAD_QSPI1B_DATA3 = _IMX_PAD(0x4F4, 0x1AC), // QSPI1B_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_DQS)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_DQS)
+  IMX_PAD_QSPI1B_DQS = _IMX_PAD(0x4F8, 0x1B0), // QSPI1B_DQS
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_SCLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_SCLK)
+  IMX_PAD_QSPI1B_SCLK = _IMX_PAD(0x4FC, 0x1B4), // QSPI1B_SCLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_SS0_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_SS0_B)
+  IMX_PAD_QSPI1B_SS0_B = _IMX_PAD(0x500, 0x1B8), // QSPI1B_SS0_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_QSPI1B_SS1_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_QSPI1B_SS1_B)
+  IMX_PAD_QSPI1B_SS1_B = _IMX_PAD(0x504, 0x1BC), // QSPI1B_SS1_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_RD0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_RD0)
+  IMX_PAD_RGMII1_RD0 = _IMX_PAD(0x508, 0x1C0), // ENET1_RX_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_RD1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_RD1)
+  IMX_PAD_RGMII1_RD1 = _IMX_PAD(0x50C, 0x1C4), // ENET1_RX_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_RD2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_RD2)
+  IMX_PAD_RGMII1_RD2 = _IMX_PAD(0x510, 0x1C8), // ENET1_RX_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_RD3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_RD3)
+  IMX_PAD_RGMII1_RD3 = _IMX_PAD(0x514, 0x1CC), // ENET1_RX_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_RX_CTL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_RX_CTL)
+  IMX_PAD_RGMII1_RX_CTL = _IMX_PAD(0x518, 0x1D0), // ENET1_RX_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_RXC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_RXC)
+  IMX_PAD_RGMII1_RXC = _IMX_PAD(0x51C, 0x1D4), // ENET1_RGMII_RXC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_TD0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_TD0)
+  IMX_PAD_RGMII1_TD0 = _IMX_PAD(0x520, 0x1D8), // ENET1_TX_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_TD1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_TD1)
+  IMX_PAD_RGMII1_TD1 = _IMX_PAD(0x524, 0x1DC), // ENET1_TX_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_TD2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_TD2)
+  IMX_PAD_RGMII1_TD2 = _IMX_PAD(0x528, 0x1E0), // ENET1_TX_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_TD3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_TD3)
+  IMX_PAD_RGMII1_TD3 = _IMX_PAD(0x52C, 0x1E4), // ENET1_TX_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_TX_CTL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_TX_CTL)
+  IMX_PAD_RGMII1_TX_CTL = _IMX_PAD(0x530, 0x1E8), // ENET1_TX_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII1_TXC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII1_TXC)
+  IMX_PAD_RGMII1_TXC = _IMX_PAD(0x534, 0x1EC), // ENET1_RGMII_TXC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_RD0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_RD0)
+  IMX_PAD_RGMII2_RD0 = _IMX_PAD(0x538, 0x1F0), // ENET2_RX_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_RD1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_RD1)
+  IMX_PAD_RGMII2_RD1 = _IMX_PAD(0x53C, 0x1F4), // ENET2_RX_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_RD2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_RD2)
+  IMX_PAD_RGMII2_RD2 = _IMX_PAD(0x540, 0x1F8), // ENET2_RX_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_RD3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_RD3)
+  IMX_PAD_RGMII2_RD3 = _IMX_PAD(0x544, 0x1FC), // ENET2_RX_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_RX_CTL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_RX_CTL)
+  IMX_PAD_RGMII2_RX_CTL = _IMX_PAD(0x548, 0x200), // ENET2_RX_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_RXC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_RXC)
+  IMX_PAD_RGMII2_RXC = _IMX_PAD(0x54C, 0x204), // ENET2_RGMII_RXC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_TD0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_TD0)
+  IMX_PAD_RGMII2_TD0 = _IMX_PAD(0x550, 0x208), // ENET2_TX_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_TD1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_TD1)
+  IMX_PAD_RGMII2_TD1 = _IMX_PAD(0x554, 0x20C), // ENET2_TX_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_TD2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_TD2)
+  IMX_PAD_RGMII2_TD2 = _IMX_PAD(0x558, 0x210), // ENET2_TX_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_TD3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_TD3)
+  IMX_PAD_RGMII2_TD3 = _IMX_PAD(0x55C, 0x214), // ENET2_TX_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_TX_CTL)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_TX_CTL)
+  IMX_PAD_RGMII2_TX_CTL = _IMX_PAD(0x560, 0x218), // ENET2_TX_EN
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_RGMII2_TXC)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_RGMII2_TXC)
+  IMX_PAD_RGMII2_TXC = _IMX_PAD(0x564, 0x21C), // ENET2_RGMII_TXC
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_CLK)
+  IMX_PAD_SD1_CLK = _IMX_PAD(0x568, 0x220), // SD1_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_CMD)
+  IMX_PAD_SD1_CMD = _IMX_PAD(0x56C, 0x224), // SD1_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA0)
+  IMX_PAD_SD1_DATA0 = _IMX_PAD(0x570, 0x228), // SD1_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA1)
+  IMX_PAD_SD1_DATA1 = _IMX_PAD(0x574, 0x22C), // SD1_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2)
+  IMX_PAD_SD1_DATA2 = _IMX_PAD(0x578, 0x230), // SD1_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD1_DATA3)
+  IMX_PAD_SD1_DATA3 = _IMX_PAD(0x57C, 0x234), // SD1_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_CLK)
+  IMX_PAD_SD2_CLK = _IMX_PAD(0x580, 0x238), // SD2_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_CMD)
+  IMX_PAD_SD2_CMD = _IMX_PAD(0x584, 0x23C), // SD2_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA0)
+  IMX_PAD_SD2_DATA0 = _IMX_PAD(0x588, 0x240), // SD2_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA1)
+  IMX_PAD_SD2_DATA1 = _IMX_PAD(0x58C, 0x244), // SD2_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA2)
+  IMX_PAD_SD2_DATA2 = _IMX_PAD(0x590, 0x248), // SD2_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD2_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD2_DATA3)
+  IMX_PAD_SD2_DATA3 = _IMX_PAD(0x594, 0x24C), // SD2_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_CLK)
+  IMX_PAD_SD4_CLK = _IMX_PAD(0x5C0, 0x278), // SD4_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_CMD)
+  IMX_PAD_SD4_CMD = _IMX_PAD(0x5C4, 0x27C), // SD4_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA0)
+  IMX_PAD_SD4_DATA0 = _IMX_PAD(0x5C8, 0x280), // SD4_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA1)
+  IMX_PAD_SD4_DATA1 = _IMX_PAD(0x5CC, 0x284), // SD4_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA2)
+  IMX_PAD_SD4_DATA2 = _IMX_PAD(0x5D0, 0x288), // SD4_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA3)
+  IMX_PAD_SD4_DATA3 = _IMX_PAD(0x5D4, 0x28C), // SD4_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA4)
+  IMX_PAD_SD4_DATA4 = _IMX_PAD(0x5D8, 0x290), // SD4_DATA4
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA5)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA5)
+  IMX_PAD_SD4_DATA5 = _IMX_PAD(0x5DC, 0x294), // SD4_DATA5
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA6)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA6)
+  IMX_PAD_SD4_DATA6 = _IMX_PAD(0x5E0, 0x298), // SD4_DATA6
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_DATA7)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_DATA7)
+  IMX_PAD_SD4_DATA7 = _IMX_PAD(0x5E4, 0x29C), // SD4_DATA7
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD4_RESET_B)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD4_RESET_B)
+  IMX_PAD_SD4_RESET_B = _IMX_PAD(0x5E8, 0x2A0), // SD4_RESET_B
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_CLK)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_CLK)
+  IMX_PAD_SD3_CLK = _IMX_PAD(0x598, 0x250), // SD3_CLK
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_CMD)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_CMD)
+  IMX_PAD_SD3_CMD = _IMX_PAD(0x59C, 0x254), // SD3_CMD
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA0)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA0)
+  IMX_PAD_SD3_DATA0 = _IMX_PAD(0x5A0, 0x258), // SD3_DATA0
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA1)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA1)
+  IMX_PAD_SD3_DATA1 = _IMX_PAD(0x5A4, 0x25C), // SD3_DATA1
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA2)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA2)
+  IMX_PAD_SD3_DATA2 = _IMX_PAD(0x5A8, 0x260), // SD3_DATA2
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA3)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA3)
+  IMX_PAD_SD3_DATA3 = _IMX_PAD(0x5AC, 0x264), // SD3_DATA3
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA4)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA4)
+  IMX_PAD_SD3_DATA4 = _IMX_PAD(0x5B0, 0x268), // SD3_DATA4
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA5)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA5)
+  IMX_PAD_SD3_DATA5 = _IMX_PAD(0x5B4, 0x26C), // SD3_DATA5
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA6)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA6)
+  IMX_PAD_SD3_DATA6 = _IMX_PAD(0x5B8, 0x270), // SD3_DATA6
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_SD3_DATA7)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_SD3_DATA7)
+  IMX_PAD_SD3_DATA7 = _IMX_PAD(0x5BC, 0x274), // SD3_DATA7
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_USB_H_DATA)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_USB_H_DATA)
+  IMX_PAD_USB_H_DATA = _IMX_PAD(0x5EC, 0x2A4), // USB_H_DATA
+
+  // Pad Control Register (IOMUXC_SW_PAD_CTL_PAD_USB_H_STROBE)
+  // Pad Mux Register (IOMUXC_SW_MUX_CTL_PAD_USB_H_STROBE)
+  IMX_PAD_USB_H_STROBE = _IMX_PAD(0x5F0, 0x2A8), // USB_H_STROBE
+} IMX_PAD;
+
+// Alternate function numbers
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO00_ALT0_I2C1_SCL = 0,
+  IMX_IOMUXC_GPIO1_IO00_ALT1_SD1_VSELECT = 1,
+  IMX_IOMUXC_GPIO1_IO00_ALT2_SPDIF_LOCK = 2,
+  IMX_IOMUXC_GPIO1_IO00_ALT4_WDOG1_ANY = 4,
+  IMX_IOMUXC_GPIO1_IO00_ALT5_GPIO1_IO00 = 5,
+  IMX_IOMUXC_GPIO1_IO00_ALT6_SNVS_VIO_5 = 6,
+} IMX_IOMUXC_GPIO1_IO00_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO01_ALT0_I2C1_SDA = 0,
+  IMX_IOMUXC_GPIO1_IO01_ALT1_SD1_RESET_B = 1,
+  IMX_IOMUXC_GPIO1_IO01_ALT2_SPDIF_SR_CLK = 2,
+  IMX_IOMUXC_GPIO1_IO01_ALT4_WDOG3_B = 4,
+  IMX_IOMUXC_GPIO1_IO01_ALT5_GPIO1_IO01 = 5,
+  IMX_IOMUXC_GPIO1_IO01_ALT6_SNVS_VIO_5_CTL = 6,
+} IMX_IOMUXC_GPIO1_IO01_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO02_ALT0_I2C2_SCL = 0,
+  IMX_IOMUXC_GPIO1_IO02_ALT1_SD1_CD_B = 1,
+  IMX_IOMUXC_GPIO1_IO02_ALT2_CSI2_MCLK = 2,
+  IMX_IOMUXC_GPIO1_IO02_ALT4_WDOG1_B = 4,
+  IMX_IOMUXC_GPIO1_IO02_ALT5_GPIO1_IO02 = 5,
+  IMX_IOMUXC_GPIO1_IO02_ALT6_CCM_REF_EN_B = 6,
+} IMX_IOMUXC_GPIO1_IO02_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO03_ALT0_I2C2_SDA = 0,
+  IMX_IOMUXC_GPIO1_IO03_ALT1_SD1_WP = 1,
+  IMX_IOMUXC_GPIO1_IO03_ALT2_ENET1_REF_CLK_25M = 2,
+  IMX_IOMUXC_GPIO1_IO03_ALT4_WDOG2_B = 4,
+  IMX_IOMUXC_GPIO1_IO03_ALT5_GPIO1_IO03 = 5,
+} IMX_IOMUXC_GPIO1_IO03_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO04_ALT0_UART1_TX_DATA = 0,
+  IMX_IOMUXC_GPIO1_IO04_ALT1_SD2_RESET_B = 1,
+  IMX_IOMUXC_GPIO1_IO04_ALT2_ENET1_MDC = 2,
+  IMX_IOMUXC_GPIO1_IO04_ALT4_ENET2_REF_CLK2 = 4,
+  IMX_IOMUXC_GPIO1_IO04_ALT5_GPIO1_IO04 = 5,
+} IMX_IOMUXC_GPIO1_IO04_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO05_ALT0_UART1_RX_DATA = 0,
+  IMX_IOMUXC_GPIO1_IO05_ALT1_SD2_VSELECT = 1,
+  IMX_IOMUXC_GPIO1_IO05_ALT2_ENET1_MDIO = 2,
+  IMX_IOMUXC_GPIO1_IO05_ALT3_ASRC_EXT_CLK = 3,
+  IMX_IOMUXC_GPIO1_IO05_ALT4_ENET1_REF_CLK1 = 4,
+  IMX_IOMUXC_GPIO1_IO05_ALT5_GPIO1_IO05 = 5,
+} IMX_IOMUXC_GPIO1_IO05_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO06_ALT0_UART2_TX_DATA = 0,
+  IMX_IOMUXC_GPIO1_IO06_ALT1_SD2_CD_B = 1,
+  IMX_IOMUXC_GPIO1_IO06_ALT2_ENET2_MDC = 2,
+  IMX_IOMUXC_GPIO1_IO06_ALT3_CSI1_MCLK = 3,
+  IMX_IOMUXC_GPIO1_IO06_ALT4_UART1_RTS_B = 4,
+  IMX_IOMUXC_GPIO1_IO06_ALT5_GPIO1_IO06 = 5,
+} IMX_IOMUXC_GPIO1_IO06_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO07_ALT0_UART2_RX_DATA = 0,
+  IMX_IOMUXC_GPIO1_IO07_ALT1_SD2_WP = 1,
+  IMX_IOMUXC_GPIO1_IO07_ALT2_ENET2_MDIO = 2,
+  IMX_IOMUXC_GPIO1_IO07_ALT3_AUDIO_CLK_OUT = 3,
+  IMX_IOMUXC_GPIO1_IO07_ALT4_UART1_CTS_B = 4,
+  IMX_IOMUXC_GPIO1_IO07_ALT5_GPIO1_IO07 = 5,
+  IMX_IOMUXC_GPIO1_IO07_ALT7_DCIC2_OUT = 7,
+} IMX_IOMUXC_GPIO1_IO07_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO08_ALT0_USB_OTG1_OC = 0,
+  IMX_IOMUXC_GPIO1_IO08_ALT1_WDOG1_B = 1,
+  IMX_IOMUXC_GPIO1_IO08_ALT2_SDMA_EXT_EVENT0 = 2,
+  IMX_IOMUXC_GPIO1_IO08_ALT3_CCM_PMIC_READY = 3,
+  IMX_IOMUXC_GPIO1_IO08_ALT4_UART2_RTS_B = 4,
+  IMX_IOMUXC_GPIO1_IO08_ALT5_GPIO1_IO08 = 5,
+  IMX_IOMUXC_GPIO1_IO08_ALT7_DCIC1_OUT = 7,
+} IMX_IOMUXC_GPIO1_IO08_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO09_ALT0_USB_OTG1_PWR = 0,
+  IMX_IOMUXC_GPIO1_IO09_ALT1_WDOG2_B = 1,
+  IMX_IOMUXC_GPIO1_IO09_ALT2_SDMA_EXT_EVENT1 = 2,
+  IMX_IOMUXC_GPIO1_IO09_ALT4_UART2_CTS_B = 4,
+  IMX_IOMUXC_GPIO1_IO09_ALT5_GPIO1_IO09 = 5,
+} IMX_IOMUXC_GPIO1_IO09_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO10_ALT0_USB_OTG1_ID = 0,
+  IMX_IOMUXC_GPIO1_IO10_ALT1_SPDIF_EXT_CLK = 1,
+  IMX_IOMUXC_GPIO1_IO10_ALT2_PWM1_OUT = 2,
+  IMX_IOMUXC_GPIO1_IO10_ALT4_CSI1_FIELD = 4,
+  IMX_IOMUXC_GPIO1_IO10_ALT5_GPIO1_IO10 = 5,
+} IMX_IOMUXC_GPIO1_IO10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO11_ALT0_USB_OTG2_OC = 0,
+  IMX_IOMUXC_GPIO1_IO11_ALT1_SPDIF_IN = 1,
+  IMX_IOMUXC_GPIO1_IO11_ALT2_PWM2_OUT = 2,
+  IMX_IOMUXC_GPIO1_IO11_ALT3_CCM_CLKO1 = 3,
+  IMX_IOMUXC_GPIO1_IO11_ALT4_MLB_DATA = 4,
+  IMX_IOMUXC_GPIO1_IO11_ALT5_GPIO1_IO11 = 5,
+} IMX_IOMUXC_GPIO1_IO11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO12_ALT0_USB_OTG2_PWR = 0,
+  IMX_IOMUXC_GPIO1_IO12_ALT1_SPDIF_OUT = 1,
+  IMX_IOMUXC_GPIO1_IO12_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_GPIO1_IO12_ALT3_CCM_CLKO2 = 3,
+  IMX_IOMUXC_GPIO1_IO12_ALT4_MLB_CLK = 4,
+  IMX_IOMUXC_GPIO1_IO12_ALT5_GPIO1_IO12 = 5,
+} IMX_IOMUXC_GPIO1_IO12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_GPIO1_IO13_ALT0_WDOG1_ANY = 0,
+  IMX_IOMUXC_GPIO1_IO13_ALT1_USB_OTG2_ID = 1,
+  IMX_IOMUXC_GPIO1_IO13_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_GPIO1_IO13_ALT4_MLB_SIG = 4,
+  IMX_IOMUXC_GPIO1_IO13_ALT5_GPIO1_IO13 = 5,
+} IMX_IOMUXC_GPIO1_IO13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA00_ALT0_CSI1_DATA02 = 0,
+  IMX_IOMUXC_CSI_DATA00_ALT1_ESAI_TX_CLK = 1,
+  IMX_IOMUXC_CSI_DATA00_ALT2_AUD6_TXC = 2,
+  IMX_IOMUXC_CSI_DATA00_ALT3_I2C1_SCL = 3,
+  IMX_IOMUXC_CSI_DATA00_ALT4_UART6_RI_B = 4,
+  IMX_IOMUXC_CSI_DATA00_ALT5_GPIO1_IO14 = 5,
+  IMX_IOMUXC_CSI_DATA00_ALT6_EIM_DATA23 = 6,
+  IMX_IOMUXC_CSI_DATA00_ALT7_SAI1_TX_BCLK = 7,
+} IMX_IOMUXC_CSI_DATA00_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA01_ALT0_CSI1_DATA03 = 0,
+  IMX_IOMUXC_CSI_DATA01_ALT1_ESAI_TX_FS = 1,
+  IMX_IOMUXC_CSI_DATA01_ALT2_AUD6_TXFS = 2,
+  IMX_IOMUXC_CSI_DATA01_ALT3_I2C1_SDA = 3,
+  IMX_IOMUXC_CSI_DATA01_ALT4_UART6_DSR_B = 4,
+  IMX_IOMUXC_CSI_DATA01_ALT5_GPIO1_IO15 = 5,
+  IMX_IOMUXC_CSI_DATA01_ALT6_EIM_DATA22 = 6,
+  IMX_IOMUXC_CSI_DATA01_ALT7_SAI1_TX_SYNC = 7,
+} IMX_IOMUXC_CSI_DATA01_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA02_ALT0_CSI1_DATA04 = 0,
+  IMX_IOMUXC_CSI_DATA02_ALT1_ESAI_RX_CLK = 1,
+  IMX_IOMUXC_CSI_DATA02_ALT2_AUD6_RXC = 2,
+  IMX_IOMUXC_CSI_DATA02_ALT3_KPP_COL5 = 3,
+  IMX_IOMUXC_CSI_DATA02_ALT4_UART6_DTR_B = 4,
+  IMX_IOMUXC_CSI_DATA02_ALT5_GPIO1_IO16 = 5,
+  IMX_IOMUXC_CSI_DATA02_ALT6_EIM_DATA21 = 6,
+  IMX_IOMUXC_CSI_DATA02_ALT7_SAI1_RX_BCLK = 7,
+} IMX_IOMUXC_CSI_DATA02_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA03_ALT0_CSI1_DATA05 = 0,
+  IMX_IOMUXC_CSI_DATA03_ALT1_ESAI_RX_FS = 1,
+  IMX_IOMUXC_CSI_DATA03_ALT2_AUD6_RXFS = 2,
+  IMX_IOMUXC_CSI_DATA03_ALT3_KPP_ROW5 = 3,
+  IMX_IOMUXC_CSI_DATA03_ALT4_UART6_DCD_B = 4,
+  IMX_IOMUXC_CSI_DATA03_ALT5_GPIO1_IO17 = 5,
+  IMX_IOMUXC_CSI_DATA03_ALT6_EIM_DATA20 = 6,
+  IMX_IOMUXC_CSI_DATA03_ALT7_SAI1_RX_SYNC = 7,
+} IMX_IOMUXC_CSI_DATA03_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA04_ALT0_CSI1_DATA06 = 0,
+  IMX_IOMUXC_CSI_DATA04_ALT1_ESAI_TX1 = 1,
+  IMX_IOMUXC_CSI_DATA04_ALT2_SPDIF_OUT = 2,
+  IMX_IOMUXC_CSI_DATA04_ALT3_KPP_COL6 = 3,
+  IMX_IOMUXC_CSI_DATA04_ALT4_UART6_RX_DATA = 4,
+  IMX_IOMUXC_CSI_DATA04_ALT5_GPIO1_IO18 = 5,
+  IMX_IOMUXC_CSI_DATA04_ALT6_EIM_DATA19 = 6,
+  IMX_IOMUXC_CSI_DATA04_ALT7_PWM5_OUT = 7,
+} IMX_IOMUXC_CSI_DATA04_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA05_ALT0_CSI1_DATA07 = 0,
+  IMX_IOMUXC_CSI_DATA05_ALT1_ESAI_TX4_RX1 = 1,
+  IMX_IOMUXC_CSI_DATA05_ALT2_SPDIF_IN = 2,
+  IMX_IOMUXC_CSI_DATA05_ALT3_KPP_ROW6 = 3,
+  IMX_IOMUXC_CSI_DATA05_ALT4_UART6_TX_DATA = 4,
+  IMX_IOMUXC_CSI_DATA05_ALT5_GPIO1_IO19 = 5,
+  IMX_IOMUXC_CSI_DATA05_ALT6_EIM_DATA18 = 6,
+  IMX_IOMUXC_CSI_DATA05_ALT7_PWM6_OUT = 7,
+} IMX_IOMUXC_CSI_DATA05_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA06_ALT0_CSI1_DATA08 = 0,
+  IMX_IOMUXC_CSI_DATA06_ALT1_ESAI_TX2_RX3 = 1,
+  IMX_IOMUXC_CSI_DATA06_ALT2_I2C4_SCL = 2,
+  IMX_IOMUXC_CSI_DATA06_ALT3_KPP_COL7 = 3,
+  IMX_IOMUXC_CSI_DATA06_ALT4_UART6_RTS_B = 4,
+  IMX_IOMUXC_CSI_DATA06_ALT5_GPIO1_IO20 = 5,
+  IMX_IOMUXC_CSI_DATA06_ALT6_EIM_DATA17 = 6,
+  IMX_IOMUXC_CSI_DATA06_ALT7_DCIC2_OUT = 7,
+} IMX_IOMUXC_CSI_DATA06_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_DATA07_ALT0_CSI1_DATA09 = 0,
+  IMX_IOMUXC_CSI_DATA07_ALT1_ESAI_TX3_RX2 = 1,
+  IMX_IOMUXC_CSI_DATA07_ALT2_I2C4_SDA = 2,
+  IMX_IOMUXC_CSI_DATA07_ALT3_KPP_ROW7 = 3,
+  IMX_IOMUXC_CSI_DATA07_ALT4_UART6_CTS_B = 4,
+  IMX_IOMUXC_CSI_DATA07_ALT5_GPIO1_IO21 = 5,
+  IMX_IOMUXC_CSI_DATA07_ALT6_EIM_DATA16 = 6,
+  IMX_IOMUXC_CSI_DATA07_ALT7_DCIC1_OUT = 7,
+} IMX_IOMUXC_CSI_DATA07_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_HSYNC_ALT0_CSI1_HSYNC = 0,
+  IMX_IOMUXC_CSI_HSYNC_ALT1_ESAI_TX0 = 1,
+  IMX_IOMUXC_CSI_HSYNC_ALT2_AUD6_TXD = 2,
+  IMX_IOMUXC_CSI_HSYNC_ALT3_UART4_RTS_B = 3,
+  IMX_IOMUXC_CSI_HSYNC_ALT4_MQS_LEFT = 4,
+  IMX_IOMUXC_CSI_HSYNC_ALT5_GPIO1_IO22 = 5,
+  IMX_IOMUXC_CSI_HSYNC_ALT6_EIM_DATA25 = 6,
+  IMX_IOMUXC_CSI_HSYNC_ALT7_SAI1_TX_DATA0 = 7,
+} IMX_IOMUXC_CSI_HSYNC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_MCLK_ALT0_CSI1_MCLK = 0,
+  IMX_IOMUXC_CSI_MCLK_ALT1_ESAI_TX_HF_CLK = 1,
+  IMX_IOMUXC_CSI_MCLK_ALT3_UART4_RX_DATA = 3,
+  IMX_IOMUXC_CSI_MCLK_ALT4_XTALOSC_REF_CLK_32K = 4,
+  IMX_IOMUXC_CSI_MCLK_ALT5_GPIO1_IO23 = 5,
+  IMX_IOMUXC_CSI_MCLK_ALT6_EIM_DATA26 = 6,
+  IMX_IOMUXC_CSI_MCLK_ALT7_CSI1_FIELD = 7,
+} IMX_IOMUXC_CSI_MCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_PIXCLK_ALT0_CSI1_PIXCLK = 0,
+  IMX_IOMUXC_CSI_PIXCLK_ALT1_ESAI_RX_HF_CLK = 1,
+  IMX_IOMUXC_CSI_PIXCLK_ALT2_AUDIO_CLK_OUT = 2,
+  IMX_IOMUXC_CSI_PIXCLK_ALT3_UART4_TX_DATA = 3,
+  IMX_IOMUXC_CSI_PIXCLK_ALT4_XTALOSC_REF_CLK_24M = 4,
+  IMX_IOMUXC_CSI_PIXCLK_ALT5_GPIO1_IO24 = 5,
+  IMX_IOMUXC_CSI_PIXCLK_ALT6_EIM_DATA27 = 6,
+  IMX_IOMUXC_CSI_PIXCLK_ALT7_ESAI_TX_HF_CLK = 7,
+} IMX_IOMUXC_CSI_PIXCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_CSI_VSYNC_ALT0_CSI1_VSYNC = 0,
+  IMX_IOMUXC_CSI_VSYNC_ALT1_ESAI_TX5_RX0 = 1,
+  IMX_IOMUXC_CSI_VSYNC_ALT2_AUD6_RXD = 2,
+  IMX_IOMUXC_CSI_VSYNC_ALT3_UART4_CTS_B = 3,
+  IMX_IOMUXC_CSI_VSYNC_ALT4_MQS_RIGHT = 4,
+  IMX_IOMUXC_CSI_VSYNC_ALT5_GPIO1_IO25 = 5,
+  IMX_IOMUXC_CSI_VSYNC_ALT6_EIM_DATA24 = 6,
+  IMX_IOMUXC_CSI_VSYNC_ALT7_SAI1_RX_DATA0 = 7,
+} IMX_IOMUXC_CSI_VSYNC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET1_COL_ALT0_ENET1_COL = 0,
+  IMX_IOMUXC_ENET1_COL_ALT1_ENET2_MDC = 1,
+  IMX_IOMUXC_ENET1_COL_ALT2_AUD4_TXC = 2,
+  IMX_IOMUXC_ENET1_COL_ALT3_UART1_RI_B = 3,
+  IMX_IOMUXC_ENET1_COL_ALT4_SPDIF_EXT_CLK = 4,
+  IMX_IOMUXC_ENET1_COL_ALT5_GPIO2_IO00 = 5,
+  IMX_IOMUXC_ENET1_COL_ALT6_CSI2_DATA23 = 6,
+  IMX_IOMUXC_ENET1_COL_ALT7_LCD2_DATA16 = 7,
+} IMX_IOMUXC_ENET1_COL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET1_CRS_ALT0_ENET1_CRS = 0,
+  IMX_IOMUXC_ENET1_CRS_ALT1_ENET2_MDIO = 1,
+  IMX_IOMUXC_ENET1_CRS_ALT2_AUD4_TXD = 2,
+  IMX_IOMUXC_ENET1_CRS_ALT3_UART1_DCD_B = 3,
+  IMX_IOMUXC_ENET1_CRS_ALT4_SPDIF_LOCK = 4,
+  IMX_IOMUXC_ENET1_CRS_ALT5_GPIO2_IO01 = 5,
+  IMX_IOMUXC_ENET1_CRS_ALT6_CSI2_DATA22 = 6,
+  IMX_IOMUXC_ENET1_CRS_ALT7_LCD2_DATA17 = 7,
+} IMX_IOMUXC_ENET1_CRS_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET1_MDC_ALT0_ENET1_MDC = 0,
+  IMX_IOMUXC_ENET1_MDC_ALT1_ENET2_MDC = 1,
+  IMX_IOMUXC_ENET1_MDC_ALT2_AUD3_RXFS = 2,
+  IMX_IOMUXC_ENET1_MDC_ALT3_XTALOSC_REF_CLK_24M = 3,
+  IMX_IOMUXC_ENET1_MDC_ALT4_EPIT2_OUT = 4,
+  IMX_IOMUXC_ENET1_MDC_ALT5_GPIO2_IO02 = 5,
+  IMX_IOMUXC_ENET1_MDC_ALT6_USB_OTG1_PWR = 6,
+  IMX_IOMUXC_ENET1_MDC_ALT7_PWM7_OUT = 7,
+} IMX_IOMUXC_ENET1_MDC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET1_MDIO_ALT0_ENET1_MDIO = 0,
+  IMX_IOMUXC_ENET1_MDIO_ALT1_ENET2_MDIO = 1,
+  IMX_IOMUXC_ENET1_MDIO_ALT2_AUDIO_CLK_OUT = 2,
+  IMX_IOMUXC_ENET1_MDIO_ALT4_EPIT1_OUT = 4,
+  IMX_IOMUXC_ENET1_MDIO_ALT5_GPIO2_IO03 = 5,
+  IMX_IOMUXC_ENET1_MDIO_ALT6_USB_OTG1_OC = 6,
+  IMX_IOMUXC_ENET1_MDIO_ALT7_PWM8_OUT = 7,
+} IMX_IOMUXC_ENET1_MDIO_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET1_RX_CLK_ALT0_ENET1_RX_CLK = 0,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT1_ENET1_REF_CLK_25M = 1,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT2_AUD4_TXFS = 2,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT3_UART1_DSR_B = 3,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT4_SPDIF_OUT = 4,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT5_GPIO2_IO04 = 5,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT6_CSI2_DATA21 = 6,
+  IMX_IOMUXC_ENET1_RX_CLK_ALT7_LCD2_DATA18 = 7,
+} IMX_IOMUXC_ENET1_RX_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET1_TX_CLK_ALT0_ENET1_TX_CLK = 0,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT1_ENET1_REF_CLK1 = 1,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT2_AUD4_RXD = 2,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT3_UART1_DTR_B = 3,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT4_SPDIF_SR_CLK = 4,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT5_GPIO2_IO05 = 5,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT6_CSI2_DATA20 = 6,
+  IMX_IOMUXC_ENET1_TX_CLK_ALT7_LCD2_DATA19 = 7,
+} IMX_IOMUXC_ENET1_TX_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET2_COL_ALT0_ENET2_COL = 0,
+  IMX_IOMUXC_ENET2_COL_ALT1_ENET1_MDC = 1,
+  IMX_IOMUXC_ENET2_COL_ALT2_AUD4_RXC = 2,
+  IMX_IOMUXC_ENET2_COL_ALT3_UART1_RX_DATA = 3,
+  IMX_IOMUXC_ENET2_COL_ALT4_SPDIF_IN = 4,
+  IMX_IOMUXC_ENET2_COL_ALT5_GPIO2_IO06 = 5,
+  IMX_IOMUXC_ENET2_COL_ALT6_USB_OTG1_ID = 6,
+  IMX_IOMUXC_ENET2_COL_ALT7_LCD2_DATA20 = 7,
+} IMX_IOMUXC_ENET2_COL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET2_CRS_ALT0_ENET2_CRS = 0,
+  IMX_IOMUXC_ENET2_CRS_ALT1_ENET1_MDIO = 1,
+  IMX_IOMUXC_ENET2_CRS_ALT2_AUD4_RXFS = 2,
+  IMX_IOMUXC_ENET2_CRS_ALT3_UART1_TX_DATA = 3,
+  IMX_IOMUXC_ENET2_CRS_ALT4_MLB_SIG = 4,
+  IMX_IOMUXC_ENET2_CRS_ALT5_GPIO2_IO07 = 5,
+  IMX_IOMUXC_ENET2_CRS_ALT6_USB_OTG2_ID = 6,
+  IMX_IOMUXC_ENET2_CRS_ALT7_LCD2_DATA21 = 7,
+} IMX_IOMUXC_ENET2_CRS_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET2_RX_CLK_ALT0_ENET2_RX_CLK = 0,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT1_ENET2_REF_CLK_25M = 1,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT2_I2C3_SCL = 2,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT3_UART1_RTS_B = 3,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT4_MLB_DATA = 4,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT5_GPIO2_IO08 = 5,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT6_USB_OTG2_OC = 6,
+  IMX_IOMUXC_ENET2_RX_CLK_ALT7_LCD2_DATA22 = 7,
+} IMX_IOMUXC_ENET2_RX_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_ENET2_TX_CLK_ALT0_ENET2_TX_CLK = 0,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT1_ENET2_REF_CLK2 = 1,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT2_I2C3_SDA = 2,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT3_UART1_CTS_B = 3,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT4_MLB_CLK = 4,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT5_GPIO2_IO09 = 5,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT6_USB_OTG2_PWR = 6,
+  IMX_IOMUXC_ENET2_TX_CLK_ALT7_LCD2_DATA23 = 7,
+} IMX_IOMUXC_ENET2_TX_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL0_ALT0_KPP_COL0 = 0,
+  IMX_IOMUXC_KEY_COL0_ALT1_SD3_CD_B = 1,
+  IMX_IOMUXC_KEY_COL0_ALT2_UART6_RTS_B = 2,
+  IMX_IOMUXC_KEY_COL0_ALT3_ECSPI1_SCLK = 3,
+  IMX_IOMUXC_KEY_COL0_ALT4_AUD5_TXC = 4,
+  IMX_IOMUXC_KEY_COL0_ALT5_GPIO2_IO10 = 5,
+  IMX_IOMUXC_KEY_COL0_ALT6_SDMA_EXT_EVENT1 = 6,
+  IMX_IOMUXC_KEY_COL0_ALT7_SAI2_TX_BCLK = 7,
+} IMX_IOMUXC_KEY_COL0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL1_ALT0_KPP_COL1 = 0,
+  IMX_IOMUXC_KEY_COL1_ALT1_SD3_RESET_B = 1,
+  IMX_IOMUXC_KEY_COL1_ALT2_UART6_TX_DATA = 2,
+  IMX_IOMUXC_KEY_COL1_ALT3_ECSPI1_MISO = 3,
+  IMX_IOMUXC_KEY_COL1_ALT4_AUD5_TXFS = 4,
+  IMX_IOMUXC_KEY_COL1_ALT5_GPIO2_IO11 = 5,
+  IMX_IOMUXC_KEY_COL1_ALT6_SD3_RESET = 6,
+  IMX_IOMUXC_KEY_COL1_ALT7_SAI2_TX_SYNC = 7,
+} IMX_IOMUXC_KEY_COL1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL2_ALT0_KPP_COL2 = 0,
+  IMX_IOMUXC_KEY_COL2_ALT1_SD4_CD_B = 1,
+  IMX_IOMUXC_KEY_COL2_ALT2_UART5_RTS_B = 2,
+  IMX_IOMUXC_KEY_COL2_ALT3_CAN1_TX = 3,
+  IMX_IOMUXC_KEY_COL2_ALT5_GPIO2_IO12 = 5,
+  IMX_IOMUXC_KEY_COL2_ALT6_EIM_DATA30 = 6,
+  IMX_IOMUXC_KEY_COL2_ALT7_ECSPI1_RDY = 7,
+} IMX_IOMUXC_KEY_COL2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL3_ALT0_KPP_COL3 = 0,
+  IMX_IOMUXC_KEY_COL3_ALT1_SD4_LCTL = 1,
+  IMX_IOMUXC_KEY_COL3_ALT2_UART5_TX_DATA = 2,
+  IMX_IOMUXC_KEY_COL3_ALT3_CAN2_TX = 3,
+  IMX_IOMUXC_KEY_COL3_ALT5_GPIO2_IO13 = 5,
+  IMX_IOMUXC_KEY_COL3_ALT6_EIM_DATA28 = 6,
+  IMX_IOMUXC_KEY_COL3_ALT7_ECSPI1_SS2 = 7,
+} IMX_IOMUXC_KEY_COL3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_COL4_ALT0_KPP_COL4 = 0,
+  IMX_IOMUXC_KEY_COL4_ALT1_ENET2_MDC = 1,
+  IMX_IOMUXC_KEY_COL4_ALT2_I2C3_SCL = 2,
+  IMX_IOMUXC_KEY_COL4_ALT3_SD2_LCTL = 3,
+  IMX_IOMUXC_KEY_COL4_ALT4_AUD5_RXC = 4,
+  IMX_IOMUXC_KEY_COL4_ALT5_GPIO2_IO14 = 5,
+  IMX_IOMUXC_KEY_COL4_ALT6_EIM_CRE = 6,
+  IMX_IOMUXC_KEY_COL4_ALT7_SAI2_RX_BCLK = 7,
+} IMX_IOMUXC_KEY_COL4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW0_ALT0_KPP_ROW0 = 0,
+  IMX_IOMUXC_KEY_ROW0_ALT1_SD3_WP = 1,
+  IMX_IOMUXC_KEY_ROW0_ALT2_UART6_CTS_B = 2,
+  IMX_IOMUXC_KEY_ROW0_ALT3_ECSPI1_MOSI = 3,
+  IMX_IOMUXC_KEY_ROW0_ALT4_AUD5_TXD = 4,
+  IMX_IOMUXC_KEY_ROW0_ALT5_GPIO2_IO15 = 5,
+  IMX_IOMUXC_KEY_ROW0_ALT6_SDMA_EXT_EVENT0 = 6,
+  IMX_IOMUXC_KEY_ROW0_ALT7_SAI2_TX_DATA0 = 7,
+} IMX_IOMUXC_KEY_ROW0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW1_ALT0_KPP_ROW1 = 0,
+  IMX_IOMUXC_KEY_ROW1_ALT1_SD4_VSELECT = 1,
+  IMX_IOMUXC_KEY_ROW1_ALT2_UART6_RX_DATA = 2,
+  IMX_IOMUXC_KEY_ROW1_ALT3_ECSPI1_SS0 = 3,
+  IMX_IOMUXC_KEY_ROW1_ALT4_AUD5_RXD = 4,
+  IMX_IOMUXC_KEY_ROW1_ALT5_GPIO2_IO16 = 5,
+  IMX_IOMUXC_KEY_ROW1_ALT6_EIM_DATA31 = 6,
+  IMX_IOMUXC_KEY_ROW1_ALT7_SAI2_RX_DATA0 = 7,
+} IMX_IOMUXC_KEY_ROW1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW2_ALT0_KPP_ROW2 = 0,
+  IMX_IOMUXC_KEY_ROW2_ALT1_SD4_WP = 1,
+  IMX_IOMUXC_KEY_ROW2_ALT2_UART5_CTS_B = 2,
+  IMX_IOMUXC_KEY_ROW2_ALT3_CAN1_RX = 3,
+  IMX_IOMUXC_KEY_ROW2_ALT5_GPIO2_IO17 = 5,
+  IMX_IOMUXC_KEY_ROW2_ALT6_EIM_DATA29 = 6,
+  IMX_IOMUXC_KEY_ROW2_ALT7_ECSPI1_SS3 = 7,
+} IMX_IOMUXC_KEY_ROW2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW3_ALT0_KPP_ROW3 = 0,
+  IMX_IOMUXC_KEY_ROW3_ALT1_SD3_LCTL = 1,
+  IMX_IOMUXC_KEY_ROW3_ALT2_UART5_RX_DATA = 2,
+  IMX_IOMUXC_KEY_ROW3_ALT3_CAN2_RX = 3,
+  IMX_IOMUXC_KEY_ROW3_ALT5_GPIO2_IO18 = 5,
+  IMX_IOMUXC_KEY_ROW3_ALT6_EIM_DTACK_B = 6,
+  IMX_IOMUXC_KEY_ROW3_ALT7_ECSPI1_SS1 = 7,
+} IMX_IOMUXC_KEY_ROW3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_KEY_ROW4_ALT0_KPP_ROW4 = 0,
+  IMX_IOMUXC_KEY_ROW4_ALT1_ENET2_MDIO = 1,
+  IMX_IOMUXC_KEY_ROW4_ALT2_I2C3_SDA = 2,
+  IMX_IOMUXC_KEY_ROW4_ALT3_SD1_LCTL = 3,
+  IMX_IOMUXC_KEY_ROW4_ALT4_AUD5_RXFS = 4,
+  IMX_IOMUXC_KEY_ROW4_ALT5_GPIO2_IO19 = 5,
+  IMX_IOMUXC_KEY_ROW4_ALT6_EIM_ACLK_FREERUN = 6,
+  IMX_IOMUXC_KEY_ROW4_ALT7_SAI2_RX_SYNC = 7,
+} IMX_IOMUXC_KEY_ROW4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_CLK_ALT0_LCD1_CLK = 0,
+  IMX_IOMUXC_LCD1_CLK_ALT1_LCD1_WR_RWN = 1,
+  IMX_IOMUXC_LCD1_CLK_ALT2_AUD3_RXC = 2,
+  IMX_IOMUXC_LCD1_CLK_ALT3_ENET1_1588_EVENT2_IN = 3,
+  IMX_IOMUXC_LCD1_CLK_ALT4_CSI1_DATA16 = 4,
+  IMX_IOMUXC_LCD1_CLK_ALT5_GPIO3_IO00 = 5,
+  IMX_IOMUXC_LCD1_CLK_ALT6_SD1_WP = 6,
+} IMX_IOMUXC_LCD1_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA00_ALT0_LCD1_DATA00 = 0,
+  IMX_IOMUXC_LCD1_DATA00_ALT1_EIM_CS1_B = 1,
+  IMX_IOMUXC_LCD1_DATA00_ALT2_ARM_M4_TRACE0 = 2,
+  IMX_IOMUXC_LCD1_DATA00_ALT3_ARM_A9_TRACE00 = 3,
+  IMX_IOMUXC_LCD1_DATA00_ALT4_CSI1_DATA20 = 4,
+  IMX_IOMUXC_LCD1_DATA00_ALT5_GPIO3_IO01 = 5,
+  IMX_IOMUXC_LCD1_DATA00_ALT6_SRC_BOOT_CFG00 = 6,
+} IMX_IOMUXC_LCD1_DATA00_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA01_ALT0_LCD1_DATA01 = 0,
+  IMX_IOMUXC_LCD1_DATA01_ALT1_EIM_CS2_B = 1,
+  IMX_IOMUXC_LCD1_DATA01_ALT2_ARM_M4_TRACE1 = 2,
+  IMX_IOMUXC_LCD1_DATA01_ALT3_ARM_A9_TRACE01 = 3,
+  IMX_IOMUXC_LCD1_DATA01_ALT4_CSI1_DATA21 = 4,
+  IMX_IOMUXC_LCD1_DATA01_ALT5_GPIO3_IO02 = 5,
+  IMX_IOMUXC_LCD1_DATA01_ALT6_SRC_BOOT_CFG01 = 6,
+} IMX_IOMUXC_LCD1_DATA01_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA02_ALT0_LCD1_DATA02 = 0,
+  IMX_IOMUXC_LCD1_DATA02_ALT1_EIM_CS3_B = 1,
+  IMX_IOMUXC_LCD1_DATA02_ALT2_ARM_M4_TRACE2 = 2,
+  IMX_IOMUXC_LCD1_DATA02_ALT3_ARM_A9_TRACE02 = 3,
+  IMX_IOMUXC_LCD1_DATA02_ALT4_CSI1_DATA22 = 4,
+  IMX_IOMUXC_LCD1_DATA02_ALT5_GPIO3_IO03 = 5,
+  IMX_IOMUXC_LCD1_DATA02_ALT6_SRC_BOOT_CFG02 = 6,
+} IMX_IOMUXC_LCD1_DATA02_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA03_ALT0_LCD1_DATA03 = 0,
+  IMX_IOMUXC_LCD1_DATA03_ALT1_EIM_ADDR24 = 1,
+  IMX_IOMUXC_LCD1_DATA03_ALT2_ARM_M4_TRACE3 = 2,
+  IMX_IOMUXC_LCD1_DATA03_ALT3_ARM_A9_TRACE03 = 3,
+  IMX_IOMUXC_LCD1_DATA03_ALT4_CSI1_DATA23 = 4,
+  IMX_IOMUXC_LCD1_DATA03_ALT5_GPIO3_IO04 = 5,
+  IMX_IOMUXC_LCD1_DATA03_ALT6_SRC_BOOT_CFG03 = 6,
+} IMX_IOMUXC_LCD1_DATA03_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA04_ALT0_LCD1_DATA04 = 0,
+  IMX_IOMUXC_LCD1_DATA04_ALT1_EIM_ADDR25 = 1,
+  IMX_IOMUXC_LCD1_DATA04_ALT3_ARM_A9_TRACE04 = 3,
+  IMX_IOMUXC_LCD1_DATA04_ALT4_CSI1_VSYNC = 4,
+  IMX_IOMUXC_LCD1_DATA04_ALT5_GPIO3_IO05 = 5,
+  IMX_IOMUXC_LCD1_DATA04_ALT6_SRC_BOOT_CFG04 = 6,
+} IMX_IOMUXC_LCD1_DATA04_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA05_ALT0_LCD1_DATA05 = 0,
+  IMX_IOMUXC_LCD1_DATA05_ALT1_EIM_ADDR26 = 1,
+  IMX_IOMUXC_LCD1_DATA05_ALT3_ARM_A9_TRACE05 = 3,
+  IMX_IOMUXC_LCD1_DATA05_ALT4_CSI1_HSYNC = 4,
+  IMX_IOMUXC_LCD1_DATA05_ALT5_GPIO3_IO06 = 5,
+  IMX_IOMUXC_LCD1_DATA05_ALT6_SRC_BOOT_CFG05 = 6,
+} IMX_IOMUXC_LCD1_DATA05_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA06_ALT0_LCD1_DATA06 = 0,
+  IMX_IOMUXC_LCD1_DATA06_ALT1_EIM_EB2_B = 1,
+  IMX_IOMUXC_LCD1_DATA06_ALT3_ARM_A9_TRACE06 = 3,
+  IMX_IOMUXC_LCD1_DATA06_ALT4_CSI1_PIXCLK = 4,
+  IMX_IOMUXC_LCD1_DATA06_ALT5_GPIO3_IO07 = 5,
+  IMX_IOMUXC_LCD1_DATA06_ALT6_SRC_BOOT_CFG06 = 6,
+} IMX_IOMUXC_LCD1_DATA06_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA07_ALT0_LCD1_DATA07 = 0,
+  IMX_IOMUXC_LCD1_DATA07_ALT1_EIM_EB3_B = 1,
+  IMX_IOMUXC_LCD1_DATA07_ALT3_ARM_A9_TRACE07 = 3,
+  IMX_IOMUXC_LCD1_DATA07_ALT4_CSI1_MCLK = 4,
+  IMX_IOMUXC_LCD1_DATA07_ALT5_GPIO3_IO08 = 5,
+  IMX_IOMUXC_LCD1_DATA07_ALT6_SRC_BOOT_CFG07 = 6,
+} IMX_IOMUXC_LCD1_DATA07_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA08_ALT0_LCD1_DATA08 = 0,
+  IMX_IOMUXC_LCD1_DATA08_ALT1_EIM_AD08 = 1,
+  IMX_IOMUXC_LCD1_DATA08_ALT3_ARM_A9_TRACE08 = 3,
+  IMX_IOMUXC_LCD1_DATA08_ALT4_CSI1_DATA09 = 4,
+  IMX_IOMUXC_LCD1_DATA08_ALT5_GPIO3_IO09 = 5,
+  IMX_IOMUXC_LCD1_DATA08_ALT6_SRC_BOOT_CFG08 = 6,
+} IMX_IOMUXC_LCD1_DATA08_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA09_ALT0_LCD1_DATA09 = 0,
+  IMX_IOMUXC_LCD1_DATA09_ALT1_EIM_AD09 = 1,
+  IMX_IOMUXC_LCD1_DATA09_ALT3_ARM_A9_TRACE09 = 3,
+  IMX_IOMUXC_LCD1_DATA09_ALT4_CSI1_DATA08 = 4,
+  IMX_IOMUXC_LCD1_DATA09_ALT5_GPIO3_IO10 = 5,
+  IMX_IOMUXC_LCD1_DATA09_ALT6_SRC_BOOT_CFG09 = 6,
+} IMX_IOMUXC_LCD1_DATA09_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA10_ALT0_LCD1_DATA10 = 0,
+  IMX_IOMUXC_LCD1_DATA10_ALT1_EIM_AD10 = 1,
+  IMX_IOMUXC_LCD1_DATA10_ALT3_ARM_A9_TRACE10 = 3,
+  IMX_IOMUXC_LCD1_DATA10_ALT4_CSI1_DATA07 = 4,
+  IMX_IOMUXC_LCD1_DATA10_ALT5_GPIO3_IO11 = 5,
+  IMX_IOMUXC_LCD1_DATA10_ALT6_SRC_BOOT_CFG10 = 6,
+} IMX_IOMUXC_LCD1_DATA10_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA11_ALT0_LCD1_DATA11 = 0,
+  IMX_IOMUXC_LCD1_DATA11_ALT1_EIM_AD11 = 1,
+  IMX_IOMUXC_LCD1_DATA11_ALT3_ARM_A9_TRACE11 = 3,
+  IMX_IOMUXC_LCD1_DATA11_ALT4_CSI1_DATA06 = 4,
+  IMX_IOMUXC_LCD1_DATA11_ALT5_GPIO3_IO12 = 5,
+  IMX_IOMUXC_LCD1_DATA11_ALT6_SRC_BOOT_CFG11 = 6,
+} IMX_IOMUXC_LCD1_DATA11_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA12_ALT0_LCD1_DATA12 = 0,
+  IMX_IOMUXC_LCD1_DATA12_ALT1_EIM_AD12 = 1,
+  IMX_IOMUXC_LCD1_DATA12_ALT3_ARM_A9_TRACE12 = 3,
+  IMX_IOMUXC_LCD1_DATA12_ALT4_CSI1_DATA05 = 4,
+  IMX_IOMUXC_LCD1_DATA12_ALT5_GPIO3_IO13 = 5,
+  IMX_IOMUXC_LCD1_DATA12_ALT6_SRC_BOOT_CFG12 = 6,
+} IMX_IOMUXC_LCD1_DATA12_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA13_ALT0_LCD1_DATA13 = 0,
+  IMX_IOMUXC_LCD1_DATA13_ALT1_EIM_AD13 = 1,
+  IMX_IOMUXC_LCD1_DATA13_ALT3_ARM_A9_TRACE13 = 3,
+  IMX_IOMUXC_LCD1_DATA13_ALT4_CSI1_DATA04 = 4,
+  IMX_IOMUXC_LCD1_DATA13_ALT5_GPIO3_IO14 = 5,
+  IMX_IOMUXC_LCD1_DATA13_ALT6_SRC_BOOT_CFG13 = 6,
+} IMX_IOMUXC_LCD1_DATA13_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA14_ALT0_LCD1_DATA14 = 0,
+  IMX_IOMUXC_LCD1_DATA14_ALT1_EIM_AD14 = 1,
+  IMX_IOMUXC_LCD1_DATA14_ALT3_ARM_A9_TRACE14 = 3,
+  IMX_IOMUXC_LCD1_DATA14_ALT4_CSI1_DATA03 = 4,
+  IMX_IOMUXC_LCD1_DATA14_ALT5_GPIO3_IO15 = 5,
+  IMX_IOMUXC_LCD1_DATA14_ALT6_SRC_BOOT_CFG14 = 6,
+} IMX_IOMUXC_LCD1_DATA14_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA15_ALT0_LCD1_DATA15 = 0,
+  IMX_IOMUXC_LCD1_DATA15_ALT1_EIM_AD15 = 1,
+  IMX_IOMUXC_LCD1_DATA15_ALT3_ARM_A9_TRACE15 = 3,
+  IMX_IOMUXC_LCD1_DATA15_ALT4_CSI1_DATA02 = 4,
+  IMX_IOMUXC_LCD1_DATA15_ALT5_GPIO3_IO16 = 5,
+  IMX_IOMUXC_LCD1_DATA15_ALT6_SRC_BOOT_CFG15 = 6,
+} IMX_IOMUXC_LCD1_DATA15_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA16_ALT0_LCD1_DATA16 = 0,
+  IMX_IOMUXC_LCD1_DATA16_ALT1_EIM_ADDR16 = 1,
+  IMX_IOMUXC_LCD1_DATA16_ALT2_ARM_M4_TRACE_CLK = 2,
+  IMX_IOMUXC_LCD1_DATA16_ALT3_ARM_A9_TRACE_CLK = 3,
+  IMX_IOMUXC_LCD1_DATA16_ALT4_CSI1_DATA01 = 4,
+  IMX_IOMUXC_LCD1_DATA16_ALT5_GPIO3_IO17 = 5,
+  IMX_IOMUXC_LCD1_DATA16_ALT6_SRC_BOOT_CFG24 = 6,
+} IMX_IOMUXC_LCD1_DATA16_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA17_ALT0_LCD1_DATA17 = 0,
+  IMX_IOMUXC_LCD1_DATA17_ALT1_EIM_ADDR17 = 1,
+  IMX_IOMUXC_LCD1_DATA17_ALT3_ARM_A9_TRACE_CTL = 3,
+  IMX_IOMUXC_LCD1_DATA17_ALT4_CSI1_DATA00 = 4,
+  IMX_IOMUXC_LCD1_DATA17_ALT5_GPIO3_IO18 = 5,
+  IMX_IOMUXC_LCD1_DATA17_ALT6_SRC_BOOT_CFG25 = 6,
+} IMX_IOMUXC_LCD1_DATA17_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA18_ALT0_LCD1_DATA18 = 0,
+  IMX_IOMUXC_LCD1_DATA18_ALT1_EIM_ADDR18 = 1,
+  IMX_IOMUXC_LCD1_DATA18_ALT2_ARM_M4_EVENTO = 2,
+  IMX_IOMUXC_LCD1_DATA18_ALT3_ARM_A9_EVENTO = 3,
+  IMX_IOMUXC_LCD1_DATA18_ALT4_CSI1_DATA15 = 4,
+  IMX_IOMUXC_LCD1_DATA18_ALT5_GPIO3_IO19 = 5,
+  IMX_IOMUXC_LCD1_DATA18_ALT6_SRC_BOOT_CFG26 = 6,
+} IMX_IOMUXC_LCD1_DATA18_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA19_ALT0_LCD1_DATA19 = 0,
+  IMX_IOMUXC_LCD1_DATA19_ALT1_EIM_ADDR19 = 1,
+  IMX_IOMUXC_LCD1_DATA19_ALT2_ARM_M4_TRACE_SWO = 2,
+  IMX_IOMUXC_LCD1_DATA19_ALT4_CSI1_DATA14 = 4,
+  IMX_IOMUXC_LCD1_DATA19_ALT5_GPIO3_IO20 = 5,
+  IMX_IOMUXC_LCD1_DATA19_ALT6_SRC_BOOT_CFG27 = 6,
+} IMX_IOMUXC_LCD1_DATA19_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA20_ALT0_LCD1_DATA20 = 0,
+  IMX_IOMUXC_LCD1_DATA20_ALT1_EIM_ADDR20 = 1,
+  IMX_IOMUXC_LCD1_DATA20_ALT2_PWM8_OUT = 2,
+  IMX_IOMUXC_LCD1_DATA20_ALT3_ENET1_1588_EVENT2_OUT = 3,
+  IMX_IOMUXC_LCD1_DATA20_ALT4_CSI1_DATA13 = 4,
+  IMX_IOMUXC_LCD1_DATA20_ALT5_GPIO3_IO21 = 5,
+  IMX_IOMUXC_LCD1_DATA20_ALT6_SRC_BOOT_CFG28 = 6,
+} IMX_IOMUXC_LCD1_DATA20_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA21_ALT0_LCD1_DATA21 = 0,
+  IMX_IOMUXC_LCD1_DATA21_ALT1_EIM_ADDR21 = 1,
+  IMX_IOMUXC_LCD1_DATA21_ALT2_PWM7_OUT = 2,
+  IMX_IOMUXC_LCD1_DATA21_ALT3_ENET1_1588_EVENT3_OUT = 3,
+  IMX_IOMUXC_LCD1_DATA21_ALT4_CSI1_DATA12 = 4,
+  IMX_IOMUXC_LCD1_DATA21_ALT5_GPIO3_IO22 = 5,
+  IMX_IOMUXC_LCD1_DATA21_ALT6_SRC_BOOT_CFG29 = 6,
+} IMX_IOMUXC_LCD1_DATA21_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA22_ALT0_LCD1_DATA22 = 0,
+  IMX_IOMUXC_LCD1_DATA22_ALT1_EIM_ADDR22 = 1,
+  IMX_IOMUXC_LCD1_DATA22_ALT2_PWM6_OUT = 2,
+  IMX_IOMUXC_LCD1_DATA22_ALT3_ENET2_1588_EVENT2_OUT = 3,
+  IMX_IOMUXC_LCD1_DATA22_ALT4_CSI1_DATA11 = 4,
+  IMX_IOMUXC_LCD1_DATA22_ALT5_GPIO3_IO23 = 5,
+  IMX_IOMUXC_LCD1_DATA22_ALT6_SRC_BOOT_CFG30 = 6,
+} IMX_IOMUXC_LCD1_DATA22_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_DATA23_ALT0_LCD1_DATA23 = 0,
+  IMX_IOMUXC_LCD1_DATA23_ALT1_EIM_ADDR23 = 1,
+  IMX_IOMUXC_LCD1_DATA23_ALT2_PWM5_OUT = 2,
+  IMX_IOMUXC_LCD1_DATA23_ALT3_ENET2_1588_EVENT3_OUT = 3,
+  IMX_IOMUXC_LCD1_DATA23_ALT4_CSI1_DATA10 = 4,
+  IMX_IOMUXC_LCD1_DATA23_ALT5_GPIO3_IO24 = 5,
+  IMX_IOMUXC_LCD1_DATA23_ALT6_SRC_BOOT_CFG31 = 6,
+} IMX_IOMUXC_LCD1_DATA23_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_ENABLE_ALT0_LCD1_ENABLE = 0,
+  IMX_IOMUXC_LCD1_ENABLE_ALT1_LCD1_RD_E = 1,
+  IMX_IOMUXC_LCD1_ENABLE_ALT2_AUD3_TXC = 2,
+  IMX_IOMUXC_LCD1_ENABLE_ALT3_ENET1_1588_EVENT3_IN = 3,
+  IMX_IOMUXC_LCD1_ENABLE_ALT4_CSI1_DATA17 = 4,
+  IMX_IOMUXC_LCD1_ENABLE_ALT5_GPIO3_IO25 = 5,
+  IMX_IOMUXC_LCD1_ENABLE_ALT6_SD1_CD_B = 6,
+} IMX_IOMUXC_LCD1_ENABLE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_HSYNC_ALT0_LCD1_HSYNC = 0,
+  IMX_IOMUXC_LCD1_HSYNC_ALT1_LCD1_RS = 1,
+  IMX_IOMUXC_LCD1_HSYNC_ALT2_AUD3_TXD = 2,
+  IMX_IOMUXC_LCD1_HSYNC_ALT3_ENET2_1588_EVENT2_IN = 3,
+  IMX_IOMUXC_LCD1_HSYNC_ALT4_CSI1_DATA18 = 4,
+  IMX_IOMUXC_LCD1_HSYNC_ALT5_GPIO3_IO26 = 5,
+  IMX_IOMUXC_LCD1_HSYNC_ALT6_SD2_WP = 6,
+} IMX_IOMUXC_LCD1_HSYNC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_RESET_ALT0_LCD1_RESET = 0,
+  IMX_IOMUXC_LCD1_RESET_ALT1_LCD1_CS = 1,
+  IMX_IOMUXC_LCD1_RESET_ALT2_AUD3_RXD = 2,
+  IMX_IOMUXC_LCD1_RESET_ALT3_ARM_A9_EVENTI = 3,
+  IMX_IOMUXC_LCD1_RESET_ALT4_ARM_M4_EVENTI = 4,
+  IMX_IOMUXC_LCD1_RESET_ALT5_GPIO3_IO27 = 5,
+  IMX_IOMUXC_LCD1_RESET_ALT6_CCM_PMIC_READY = 6,
+} IMX_IOMUXC_LCD1_RESET_ALT;
+
+typedef enum {
+  IMX_IOMUXC_LCD1_VSYNC_ALT0_LCD1_VSYNC = 0,
+  IMX_IOMUXC_LCD1_VSYNC_ALT1_LCD1_BUSY = 1,
+  IMX_IOMUXC_LCD1_VSYNC_ALT2_AUD3_TXFS = 2,
+  IMX_IOMUXC_LCD1_VSYNC_ALT3_ENET2_1588_EVENT3_IN = 3,
+  IMX_IOMUXC_LCD1_VSYNC_ALT4_CSI1_DATA19 = 4,
+  IMX_IOMUXC_LCD1_VSYNC_ALT5_GPIO3_IO28 = 5,
+  IMX_IOMUXC_LCD1_VSYNC_ALT6_SD2_CD_B = 6,
+} IMX_IOMUXC_LCD1_VSYNC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_ALE_ALT0_NAND_ALE = 0,
+  IMX_IOMUXC_NAND_ALE_ALT1_I2C3_SDA = 1,
+  IMX_IOMUXC_NAND_ALE_ALT2_QSPI2A_SS0_B = 2,
+  IMX_IOMUXC_NAND_ALE_ALT3_ECSPI2_SS0 = 3,
+  IMX_IOMUXC_NAND_ALE_ALT4_ESAI_TX3_RX2 = 4,
+  IMX_IOMUXC_NAND_ALE_ALT5_GPIO4_IO00 = 5,
+  IMX_IOMUXC_NAND_ALE_ALT6_EIM_CS0_B = 6,
+} IMX_IOMUXC_NAND_ALE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_CE0_B_ALT0_NAND_CE0_B = 0,
+  IMX_IOMUXC_NAND_CE0_B_ALT1_SD2_VSELECT = 1,
+  IMX_IOMUXC_NAND_CE0_B_ALT2_QSPI2A_DATA2 = 2,
+  IMX_IOMUXC_NAND_CE0_B_ALT3_AUD4_TXC = 3,
+  IMX_IOMUXC_NAND_CE0_B_ALT4_ESAI_TX_CLK = 4,
+  IMX_IOMUXC_NAND_CE0_B_ALT5_GPIO4_IO01 = 5,
+  IMX_IOMUXC_NAND_CE0_B_ALT6_EIM_LBA_B = 6,
+} IMX_IOMUXC_NAND_CE0_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_CE1_B_ALT0_NAND_CE1_B = 0,
+  IMX_IOMUXC_NAND_CE1_B_ALT1_SD3_RESET_B = 1,
+  IMX_IOMUXC_NAND_CE1_B_ALT2_QSPI2A_DATA3 = 2,
+  IMX_IOMUXC_NAND_CE1_B_ALT3_AUD4_TXD = 3,
+  IMX_IOMUXC_NAND_CE1_B_ALT4_ESAI_TX0 = 4,
+  IMX_IOMUXC_NAND_CE1_B_ALT5_GPIO4_IO02 = 5,
+  IMX_IOMUXC_NAND_CE1_B_ALT6_EIM_OE = 6,
+} IMX_IOMUXC_NAND_CE1_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_CLE_ALT0_NAND_CLE = 0,
+  IMX_IOMUXC_NAND_CLE_ALT1_I2C3_SCL = 1,
+  IMX_IOMUXC_NAND_CLE_ALT2_QSPI2A_SCLK = 2,
+  IMX_IOMUXC_NAND_CLE_ALT3_ECSPI2_SCLK = 3,
+  IMX_IOMUXC_NAND_CLE_ALT4_ESAI_TX2_RX3 = 4,
+  IMX_IOMUXC_NAND_CLE_ALT5_GPIO4_IO03 = 5,
+  IMX_IOMUXC_NAND_CLE_ALT6_EIM_BCLK = 6,
+} IMX_IOMUXC_NAND_CLE_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA00_ALT0_NAND_DATA00 = 0,
+  IMX_IOMUXC_NAND_DATA00_ALT1_SD1_DATA4 = 1,
+  IMX_IOMUXC_NAND_DATA00_ALT2_QSPI2B_DATA1 = 2,
+  IMX_IOMUXC_NAND_DATA00_ALT3_ECSPI5_MISO = 3,
+  IMX_IOMUXC_NAND_DATA00_ALT4_ESAI_RX_CLK = 4,
+  IMX_IOMUXC_NAND_DATA00_ALT5_GPIO4_IO04 = 5,
+  IMX_IOMUXC_NAND_DATA00_ALT6_EIM_AD00 = 6,
+} IMX_IOMUXC_NAND_DATA00_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA01_ALT0_NAND_DATA01 = 0,
+  IMX_IOMUXC_NAND_DATA01_ALT1_SD1_DATA5 = 1,
+  IMX_IOMUXC_NAND_DATA01_ALT2_QSPI2B_DATA0 = 2,
+  IMX_IOMUXC_NAND_DATA01_ALT3_ECSPI5_MOSI = 3,
+  IMX_IOMUXC_NAND_DATA01_ALT4_ESAI_RX_FS = 4,
+  IMX_IOMUXC_NAND_DATA01_ALT5_GPIO4_IO05 = 5,
+  IMX_IOMUXC_NAND_DATA01_ALT6_EIM_AD01 = 6,
+} IMX_IOMUXC_NAND_DATA01_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA02_ALT0_NAND_DATA02 = 0,
+  IMX_IOMUXC_NAND_DATA02_ALT1_SD1_DATA6 = 1,
+  IMX_IOMUXC_NAND_DATA02_ALT2_QSPI2B_SCLK = 2,
+  IMX_IOMUXC_NAND_DATA02_ALT3_ECSPI5_SCLK = 3,
+  IMX_IOMUXC_NAND_DATA02_ALT4_ESAI_TX_HF_CLK = 4,
+  IMX_IOMUXC_NAND_DATA02_ALT5_GPIO4_IO06 = 5,
+  IMX_IOMUXC_NAND_DATA02_ALT6_EIM_AD02 = 6,
+} IMX_IOMUXC_NAND_DATA02_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA03_ALT0_NAND_DATA03 = 0,
+  IMX_IOMUXC_NAND_DATA03_ALT1_SD1_DATA7 = 1,
+  IMX_IOMUXC_NAND_DATA03_ALT2_QSPI2B_SS0_B = 2,
+  IMX_IOMUXC_NAND_DATA03_ALT3_ECSPI5_SS0 = 3,
+  IMX_IOMUXC_NAND_DATA03_ALT4_ESAI_RX_HF_CLK = 4,
+  IMX_IOMUXC_NAND_DATA03_ALT5_GPIO4_IO07 = 5,
+  IMX_IOMUXC_NAND_DATA03_ALT6_EIM_AD03 = 6,
+} IMX_IOMUXC_NAND_DATA03_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA04_ALT0_NAND_DATA04 = 0,
+  IMX_IOMUXC_NAND_DATA04_ALT1_SD2_DATA4 = 1,
+  IMX_IOMUXC_NAND_DATA04_ALT2_QSPI2B_SS1_B = 2,
+  IMX_IOMUXC_NAND_DATA04_ALT3_UART3_RTS_B = 3,
+  IMX_IOMUXC_NAND_DATA04_ALT4_AUD4_RXFS = 4,
+  IMX_IOMUXC_NAND_DATA04_ALT5_GPIO4_IO08 = 5,
+  IMX_IOMUXC_NAND_DATA04_ALT6_EIM_AD04 = 6,
+} IMX_IOMUXC_NAND_DATA04_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA05_ALT0_NAND_DATA05 = 0,
+  IMX_IOMUXC_NAND_DATA05_ALT1_SD2_DATA5 = 1,
+  IMX_IOMUXC_NAND_DATA05_ALT2_QSPI2B_DQS = 2,
+  IMX_IOMUXC_NAND_DATA05_ALT3_UART3_CTS_B = 3,
+  IMX_IOMUXC_NAND_DATA05_ALT4_AUD4_RXC = 4,
+  IMX_IOMUXC_NAND_DATA05_ALT5_GPIO4_IO09 = 5,
+  IMX_IOMUXC_NAND_DATA05_ALT6_EIM_AD05 = 6,
+} IMX_IOMUXC_NAND_DATA05_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA06_ALT0_NAND_DATA06 = 0,
+  IMX_IOMUXC_NAND_DATA06_ALT1_SD2_DATA6 = 1,
+  IMX_IOMUXC_NAND_DATA06_ALT2_QSPI2A_SS1_B = 2,
+  IMX_IOMUXC_NAND_DATA06_ALT3_UART3_RX_DATA = 3,
+  IMX_IOMUXC_NAND_DATA06_ALT4_PWM3_OUT = 4,
+  IMX_IOMUXC_NAND_DATA06_ALT5_GPIO4_IO10 = 5,
+  IMX_IOMUXC_NAND_DATA06_ALT6_EIM_AD06 = 6,
+} IMX_IOMUXC_NAND_DATA06_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_DATA07_ALT0_NAND_DATA07 = 0,
+  IMX_IOMUXC_NAND_DATA07_ALT1_SD2_DATA7 = 1,
+  IMX_IOMUXC_NAND_DATA07_ALT2_QSPI2A_DQS = 2,
+  IMX_IOMUXC_NAND_DATA07_ALT3_UART3_TX_DATA = 3,
+  IMX_IOMUXC_NAND_DATA07_ALT4_PWM4_OUT = 4,
+  IMX_IOMUXC_NAND_DATA07_ALT5_GPIO4_IO11 = 5,
+  IMX_IOMUXC_NAND_DATA07_ALT6_EIM_AD07 = 6,
+} IMX_IOMUXC_NAND_DATA07_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_RE_B_ALT0_NAND_RE_B = 0,
+  IMX_IOMUXC_NAND_RE_B_ALT1_SD2_RESET_B = 1,
+  IMX_IOMUXC_NAND_RE_B_ALT2_QSPI2B_DATA3 = 2,
+  IMX_IOMUXC_NAND_RE_B_ALT3_AUD4_TXFS = 3,
+  IMX_IOMUXC_NAND_RE_B_ALT4_ESAI_TX_FS = 4,
+  IMX_IOMUXC_NAND_RE_B_ALT5_GPIO4_IO12 = 5,
+  IMX_IOMUXC_NAND_RE_B_ALT6_EIM_RW = 6,
+} IMX_IOMUXC_NAND_RE_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_READY_B_ALT0_NAND_READY_B = 0,
+  IMX_IOMUXC_NAND_READY_B_ALT1_SD1_VSELECT = 1,
+  IMX_IOMUXC_NAND_READY_B_ALT2_QSPI2A_DATA1 = 2,
+  IMX_IOMUXC_NAND_READY_B_ALT3_ECSPI2_MISO = 3,
+  IMX_IOMUXC_NAND_READY_B_ALT4_ESAI_TX1 = 4,
+  IMX_IOMUXC_NAND_READY_B_ALT5_GPIO4_IO13 = 5,
+  IMX_IOMUXC_NAND_READY_B_ALT6_EIM_EB1_B = 6,
+} IMX_IOMUXC_NAND_READY_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_WE_B_ALT0_NAND_WE_B = 0,
+  IMX_IOMUXC_NAND_WE_B_ALT1_SD4_VSELECT = 1,
+  IMX_IOMUXC_NAND_WE_B_ALT2_QSPI2B_DATA2 = 2,
+  IMX_IOMUXC_NAND_WE_B_ALT3_AUD4_RXD = 3,
+  IMX_IOMUXC_NAND_WE_B_ALT4_ESAI_TX5_RX0 = 4,
+  IMX_IOMUXC_NAND_WE_B_ALT5_GPIO4_IO14 = 5,
+  IMX_IOMUXC_NAND_WE_B_ALT6_EIM_WAIT = 6,
+} IMX_IOMUXC_NAND_WE_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_NAND_WP_B_ALT0_NAND_WP_B = 0,
+  IMX_IOMUXC_NAND_WP_B_ALT1_SD1_RESET_B = 1,
+  IMX_IOMUXC_NAND_WP_B_ALT2_QSPI2A_DATA0 = 2,
+  IMX_IOMUXC_NAND_WP_B_ALT3_ECSPI2_MOSI = 3,
+  IMX_IOMUXC_NAND_WP_B_ALT4_ESAI_TX4_RX1 = 4,
+  IMX_IOMUXC_NAND_WP_B_ALT5_GPIO4_IO15 = 5,
+  IMX_IOMUXC_NAND_WP_B_ALT6_EIM_EB0_B = 6,
+} IMX_IOMUXC_NAND_WP_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_DATA0_ALT0_QSPI1A_DATA0 = 0,
+  IMX_IOMUXC_QSPI1A_DATA0_ALT1_USB_OTG2_OC = 1,
+  IMX_IOMUXC_QSPI1A_DATA0_ALT2_ECSPI1_MOSI = 2,
+  IMX_IOMUXC_QSPI1A_DATA0_ALT3_ESAI_TX4_RX1 = 3,
+  IMX_IOMUXC_QSPI1A_DATA0_ALT4_CSI1_DATA14 = 4,
+  IMX_IOMUXC_QSPI1A_DATA0_ALT5_GPIO4_IO16 = 5,
+  IMX_IOMUXC_QSPI1A_DATA0_ALT6_EIM_DATA06 = 6,
+} IMX_IOMUXC_QSPI1A_DATA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_DATA1_ALT0_QSPI1A_DATA1 = 0,
+  IMX_IOMUXC_QSPI1A_DATA1_ALT1_USB_OTG1_ID = 1,
+  IMX_IOMUXC_QSPI1A_DATA1_ALT2_ECSPI1_MISO = 2,
+  IMX_IOMUXC_QSPI1A_DATA1_ALT3_ESAI_TX1 = 3,
+  IMX_IOMUXC_QSPI1A_DATA1_ALT4_CSI1_DATA13 = 4,
+  IMX_IOMUXC_QSPI1A_DATA1_ALT5_GPIO4_IO17 = 5,
+  IMX_IOMUXC_QSPI1A_DATA1_ALT6_EIM_DATA05 = 6,
+} IMX_IOMUXC_QSPI1A_DATA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_DATA2_ALT0_QSPI1A_DATA2 = 0,
+  IMX_IOMUXC_QSPI1A_DATA2_ALT1_USB_OTG1_PWR = 1,
+  IMX_IOMUXC_QSPI1A_DATA2_ALT2_ECSPI5_SS1 = 2,
+  IMX_IOMUXC_QSPI1A_DATA2_ALT3_ESAI_TX_CLK = 3,
+  IMX_IOMUXC_QSPI1A_DATA2_ALT4_CSI1_DATA12 = 4,
+  IMX_IOMUXC_QSPI1A_DATA2_ALT5_GPIO4_IO18 = 5,
+  IMX_IOMUXC_QSPI1A_DATA2_ALT6_EIM_DATA04 = 6,
+} IMX_IOMUXC_QSPI1A_DATA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_DATA3_ALT0_QSPI1A_DATA3 = 0,
+  IMX_IOMUXC_QSPI1A_DATA3_ALT1_USB_OTG1_OC = 1,
+  IMX_IOMUXC_QSPI1A_DATA3_ALT2_ECSPI5_SS2 = 2,
+  IMX_IOMUXC_QSPI1A_DATA3_ALT3_ESAI_TX0 = 3,
+  IMX_IOMUXC_QSPI1A_DATA3_ALT4_CSI1_DATA11 = 4,
+  IMX_IOMUXC_QSPI1A_DATA3_ALT5_GPIO4_IO19 = 5,
+  IMX_IOMUXC_QSPI1A_DATA3_ALT6_EIM_DATA03 = 6,
+} IMX_IOMUXC_QSPI1A_DATA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_DQS_ALT0_QSPI1A_DQS = 0,
+  IMX_IOMUXC_QSPI1A_DQS_ALT1_CAN2_TX = 1,
+  IMX_IOMUXC_QSPI1A_DQS_ALT3_ECSPI5_MOSI = 3,
+  IMX_IOMUXC_QSPI1A_DQS_ALT4_CSI1_DATA15 = 4,
+  IMX_IOMUXC_QSPI1A_DQS_ALT5_GPIO4_IO20 = 5,
+  IMX_IOMUXC_QSPI1A_DQS_ALT6_EIM_DATA07 = 6,
+} IMX_IOMUXC_QSPI1A_DQS_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_SCLK_ALT0_QSPI1A_SCLK = 0,
+  IMX_IOMUXC_QSPI1A_SCLK_ALT1_USB_OTG2_ID = 1,
+  IMX_IOMUXC_QSPI1A_SCLK_ALT2_ECSPI1_SCLK = 2,
+  IMX_IOMUXC_QSPI1A_SCLK_ALT3_ESAI_TX2_RX3 = 3,
+  IMX_IOMUXC_QSPI1A_SCLK_ALT4_CSI1_DATA01 = 4,
+  IMX_IOMUXC_QSPI1A_SCLK_ALT5_GPIO4_IO21 = 5,
+  IMX_IOMUXC_QSPI1A_SCLK_ALT6_EIM_DATA00 = 6,
+} IMX_IOMUXC_QSPI1A_SCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT0_QSPI1A_SS0_B = 0,
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT1_USB_OTG2_PWR = 1,
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT2_ECSPI1_SS0 = 2,
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT3_ESAI_TX3_RX2 = 3,
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT4_CSI1_DATA00 = 4,
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT5_GPIO4_IO22 = 5,
+  IMX_IOMUXC_QSPI1A_SS0_B_ALT6_EIM_DATA01 = 6,
+} IMX_IOMUXC_QSPI1A_SS0_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1A_SS1_B_ALT0_QSPI1A_SS1_B = 0,
+  IMX_IOMUXC_QSPI1A_SS1_B_ALT1_CAN1_RX = 1,
+  IMX_IOMUXC_QSPI1A_SS1_B_ALT3_ECSPI5_MISO = 3,
+  IMX_IOMUXC_QSPI1A_SS1_B_ALT4_CSI1_DATA10 = 4,
+  IMX_IOMUXC_QSPI1A_SS1_B_ALT5_GPIO4_IO23 = 5,
+  IMX_IOMUXC_QSPI1A_SS1_B_ALT6_EIM_DATA02 = 6,
+} IMX_IOMUXC_QSPI1A_SS1_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_DATA0_ALT0_QSPI1B_DATA0 = 0,
+  IMX_IOMUXC_QSPI1B_DATA0_ALT1_UART3_CTS_B = 1,
+  IMX_IOMUXC_QSPI1B_DATA0_ALT2_ECSPI3_MOSI = 2,
+  IMX_IOMUXC_QSPI1B_DATA0_ALT3_ESAI_RX_FS = 3,
+  IMX_IOMUXC_QSPI1B_DATA0_ALT4_CSI1_DATA22 = 4,
+  IMX_IOMUXC_QSPI1B_DATA0_ALT5_GPIO4_IO24 = 5,
+  IMX_IOMUXC_QSPI1B_DATA0_ALT6_EIM_DATA14 = 6,
+} IMX_IOMUXC_QSPI1B_DATA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_DATA1_ALT0_QSPI1B_DATA1 = 0,
+  IMX_IOMUXC_QSPI1B_DATA1_ALT1_UART3_RTS_B = 1,
+  IMX_IOMUXC_QSPI1B_DATA1_ALT2_ECSPI3_MISO = 2,
+  IMX_IOMUXC_QSPI1B_DATA1_ALT3_ESAI_RX_CLK = 3,
+  IMX_IOMUXC_QSPI1B_DATA1_ALT4_CSI1_DATA21 = 4,
+  IMX_IOMUXC_QSPI1B_DATA1_ALT5_GPIO4_IO25 = 5,
+  IMX_IOMUXC_QSPI1B_DATA1_ALT6_EIM_DATA13 = 6,
+} IMX_IOMUXC_QSPI1B_DATA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_DATA2_ALT0_QSPI1B_DATA2 = 0,
+  IMX_IOMUXC_QSPI1B_DATA2_ALT1_I2C2_SDA = 1,
+  IMX_IOMUXC_QSPI1B_DATA2_ALT2_ECSPI5_RDY = 2,
+  IMX_IOMUXC_QSPI1B_DATA2_ALT3_ESAI_TX5_RX0 = 3,
+  IMX_IOMUXC_QSPI1B_DATA2_ALT4_CSI1_DATA20 = 4,
+  IMX_IOMUXC_QSPI1B_DATA2_ALT5_GPIO4_IO26 = 5,
+  IMX_IOMUXC_QSPI1B_DATA2_ALT6_EIM_DATA12 = 6,
+} IMX_IOMUXC_QSPI1B_DATA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_DATA3_ALT0_QSPI1B_DATA3 = 0,
+  IMX_IOMUXC_QSPI1B_DATA3_ALT1_I2C2_SCL = 1,
+  IMX_IOMUXC_QSPI1B_DATA3_ALT2_ECSPI5_SS3 = 2,
+  IMX_IOMUXC_QSPI1B_DATA3_ALT3_ESAI_TX_FS = 3,
+  IMX_IOMUXC_QSPI1B_DATA3_ALT4_CSI1_DATA19 = 4,
+  IMX_IOMUXC_QSPI1B_DATA3_ALT5_GPIO4_IO27 = 5,
+  IMX_IOMUXC_QSPI1B_DATA3_ALT6_EIM_DATA11 = 6,
+} IMX_IOMUXC_QSPI1B_DATA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_DQS_ALT0_QSPI1B_DQS = 0,
+  IMX_IOMUXC_QSPI1B_DQS_ALT1_CAN1_TX = 1,
+  IMX_IOMUXC_QSPI1B_DQS_ALT3_ECSPI5_SS0 = 3,
+  IMX_IOMUXC_QSPI1B_DQS_ALT4_CSI1_DATA23 = 4,
+  IMX_IOMUXC_QSPI1B_DQS_ALT5_GPIO4_IO28 = 5,
+  IMX_IOMUXC_QSPI1B_DQS_ALT6_EIM_DATA15 = 6,
+} IMX_IOMUXC_QSPI1B_DQS_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_SCLK_ALT0_QSPI1B_SCLK = 0,
+  IMX_IOMUXC_QSPI1B_SCLK_ALT1_UART3_RX_DATA = 1,
+  IMX_IOMUXC_QSPI1B_SCLK_ALT2_ECSPI3_SCLK = 2,
+  IMX_IOMUXC_QSPI1B_SCLK_ALT3_ESAI_RX_HF_CLK = 3,
+  IMX_IOMUXC_QSPI1B_SCLK_ALT4_CSI1_DATA16 = 4,
+  IMX_IOMUXC_QSPI1B_SCLK_ALT5_GPIO4_IO29 = 5,
+  IMX_IOMUXC_QSPI1B_SCLK_ALT6_EIM_DATA08 = 6,
+} IMX_IOMUXC_QSPI1B_SCLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT0_QSPI1B_SS0_B = 0,
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT1_UART3_TX_DATA = 1,
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT2_ECSPI3_SS0 = 2,
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT3_ESAI_TX_HF_CLK = 3,
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT4_CSI1_DATA17 = 4,
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT5_GPIO4_IO30 = 5,
+  IMX_IOMUXC_QSPI1B_SS0_B_ALT6_EIM_DATA09 = 6,
+} IMX_IOMUXC_QSPI1B_SS0_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_QSPI1B_SS1_B_ALT0_QSPI1B_SS1_B = 0,
+  IMX_IOMUXC_QSPI1B_SS1_B_ALT1_CAN2_RX = 1,
+  IMX_IOMUXC_QSPI1B_SS1_B_ALT3_ECSPI5_SCLK = 3,
+  IMX_IOMUXC_QSPI1B_SS1_B_ALT4_CSI1_DATA18 = 4,
+  IMX_IOMUXC_QSPI1B_SS1_B_ALT5_GPIO4_IO31 = 5,
+  IMX_IOMUXC_QSPI1B_SS1_B_ALT6_EIM_DATA10 = 6,
+} IMX_IOMUXC_QSPI1B_SS1_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_RD0_ALT0_ENET1_RX_DATA0 = 0,
+  IMX_IOMUXC_RGMII1_RD0_ALT5_GPIO5_IO00 = 5,
+  IMX_IOMUXC_RGMII1_RD0_ALT6_CSI2_DATA10 = 6,
+} IMX_IOMUXC_RGMII1_RD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_RD1_ALT0_ENET1_RX_DATA1 = 0,
+  IMX_IOMUXC_RGMII1_RD1_ALT5_GPIO5_IO01 = 5,
+  IMX_IOMUXC_RGMII1_RD1_ALT6_CSI2_DATA11 = 6,
+} IMX_IOMUXC_RGMII1_RD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_RD2_ALT0_ENET1_RX_DATA2 = 0,
+  IMX_IOMUXC_RGMII1_RD2_ALT5_GPIO5_IO02 = 5,
+  IMX_IOMUXC_RGMII1_RD2_ALT6_CSI2_DATA12 = 6,
+} IMX_IOMUXC_RGMII1_RD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_RD3_ALT0_ENET1_RX_DATA3 = 0,
+  IMX_IOMUXC_RGMII1_RD3_ALT5_GPIO5_IO03 = 5,
+  IMX_IOMUXC_RGMII1_RD3_ALT6_CSI2_DATA13 = 6,
+} IMX_IOMUXC_RGMII1_RD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_RX_CTL_ALT0_ENET1_RX_EN = 0,
+  IMX_IOMUXC_RGMII1_RX_CTL_ALT5_GPIO5_IO04 = 5,
+  IMX_IOMUXC_RGMII1_RX_CTL_ALT6_CSI2_DATA14 = 6,
+} IMX_IOMUXC_RGMII1_RX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_RXC_ALT0_ENET1_RGMII_RXC = 0,
+  IMX_IOMUXC_RGMII1_RXC_ALT1_ENET1_RX_ER = 1,
+  IMX_IOMUXC_RGMII1_RXC_ALT5_GPIO5_IO05 = 5,
+  IMX_IOMUXC_RGMII1_RXC_ALT6_CSI2_DATA15 = 6,
+} IMX_IOMUXC_RGMII1_RXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_TD0_ALT0_ENET1_TX_DATA0 = 0,
+  IMX_IOMUXC_RGMII1_TD0_ALT2_SAI2_RX_SYNC = 2,
+  IMX_IOMUXC_RGMII1_TD0_ALT5_GPIO5_IO06 = 5,
+  IMX_IOMUXC_RGMII1_TD0_ALT6_CSI2_DATA16 = 6,
+} IMX_IOMUXC_RGMII1_TD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_TD1_ALT0_ENET1_TX_DATA1 = 0,
+  IMX_IOMUXC_RGMII1_TD1_ALT2_SAI2_RX_BCLK = 2,
+  IMX_IOMUXC_RGMII1_TD1_ALT5_GPIO5_IO07 = 5,
+  IMX_IOMUXC_RGMII1_TD1_ALT6_CSI2_DATA17 = 6,
+} IMX_IOMUXC_RGMII1_TD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_TD2_ALT0_ENET1_TX_DATA2 = 0,
+  IMX_IOMUXC_RGMII1_TD2_ALT2_SAI2_TX_SYNC = 2,
+  IMX_IOMUXC_RGMII1_TD2_ALT5_GPIO5_IO08 = 5,
+  IMX_IOMUXC_RGMII1_TD2_ALT6_CSI2_DATA18 = 6,
+} IMX_IOMUXC_RGMII1_TD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_TD3_ALT0_ENET1_TX_DATA3 = 0,
+  IMX_IOMUXC_RGMII1_TD3_ALT2_SAI2_TX_BCLK = 2,
+  IMX_IOMUXC_RGMII1_TD3_ALT5_GPIO5_IO09 = 5,
+  IMX_IOMUXC_RGMII1_TD3_ALT6_CSI2_DATA19 = 6,
+} IMX_IOMUXC_RGMII1_TD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_TX_CTL_ALT0_ENET1_TX_EN = 0,
+  IMX_IOMUXC_RGMII1_TX_CTL_ALT2_SAI2_RX_DATA0 = 2,
+  IMX_IOMUXC_RGMII1_TX_CTL_ALT5_GPIO5_IO10 = 5,
+  IMX_IOMUXC_RGMII1_TX_CTL_ALT6_CSI2_DATA00 = 6,
+} IMX_IOMUXC_RGMII1_TX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII1_TXC_ALT0_ENET1_RGMII_TXC = 0,
+  IMX_IOMUXC_RGMII1_TXC_ALT1_ENET1_TX_ER = 1,
+  IMX_IOMUXC_RGMII1_TXC_ALT2_SAI2_TX_DATA0 = 2,
+  IMX_IOMUXC_RGMII1_TXC_ALT5_GPIO5_IO11 = 5,
+  IMX_IOMUXC_RGMII1_TXC_ALT6_CSI2_DATA01 = 6,
+} IMX_IOMUXC_RGMII1_TXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_RD0_ALT0_ENET2_RX_DATA0 = 0,
+  IMX_IOMUXC_RGMII2_RD0_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_RGMII2_RD0_ALT5_GPIO5_IO12 = 5,
+  IMX_IOMUXC_RGMII2_RD0_ALT6_CSI2_DATA02 = 6,
+} IMX_IOMUXC_RGMII2_RD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_RD1_ALT0_ENET2_RX_DATA1 = 0,
+  IMX_IOMUXC_RGMII2_RD1_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_RGMII2_RD1_ALT5_GPIO5_IO13 = 5,
+  IMX_IOMUXC_RGMII2_RD1_ALT6_CSI2_DATA03 = 6,
+} IMX_IOMUXC_RGMII2_RD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_RD2_ALT0_ENET2_RX_DATA2 = 0,
+  IMX_IOMUXC_RGMII2_RD2_ALT2_PWM2_OUT = 2,
+  IMX_IOMUXC_RGMII2_RD2_ALT5_GPIO5_IO14 = 5,
+  IMX_IOMUXC_RGMII2_RD2_ALT6_CSI2_DATA04 = 6,
+} IMX_IOMUXC_RGMII2_RD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_RD3_ALT0_ENET2_RX_DATA3 = 0,
+  IMX_IOMUXC_RGMII2_RD3_ALT2_PWM1_OUT = 2,
+  IMX_IOMUXC_RGMII2_RD3_ALT5_GPIO5_IO15 = 5,
+  IMX_IOMUXC_RGMII2_RD3_ALT6_CSI2_DATA05 = 6,
+} IMX_IOMUXC_RGMII2_RD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_RX_CTL_ALT0_ENET2_RX_EN = 0,
+  IMX_IOMUXC_RGMII2_RX_CTL_ALT5_GPIO5_IO16 = 5,
+  IMX_IOMUXC_RGMII2_RX_CTL_ALT6_CSI2_DATA06 = 6,
+} IMX_IOMUXC_RGMII2_RX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_RXC_ALT0_ENET2_RGMII_RXC = 0,
+  IMX_IOMUXC_RGMII2_RXC_ALT1_ENET2_RX_ER = 1,
+  IMX_IOMUXC_RGMII2_RXC_ALT5_GPIO5_IO17 = 5,
+  IMX_IOMUXC_RGMII2_RXC_ALT6_CSI2_DATA07 = 6,
+} IMX_IOMUXC_RGMII2_RXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_TD0_ALT0_ENET2_TX_DATA0 = 0,
+  IMX_IOMUXC_RGMII2_TD0_ALT2_SAI1_RX_SYNC = 2,
+  IMX_IOMUXC_RGMII2_TD0_ALT3_PWM8_OUT = 3,
+  IMX_IOMUXC_RGMII2_TD0_ALT5_GPIO5_IO18 = 5,
+  IMX_IOMUXC_RGMII2_TD0_ALT6_CSI2_DATA08 = 6,
+} IMX_IOMUXC_RGMII2_TD0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_TD1_ALT0_ENET2_TX_DATA1 = 0,
+  IMX_IOMUXC_RGMII2_TD1_ALT2_SAI1_RX_BCLK = 2,
+  IMX_IOMUXC_RGMII2_TD1_ALT3_PWM7_OUT = 3,
+  IMX_IOMUXC_RGMII2_TD1_ALT5_GPIO5_IO19 = 5,
+  IMX_IOMUXC_RGMII2_TD1_ALT6_CSI2_DATA09 = 6,
+} IMX_IOMUXC_RGMII2_TD1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_TD2_ALT0_ENET2_TX_DATA2 = 0,
+  IMX_IOMUXC_RGMII2_TD2_ALT2_SAI1_TX_SYNC = 2,
+  IMX_IOMUXC_RGMII2_TD2_ALT3_PWM6_OUT = 3,
+  IMX_IOMUXC_RGMII2_TD2_ALT5_GPIO5_IO20 = 5,
+  IMX_IOMUXC_RGMII2_TD2_ALT6_CSI2_VSYNC = 6,
+} IMX_IOMUXC_RGMII2_TD2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_TD3_ALT0_ENET2_TX_DATA3 = 0,
+  IMX_IOMUXC_RGMII2_TD3_ALT2_SAI1_TX_BCLK = 2,
+  IMX_IOMUXC_RGMII2_TD3_ALT3_PWM5_OUT = 3,
+  IMX_IOMUXC_RGMII2_TD3_ALT5_GPIO5_IO21 = 5,
+  IMX_IOMUXC_RGMII2_TD3_ALT6_CSI2_HSYNC = 6,
+} IMX_IOMUXC_RGMII2_TD3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_TX_CTL_ALT0_ENET2_TX_EN = 0,
+  IMX_IOMUXC_RGMII2_TX_CTL_ALT2_SAI1_RX_DATA0 = 2,
+  IMX_IOMUXC_RGMII2_TX_CTL_ALT5_GPIO5_IO22 = 5,
+  IMX_IOMUXC_RGMII2_TX_CTL_ALT6_CSI2_FIELD = 6,
+  IMX_IOMUXC_RGMII2_TX_CTL_ALT7_JTAG_DE_B = 7,
+} IMX_IOMUXC_RGMII2_TX_CTL_ALT;
+
+typedef enum {
+  IMX_IOMUXC_RGMII2_TXC_ALT0_ENET2_RGMII_TXC = 0,
+  IMX_IOMUXC_RGMII2_TXC_ALT1_ENET2_TX_ER = 1,
+  IMX_IOMUXC_RGMII2_TXC_ALT2_SAI1_TX_DATA0 = 2,
+  IMX_IOMUXC_RGMII2_TXC_ALT5_GPIO5_IO23 = 5,
+  IMX_IOMUXC_RGMII2_TXC_ALT6_CSI2_PIXCLK = 6,
+} IMX_IOMUXC_RGMII2_TXC_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_CLK_ALT0_SD1_CLK = 0,
+  IMX_IOMUXC_SD1_CLK_ALT1_AUD5_RXFS = 1,
+  IMX_IOMUXC_SD1_CLK_ALT2_WDOG2_B = 2,
+  IMX_IOMUXC_SD1_CLK_ALT3_GPT_CLK = 3,
+  IMX_IOMUXC_SD1_CLK_ALT4_WDOG2_RST_B_DEB = 4,
+  IMX_IOMUXC_SD1_CLK_ALT5_GPIO6_IO00 = 5,
+  IMX_IOMUXC_SD1_CLK_ALT6_ENET2_1588_EVENT1_OUT = 6,
+} IMX_IOMUXC_SD1_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_CMD_ALT0_SD1_CMD = 0,
+  IMX_IOMUXC_SD1_CMD_ALT1_AUD5_RXC = 1,
+  IMX_IOMUXC_SD1_CMD_ALT2_WDOG1_B = 2,
+  IMX_IOMUXC_SD1_CMD_ALT3_GPT_COMPARE1 = 3,
+  IMX_IOMUXC_SD1_CMD_ALT4_WDOG1_RST_B_DEB = 4,
+  IMX_IOMUXC_SD1_CMD_ALT5_GPIO6_IO01 = 5,
+  IMX_IOMUXC_SD1_CMD_ALT6_ENET2_1588_EVENT1_IN = 6,
+  IMX_IOMUXC_SD1_CMD_ALT7_CCM_CLKO1 = 7,
+} IMX_IOMUXC_SD1_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DATA0_ALT0_SD1_DATA0 = 0,
+  IMX_IOMUXC_SD1_DATA0_ALT1_AUD5_RXD = 1,
+  IMX_IOMUXC_SD1_DATA0_ALT3_GPT_CAPTURE1 = 3,
+  IMX_IOMUXC_SD1_DATA0_ALT4_UART2_RX_DATA = 4,
+  IMX_IOMUXC_SD1_DATA0_ALT5_GPIO6_IO02 = 5,
+  IMX_IOMUXC_SD1_DATA0_ALT6_ENET1_1588_EVENT1_IN = 6,
+} IMX_IOMUXC_SD1_DATA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DATA1_ALT0_SD1_DATA1 = 0,
+  IMX_IOMUXC_SD1_DATA1_ALT1_AUD5_TXC = 1,
+  IMX_IOMUXC_SD1_DATA1_ALT2_PWM4_OUT = 2,
+  IMX_IOMUXC_SD1_DATA1_ALT3_GPT_CAPTURE2 = 3,
+  IMX_IOMUXC_SD1_DATA1_ALT4_UART2_TX_DATA = 4,
+  IMX_IOMUXC_SD1_DATA1_ALT5_GPIO6_IO03 = 5,
+  IMX_IOMUXC_SD1_DATA1_ALT6_ENET1_1588_EVENT1_OUT = 6,
+  IMX_IOMUXC_SD1_DATA1_ALT7_CCM_CLKO2 = 7,
+} IMX_IOMUXC_SD1_DATA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DATA2_ALT0_SD1_DATA2 = 0,
+  IMX_IOMUXC_SD1_DATA2_ALT1_AUD5_TXFS = 1,
+  IMX_IOMUXC_SD1_DATA2_ALT2_PWM3_OUT = 2,
+  IMX_IOMUXC_SD1_DATA2_ALT3_GPT_COMPARE2 = 3,
+  IMX_IOMUXC_SD1_DATA2_ALT4_UART2_CTS_B = 4,
+  IMX_IOMUXC_SD1_DATA2_ALT5_GPIO6_IO04 = 5,
+  IMX_IOMUXC_SD1_DATA2_ALT6_ECSPI4_RDY = 6,
+} IMX_IOMUXC_SD1_DATA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD1_DATA3_ALT0_SD1_DATA3 = 0,
+  IMX_IOMUXC_SD1_DATA3_ALT1_AUD5_TXD = 1,
+  IMX_IOMUXC_SD1_DATA3_ALT2_AUD5_RXD = 2,
+  IMX_IOMUXC_SD1_DATA3_ALT3_GPT_COMPARE3 = 3,
+  IMX_IOMUXC_SD1_DATA3_ALT4_UART2_RTS_B = 4,
+  IMX_IOMUXC_SD1_DATA3_ALT5_GPIO6_IO05 = 5,
+  IMX_IOMUXC_SD1_DATA3_ALT6_ECSPI4_SS1 = 6,
+  IMX_IOMUXC_SD1_DATA3_ALT7_CCM_PMIC_READY = 7,
+} IMX_IOMUXC_SD1_DATA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_CLK_ALT0_SD2_CLK = 0,
+  IMX_IOMUXC_SD2_CLK_ALT1_AUD6_RXFS = 1,
+  IMX_IOMUXC_SD2_CLK_ALT2_KPP_COL5 = 2,
+  IMX_IOMUXC_SD2_CLK_ALT3_ECSPI4_SCLK = 3,
+  IMX_IOMUXC_SD2_CLK_ALT4_MLB_SIG = 4,
+  IMX_IOMUXC_SD2_CLK_ALT5_GPIO6_IO06 = 5,
+  IMX_IOMUXC_SD2_CLK_ALT6_MQS_RIGHT = 6,
+  IMX_IOMUXC_SD2_CLK_ALT7_WDOG1_ANY = 7,
+} IMX_IOMUXC_SD2_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_CMD_ALT0_SD2_CMD = 0,
+  IMX_IOMUXC_SD2_CMD_ALT1_AUD6_RXC = 1,
+  IMX_IOMUXC_SD2_CMD_ALT2_KPP_ROW5 = 2,
+  IMX_IOMUXC_SD2_CMD_ALT3_ECSPI4_MOSI = 3,
+  IMX_IOMUXC_SD2_CMD_ALT4_MLB_CLK = 4,
+  IMX_IOMUXC_SD2_CMD_ALT5_GPIO6_IO07 = 5,
+  IMX_IOMUXC_SD2_CMD_ALT6_MQS_LEFT = 6,
+  IMX_IOMUXC_SD2_CMD_ALT7_WDOG3_B = 7,
+} IMX_IOMUXC_SD2_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DATA0_ALT0_SD2_DATA0 = 0,
+  IMX_IOMUXC_SD2_DATA0_ALT1_AUD6_RXD = 1,
+  IMX_IOMUXC_SD2_DATA0_ALT2_KPP_ROW7 = 2,
+  IMX_IOMUXC_SD2_DATA0_ALT3_PWM1_OUT = 3,
+  IMX_IOMUXC_SD2_DATA0_ALT4_I2C4_SDA = 4,
+  IMX_IOMUXC_SD2_DATA0_ALT5_GPIO6_IO08 = 5,
+  IMX_IOMUXC_SD2_DATA0_ALT6_ECSPI4_SS3 = 6,
+  IMX_IOMUXC_SD2_DATA0_ALT7_UART4_RX_DATA = 7,
+} IMX_IOMUXC_SD2_DATA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DATA1_ALT0_SD2_DATA1 = 0,
+  IMX_IOMUXC_SD2_DATA1_ALT1_AUD6_TXC = 1,
+  IMX_IOMUXC_SD2_DATA1_ALT2_KPP_COL7 = 2,
+  IMX_IOMUXC_SD2_DATA1_ALT3_PWM2_OUT = 3,
+  IMX_IOMUXC_SD2_DATA1_ALT4_I2C4_SCL = 4,
+  IMX_IOMUXC_SD2_DATA1_ALT5_GPIO6_IO09 = 5,
+  IMX_IOMUXC_SD2_DATA1_ALT6_ECSPI4_SS2 = 6,
+  IMX_IOMUXC_SD2_DATA1_ALT7_UART4_TX_DATA = 7,
+} IMX_IOMUXC_SD2_DATA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DATA2_ALT0_SD2_DATA2 = 0,
+  IMX_IOMUXC_SD2_DATA2_ALT1_AUD6_TXFS = 1,
+  IMX_IOMUXC_SD2_DATA2_ALT2_KPP_ROW6 = 2,
+  IMX_IOMUXC_SD2_DATA2_ALT3_ECSPI4_SS0 = 3,
+  IMX_IOMUXC_SD2_DATA2_ALT4_SDMA_EXT_EVENT0 = 4,
+  IMX_IOMUXC_SD2_DATA2_ALT5_GPIO6_IO10 = 5,
+  IMX_IOMUXC_SD2_DATA2_ALT6_SPDIF_OUT = 6,
+  IMX_IOMUXC_SD2_DATA2_ALT7_UART6_RX_DATA = 7,
+} IMX_IOMUXC_SD2_DATA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD2_DATA3_ALT0_SD2_DATA3 = 0,
+  IMX_IOMUXC_SD2_DATA3_ALT1_AUD6_TXD = 1,
+  IMX_IOMUXC_SD2_DATA3_ALT2_KPP_COL6 = 2,
+  IMX_IOMUXC_SD2_DATA3_ALT3_ECSPI4_MISO = 3,
+  IMX_IOMUXC_SD2_DATA3_ALT4_MLB_DATA = 4,
+  IMX_IOMUXC_SD2_DATA3_ALT5_GPIO6_IO11 = 5,
+  IMX_IOMUXC_SD2_DATA3_ALT6_SPDIF_IN = 6,
+  IMX_IOMUXC_SD2_DATA3_ALT7_UART6_TX_DATA = 7,
+} IMX_IOMUXC_SD2_DATA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_CLK_ALT0_SD4_CLK = 0,
+  IMX_IOMUXC_SD4_CLK_ALT1_NAND_DATA15 = 1,
+  IMX_IOMUXC_SD4_CLK_ALT2_ECSPI2_MISO = 2,
+  IMX_IOMUXC_SD4_CLK_ALT3_AUD3_RXFS = 3,
+  IMX_IOMUXC_SD4_CLK_ALT4_LCD2_DATA13 = 4,
+  IMX_IOMUXC_SD4_CLK_ALT5_GPIO6_IO12 = 5,
+  IMX_IOMUXC_SD4_CLK_ALT6_ECSPI3_SS2 = 6,
+} IMX_IOMUXC_SD4_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_CMD_ALT0_SD4_CMD = 0,
+  IMX_IOMUXC_SD4_CMD_ALT1_NAND_DATA14 = 1,
+  IMX_IOMUXC_SD4_CMD_ALT2_ECSPI2_MOSI = 2,
+  IMX_IOMUXC_SD4_CMD_ALT3_AUD3_RXC = 3,
+  IMX_IOMUXC_SD4_CMD_ALT4_LCD2_DATA14 = 4,
+  IMX_IOMUXC_SD4_CMD_ALT5_GPIO6_IO13 = 5,
+  IMX_IOMUXC_SD4_CMD_ALT6_ECSPI3_SS1 = 6,
+} IMX_IOMUXC_SD4_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA0_ALT0_SD4_DATA0 = 0,
+  IMX_IOMUXC_SD4_DATA0_ALT1_NAND_DATA10 = 1,
+  IMX_IOMUXC_SD4_DATA0_ALT2_ECSPI2_SS0 = 2,
+  IMX_IOMUXC_SD4_DATA0_ALT3_AUD3_RXD = 3,
+  IMX_IOMUXC_SD4_DATA0_ALT4_LCD2_DATA12 = 4,
+  IMX_IOMUXC_SD4_DATA0_ALT5_GPIO6_IO14 = 5,
+  IMX_IOMUXC_SD4_DATA0_ALT6_ECSPI3_SS3 = 6,
+} IMX_IOMUXC_SD4_DATA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA1_ALT0_SD4_DATA1 = 0,
+  IMX_IOMUXC_SD4_DATA1_ALT1_NAND_DATA11 = 1,
+  IMX_IOMUXC_SD4_DATA1_ALT2_ECSPI2_SCLK = 2,
+  IMX_IOMUXC_SD4_DATA1_ALT3_AUD3_TXC = 3,
+  IMX_IOMUXC_SD4_DATA1_ALT4_LCD2_DATA11 = 4,
+  IMX_IOMUXC_SD4_DATA1_ALT5_GPIO6_IO15 = 5,
+  IMX_IOMUXC_SD4_DATA1_ALT6_ECSPI3_RDY = 6,
+} IMX_IOMUXC_SD4_DATA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA2_ALT0_SD4_DATA2 = 0,
+  IMX_IOMUXC_SD4_DATA2_ALT1_NAND_DATA12 = 1,
+  IMX_IOMUXC_SD4_DATA2_ALT2_I2C2_SDA = 2,
+  IMX_IOMUXC_SD4_DATA2_ALT3_AUD3_TXFS = 3,
+  IMX_IOMUXC_SD4_DATA2_ALT4_LCD2_DATA10 = 4,
+  IMX_IOMUXC_SD4_DATA2_ALT5_GPIO6_IO16 = 5,
+  IMX_IOMUXC_SD4_DATA2_ALT6_ECSPI2_SS3 = 6,
+} IMX_IOMUXC_SD4_DATA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA3_ALT0_SD4_DATA3 = 0,
+  IMX_IOMUXC_SD4_DATA3_ALT1_NAND_DATA13 = 1,
+  IMX_IOMUXC_SD4_DATA3_ALT2_I2C2_SCL = 2,
+  IMX_IOMUXC_SD4_DATA3_ALT3_AUD3_TXD = 3,
+  IMX_IOMUXC_SD4_DATA3_ALT4_LCD2_DATA09 = 4,
+  IMX_IOMUXC_SD4_DATA3_ALT5_GPIO6_IO17 = 5,
+  IMX_IOMUXC_SD4_DATA3_ALT6_ECSPI2_RDY = 6,
+} IMX_IOMUXC_SD4_DATA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA4_ALT0_SD4_DATA4 = 0,
+  IMX_IOMUXC_SD4_DATA4_ALT1_NAND_DATA09 = 1,
+  IMX_IOMUXC_SD4_DATA4_ALT2_UART5_RX_DATA = 2,
+  IMX_IOMUXC_SD4_DATA4_ALT3_ECSPI3_SCLK = 3,
+  IMX_IOMUXC_SD4_DATA4_ALT4_LCD2_DATA08 = 4,
+  IMX_IOMUXC_SD4_DATA4_ALT5_GPIO6_IO18 = 5,
+  IMX_IOMUXC_SD4_DATA4_ALT6_SPDIF_OUT = 6,
+} IMX_IOMUXC_SD4_DATA4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA5_ALT0_SD4_DATA5 = 0,
+  IMX_IOMUXC_SD4_DATA5_ALT1_NAND_CE2_B = 1,
+  IMX_IOMUXC_SD4_DATA5_ALT2_UART5_TX_DATA = 2,
+  IMX_IOMUXC_SD4_DATA5_ALT3_ECSPI3_MOSI = 3,
+  IMX_IOMUXC_SD4_DATA5_ALT4_LCD2_DATA07 = 4,
+  IMX_IOMUXC_SD4_DATA5_ALT5_GPIO6_IO19 = 5,
+  IMX_IOMUXC_SD4_DATA5_ALT6_SPDIF_IN = 6,
+} IMX_IOMUXC_SD4_DATA5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA6_ALT0_SD4_DATA6 = 0,
+  IMX_IOMUXC_SD4_DATA6_ALT1_NAND_CE3_B = 1,
+  IMX_IOMUXC_SD4_DATA6_ALT2_UART5_RTS_B = 2,
+  IMX_IOMUXC_SD4_DATA6_ALT3_ECSPI3_MISO = 3,
+  IMX_IOMUXC_SD4_DATA6_ALT4_LCD2_DATA06 = 4,
+  IMX_IOMUXC_SD4_DATA6_ALT5_GPIO6_IO20 = 5,
+  IMX_IOMUXC_SD4_DATA6_ALT6_SD4_WP = 6,
+} IMX_IOMUXC_SD4_DATA6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_DATA7_ALT0_SD4_DATA7 = 0,
+  IMX_IOMUXC_SD4_DATA7_ALT1_NAND_DATA08 = 1,
+  IMX_IOMUXC_SD4_DATA7_ALT2_UART5_CTS_B = 2,
+  IMX_IOMUXC_SD4_DATA7_ALT3_ECSPI3_SS0 = 3,
+  IMX_IOMUXC_SD4_DATA7_ALT4_LCD2_DATA15 = 4,
+  IMX_IOMUXC_SD4_DATA7_ALT5_GPIO6_IO21 = 5,
+  IMX_IOMUXC_SD4_DATA7_ALT6_SD4_CD_B = 6,
+} IMX_IOMUXC_SD4_DATA7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD4_RESET_B_ALT0_SD4_RESET_B = 0,
+  IMX_IOMUXC_SD4_RESET_B_ALT1_NAND_DQS = 1,
+  IMX_IOMUXC_SD4_RESET_B_ALT2_SD4_RESET = 2,
+  IMX_IOMUXC_SD4_RESET_B_ALT3_AUDIO_CLK_OUT = 3,
+  IMX_IOMUXC_SD4_RESET_B_ALT4_LCD2_RESET = 4,
+  IMX_IOMUXC_SD4_RESET_B_ALT5_GPIO6_IO22 = 5,
+  IMX_IOMUXC_SD4_RESET_B_ALT6_LCD2_CS = 6,
+} IMX_IOMUXC_SD4_RESET_B_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_CLK_ALT0_SD3_CLK = 0,
+  IMX_IOMUXC_SD3_CLK_ALT1_UART4_CTS_B = 1,
+  IMX_IOMUXC_SD3_CLK_ALT2_ECSPI4_SCLK = 2,
+  IMX_IOMUXC_SD3_CLK_ALT3_AUD6_RXFS = 3,
+  IMX_IOMUXC_SD3_CLK_ALT4_LCD2_VSYNC = 4,
+  IMX_IOMUXC_SD3_CLK_ALT5_GPIO7_IO00 = 5,
+  IMX_IOMUXC_SD3_CLK_ALT6_LCD2_BUSY = 6,
+} IMX_IOMUXC_SD3_CLK_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_CMD_ALT0_SD3_CMD = 0,
+  IMX_IOMUXC_SD3_CMD_ALT1_UART4_TX_DATA = 1,
+  IMX_IOMUXC_SD3_CMD_ALT2_ECSPI4_MOSI = 2,
+  IMX_IOMUXC_SD3_CMD_ALT3_AUD6_RXC = 3,
+  IMX_IOMUXC_SD3_CMD_ALT4_LCD2_HSYNC = 4,
+  IMX_IOMUXC_SD3_CMD_ALT5_GPIO7_IO01 = 5,
+  IMX_IOMUXC_SD3_CMD_ALT6_LCD2_RS = 6,
+} IMX_IOMUXC_SD3_CMD_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA0_ALT0_SD3_DATA0 = 0,
+  IMX_IOMUXC_SD3_DATA0_ALT1_I2C4_SCL = 1,
+  IMX_IOMUXC_SD3_DATA0_ALT2_ECSPI2_SS1 = 2,
+  IMX_IOMUXC_SD3_DATA0_ALT3_AUD6_RXD = 3,
+  IMX_IOMUXC_SD3_DATA0_ALT4_LCD2_DATA01 = 4,
+  IMX_IOMUXC_SD3_DATA0_ALT5_GPIO7_IO02 = 5,
+  IMX_IOMUXC_SD3_DATA0_ALT6_DCIC1_OUT = 6,
+} IMX_IOMUXC_SD3_DATA0_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA1_ALT0_SD3_DATA1 = 0,
+  IMX_IOMUXC_SD3_DATA1_ALT1_I2C4_SDA = 1,
+  IMX_IOMUXC_SD3_DATA1_ALT2_ECSPI2_SS2 = 2,
+  IMX_IOMUXC_SD3_DATA1_ALT3_AUD6_TXC = 3,
+  IMX_IOMUXC_SD3_DATA1_ALT4_LCD2_DATA00 = 4,
+  IMX_IOMUXC_SD3_DATA1_ALT5_GPIO7_IO03 = 5,
+  IMX_IOMUXC_SD3_DATA1_ALT6_DCIC2_OUT = 6,
+} IMX_IOMUXC_SD3_DATA1_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA2_ALT0_SD3_DATA2 = 0,
+  IMX_IOMUXC_SD3_DATA2_ALT1_UART4_RTS_B = 1,
+  IMX_IOMUXC_SD3_DATA2_ALT2_ECSPI4_SS0 = 2,
+  IMX_IOMUXC_SD3_DATA2_ALT3_AUD6_TXFS = 3,
+  IMX_IOMUXC_SD3_DATA2_ALT4_LCD2_CLK = 4,
+  IMX_IOMUXC_SD3_DATA2_ALT5_GPIO7_IO04 = 5,
+  IMX_IOMUXC_SD3_DATA2_ALT6_LCD2_WR_RWN = 6,
+} IMX_IOMUXC_SD3_DATA2_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA3_ALT0_SD3_DATA3 = 0,
+  IMX_IOMUXC_SD3_DATA3_ALT1_UART4_RX_DATA = 1,
+  IMX_IOMUXC_SD3_DATA3_ALT2_ECSPI4_MISO = 2,
+  IMX_IOMUXC_SD3_DATA3_ALT3_AUD6_TXD = 3,
+  IMX_IOMUXC_SD3_DATA3_ALT4_LCD2_ENABLE = 4,
+  IMX_IOMUXC_SD3_DATA3_ALT5_GPIO7_IO05 = 5,
+  IMX_IOMUXC_SD3_DATA3_ALT6_LCD2_RD_E = 6,
+} IMX_IOMUXC_SD3_DATA3_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA4_ALT0_SD3_DATA4 = 0,
+  IMX_IOMUXC_SD3_DATA4_ALT1_CAN2_RX = 1,
+  IMX_IOMUXC_SD3_DATA4_ALT3_UART3_RX_DATA = 3,
+  IMX_IOMUXC_SD3_DATA4_ALT4_LCD2_DATA03 = 4,
+  IMX_IOMUXC_SD3_DATA4_ALT5_GPIO7_IO06 = 5,
+  IMX_IOMUXC_SD3_DATA4_ALT6_ENET2_1588_EVENT0_IN = 6,
+} IMX_IOMUXC_SD3_DATA4_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA5_ALT0_SD3_DATA5 = 0,
+  IMX_IOMUXC_SD3_DATA5_ALT1_CAN1_TX = 1,
+  IMX_IOMUXC_SD3_DATA5_ALT3_UART3_TX_DATA = 3,
+  IMX_IOMUXC_SD3_DATA5_ALT4_LCD2_DATA02 = 4,
+  IMX_IOMUXC_SD3_DATA5_ALT5_GPIO7_IO07 = 5,
+  IMX_IOMUXC_SD3_DATA5_ALT6_ENET2_1588_EVENT0_OUT = 6,
+} IMX_IOMUXC_SD3_DATA5_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA6_ALT0_SD3_DATA6 = 0,
+  IMX_IOMUXC_SD3_DATA6_ALT1_CAN2_TX = 1,
+  IMX_IOMUXC_SD3_DATA6_ALT3_UART3_RTS_B = 3,
+  IMX_IOMUXC_SD3_DATA6_ALT4_LCD2_DATA04 = 4,
+  IMX_IOMUXC_SD3_DATA6_ALT5_GPIO7_IO08 = 5,
+  IMX_IOMUXC_SD3_DATA6_ALT6_ENET1_1588_EVENT0_OUT = 6,
+} IMX_IOMUXC_SD3_DATA6_ALT;
+
+typedef enum {
+  IMX_IOMUXC_SD3_DATA7_ALT0_SD3_DATA7 = 0,
+  IMX_IOMUXC_SD3_DATA7_ALT1_CAN1_RX = 1,
+  IMX_IOMUXC_SD3_DATA7_ALT3_UART3_CTS_B = 3,
+  IMX_IOMUXC_SD3_DATA7_ALT4_LCD2_DATA05 = 4,
+  IMX_IOMUXC_SD3_DATA7_ALT5_GPIO7_IO09 = 5,
+  IMX_IOMUXC_SD3_DATA7_ALT6_ENET1_1588_EVENT0_IN = 6,
+} IMX_IOMUXC_SD3_DATA7_ALT;
+
+typedef enum {
+  IMX_IOMUXC_USB_H_DATA_ALT0_USB_H_DATA = 0,
+  IMX_IOMUXC_USB_H_DATA_ALT1_PWM2_OUT = 1,
+  IMX_IOMUXC_USB_H_DATA_ALT2_XTALOSC_REF_CLK_24M = 2,
+  IMX_IOMUXC_USB_H_DATA_ALT3_I2C4_SDA = 3,
+  IMX_IOMUXC_USB_H_DATA_ALT4_WDOG3_B = 4,
+  IMX_IOMUXC_USB_H_DATA_ALT5_GPIO7_IO10 = 5,
+} IMX_IOMUXC_USB_H_DATA_ALT;
+
+typedef enum {
+  IMX_IOMUXC_USB_H_STROBE_ALT0_USB_H_STROBE = 0,
+  IMX_IOMUXC_USB_H_STROBE_ALT1_PWM1_OUT = 1,
+  IMX_IOMUXC_USB_H_STROBE_ALT2_XTALOSC_REF_CLK_32K = 2,
+  IMX_IOMUXC_USB_H_STROBE_ALT3_I2C4_SCL = 3,
+  IMX_IOMUXC_USB_H_STROBE_ALT4_WDOG3_RST_B_DEB = 4,
+  IMX_IOMUXC_USB_H_STROBE_ALT5_GPIO7_IO11 = 5,
+} IMX_IOMUXC_USB_H_STROBE_ALT;
+
+#endif // _IMX6_IOMUX_SX_H_
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h b/Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h
new file mode 100644
index 000000000000..fb49330d2130
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h
@@ -0,0 +1,332 @@
+/** @file
+*
+*  Header defining the iMX6DQ constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX6_DQ_H__
+#define __IMX6_DQ_H__
+
+#include "iMX6_common.h"
+
+#pragma pack(push, 1)
+
+// IOMUX Controller (IOMUXC)
+#define IMX_IOMUXC_TZASC1_BYP   0x1
+#define IMX_IOMUXC_TZASC2_BYP   0x2
+
+// IOMUXC Registers
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL0      0x020E01F8
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0      0x020E01FC
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL1      0x020E0200
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1      0x020E0204
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL2      0x020E0208
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2      0x020E020C
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL3      0x020E0210
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3      0x020E0214
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL4      0x020E0218
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4      0x020E021C
+
+// Define base address of Select Input registers to be one word
+// less than the minimum value so that a valid Select Input value
+// is non-zero.
+#define IOMUXC_SELECT_INPUT_BASE_ADDRESS 0x20E07AC
+
+typedef enum {
+  IOMUXC_ASRC_ASRCK_CLOCK_6_SELECT_INPUT    = 0x20E07B0,
+  IOMUXC_AUD4_INPUT_DA_AMX_SELECT_INPUT     = 0x20E07B4,
+  IOMUXC_AUD4_INPUT_DB_AMX_SELECT_INPUT     = 0x20E07B8,
+  IOMUXC_AUD4_INPUT_RXCLK_AMX_SELECT_INPUT  = 0x20E07BC,
+  IOMUXC_AUD4_INPUT_RXFS_AMX_SELECT_INPUT   = 0x20E07C0,
+  IOMUXC_AUD4_INPUT_TXCLK_AMX_SELECT_INPUT  = 0x20E07C4,
+  IOMUXC_AUD4_INPUT_TXFS_AMX_SELECT_INPUT   = 0x20E07C8,
+  IOMUXC_AUD5_INPUT_DA_AMX_SELECT_INPUT     = 0x20E07CC,
+  IOMUXC_AUD5_INPUT_DB_AMX_SELECT_INPUT     = 0x20E07D0,
+  IOMUXC_AUD5_INPUT_RXCLK_AMX_SELECT_INPUT  = 0x20E07D4,
+  IOMUXC_AUD5_INPUT_RXFS_AMX_SELECT_INPUT   = 0x20E07D8,
+  IOMUXC_AUD5_INPUT_TXCLK_AMX_SELECT_INPUT  = 0x20E07DC,
+  IOMUXC_AUD5_INPUT_TXFS_AMX_SELECT_INPUT   = 0x20E07E0,
+  IOMUXC_FLEXCAN1_RX_SELECT_INPUT           = 0x20E07E4,
+  IOMUXC_FLEXCAN2_RX_SELECT_INPUT           = 0x20E07E8,
+  IOMUXC_CCM_PMIC_READY_SELECT_INPUT        = 0x20E07F0,
+  IOMUXC_ECSPI1_CSPI_CLK_IN_SELECT_INPUT    = 0x20E07F4,
+  IOMUXC_ECSPI1_MISO_SELECT_INPUT           = 0x20E07F8,
+  IOMUXC_ECSPI1_MOSI_SELECT_INPUT           = 0x20E07FC,
+  IOMUXC_ECSPI1_SS0_SELECT_INPUT            = 0x20E0800,
+  IOMUXC_ECSPI1_SS1_SELECT_INPUT            = 0x20E0804,
+  IOMUXC_ECSPI1_SS2_SELECT_INPUT            = 0x20E0808,
+  IOMUXC_ECSPI1_SS3_SELECT_INPUT            = 0x20E080C,
+  IOMUXC_ECSPI2_CSPI_CLK_IN_SELECT_INPUT    = 0x20E0810,
+  IOMUXC_ECSPI2_MISO_SELECT_INPUT           = 0x20E0814,
+  IOMUXC_ECSPI2_MOSI_SELECT_INPUT           = 0x20E0818,
+  IOMUXC_ECSPI2_SS0_SELECT_INPUT            = 0x20E081C,
+  IOMUXC_ECSPI2_SS1_SELECT_INPUT            = 0x20E0820,
+  IOMUXC_ECSPI4_SS0_SELECT_INPUT            = 0x20E0824,
+  IOMUXC_ECSPI5_CSPI_CLK_IN_SELECT_INPUT    = 0x20E0828,
+  IOMUXC_ECSPI5_MISO_SELECT_INPUT           = 0x20E082C,
+  IOMUXC_ECSPI5_MOSI_SELECT_INPUT           = 0x20E0830,
+  IOMUXC_ECSPI5_SS0_SELECT_INPUT            = 0x20E0834,
+  IOMUXC_ECSPI5_SS1_SELECT_INPUT            = 0x20E0838,
+  IOMUXC_ENET_REF_CLK_SELECT_INPUT          = 0x20E083C,
+  IOMUXC_ENET_MAC0_MDIO_SELECT_INPUT        = 0x20E0840,
+  IOMUXC_ENET_MAC0_RX_CLK_SELECT_INPUT      = 0x20E0844,
+  IOMUXC_ENET_MAC0_RX_DATA0_SELECT_INPUT    = 0x20E0848,
+  IOMUXC_ENET_MAC0_RX_DATA1_SELECT_INPUT    = 0x20E084C,
+  IOMUXC_ENET_MAC0_RX_DATA2_SELECT_INPUT    = 0x20E0850,
+  IOMUXC_ENET_MAC0_RX_DATA3_SELECT_INPUT    = 0x20E0854,
+  IOMUXC_ENET_MAC0_RX_EN_SELECT_INPUT       = 0x20E0858,
+  IOMUXC_ESAI_RX_FS_SELECT_INPUT            = 0x20E085C,
+  IOMUXC_ESAI_TX_FS_SELECT_INPUT            = 0x20E0860,
+  IOMUXC_ESAI_RX_HF_CLK_SELECT_INPUT        = 0x20E0864,
+  IOMUXC_ESAI_TX_HF_CLK_SELECT_INPUT        = 0x20E0868,
+  IOMUXC_ESAI_RX_CLK_SELECT_INPUT           = 0x20E086C,
+  IOMUXC_ESAI_TX_CLK_SELECT_INPUT           = 0x20E0870,
+  IOMUXC_ESAI_SDO0_SELECT_INPUT             = 0x20E0874,
+  IOMUXC_ESAI_SDO1_SELECT_INPUT             = 0x20E0878,
+  IOMUXC_ESAI_SDO2_SDI3_SELECT_INPUT        = 0x20E087C,
+  IOMUXC_ESAI_SDO3_SDI2_SELECT_INPUT        = 0x20E0880,
+  IOMUXC_ESAI_SDO4_SDI1_SELECT_INPUT        = 0x20E0884,
+  IOMUXC_ESAI_SDO5_SDI0_SELECT_INPUT        = 0x20E0888,
+  IOMUXC_HDMI_ICECIN_SELECT_INPUT           = 0x20E088C,
+  IOMUXC_HDMI_II2C_CLKIN_SELECT_INPUT       = 0x20E0890,
+  IOMUXC_HDMI_II2C_DATAIN_SELECT_INPUT      = 0x20E0894,
+  IOMUXC_I2C1_SCL_IN_SELECT_INPUT           = 0x20E0898,
+  IOMUXC_I2C1_SDA_IN_SELECT_INPUT           = 0x20E089C,
+  IOMUXC_I2C2_SCL_IN_SELECT_INPUT           = 0x20E08A0,
+  IOMUXC_I2C2_SDA_IN_SELECT_INPUT           = 0x20E08A4,
+  IOMUXC_I2C3_SCL_IN_SELECT_INPUT           = 0x20E08A8,
+  IOMUXC_I2C3_SDA_IN_SELECT_INPUT           = 0x20E08AC,
+  IOMUXC_IPU2_SENS1_DATA10_SELECT_INPUT     = 0x20E08B0,
+  IOMUXC_IPU2_SENS1_DATA11_SELECT_INPUT     = 0x20E08B4,
+  IOMUXC_IPU2_SENS1_DATA12_SELECT_INPUT     = 0x20E08B8,
+  IOMUXC_IPU2_SENS1_DATA13_SELECT_INPUT     = 0x20E08BC,
+  IOMUXC_IPU2_SENS1_DATA14_SELECT_INPUT     = 0x20E08C0,
+  IOMUXC_IPU2_SENS1_DATA15_SELECT_INPUT     = 0x20E08C4,
+  IOMUXC_IPU2_SENS1_DATA16_SELECT_INPUT     = 0x20E08C8,
+  IOMUXC_IPU2_SENS1_DATA17_SELECT_INPUT     = 0x20E08CC,
+  IOMUXC_IPU2_SENS1_DATA18_SELECT_INPUT     = 0x20E08D0,
+  IOMUXC_IPU2_SENS1_DATA19_SELECT_INPUT     = 0x20E08D4,
+  IOMUXC_IPU2_SENS1_DATA_EN_SELECT_INPUT    = 0x20E08D8,
+  IOMUXC_IPU2_SENS1_HSYNC_SELECT_INPUT      = 0x20E08DC,
+  IOMUXC_IPU2_SENS1_PIX_CLK_SELECT_INPUT    = 0x20E08E0,
+  IOMUXC_IPU2_SENS1_VSYNC_SELECT_INPUT      = 0x20E08E4,
+  IOMUXC_KEY_COL5_SELECT_INPUT              = 0x20E08E8,
+  IOMUXC_KEY_COL6_SELECT_INPUT              = 0x20E08EC,
+  IOMUXC_KEY_COL7_SELECT_INPUT              = 0x20E08F0,
+  IOMUXC_KEY_ROW5_SELECT_INPUT              = 0x20E08F4,
+  IOMUXC_KEY_ROW6_SELECT_INPUT              = 0x20E08F8,
+  IOMUXC_KEY_ROW7_SELECT_INPUT              = 0x20E08FC,
+  IOMUXC_MLB_MLB_CLK_IN_SELECT_INPUT        = 0x20E0900,
+  IOMUXC_MLB_MLB_DATA_IN_SELECT_INPUT       = 0x20E0904,
+  IOMUXC_MLB_MLB_SIG_IN_SELECT_INPUT        = 0x20E0908,
+  IOMUXC_SDMA_EVENTS14_SELECT_INPUT         = 0x20E090C,
+  IOMUXC_SDMA_EVENTS47_SELECT_INPUT         = 0x20E0910,
+  IOMUXC_SPDIF_SPDIF_IN1_SELECT_INPUT       = 0x20E0914,
+  IOMUXC_SPDIF_TX_CLK2_SELECT_INPUT         = 0x20E0918,
+  IOMUXC_UART1_UART_RTS_B_SELECT_INPUT      = 0x20E091C,
+  IOMUXC_UART1_UART_RX_DATA_SELECT_INPUT    = 0x20E0920,
+  IOMUXC_UART2_UART_RTS_B_SELECT_INPUT      = 0x20E0924,
+  IOMUXC_UART2_UART_RX_DATA_SELECT_INPUT    = 0x20E0928,
+  IOMUXC_UART3_UART_RTS_B_SELECT_INPUT      = 0x20E092C,
+  IOMUXC_UART3_UART_RX_DATA_SELECT_INPUT    = 0x20E0930,
+  IOMUXC_UART4_UART_RTS_B_SELECT_INPUT      = 0x20E0934,
+  IOMUXC_UART4_UART_RX_DATA_SELECT_INPUT    = 0x20E0938,
+  IOMUXC_UART5_UART_RTS_B_SELECT_INPUT      = 0x20E093C,
+  IOMUXC_UART5_UART_RX_DATA_SELECT_INPUT    = 0x20E0940,
+  IOMUXC_USB_OTG_OC_SELECT_INPUT            = 0x20E0944,
+  IOMUXC_USB_H1_OC_SELECT_INPUT             = 0x20E0948,
+  IOMUXC_USDHC1_WP_ON_SELECT_INPUT          = 0x20E094C,
+  IOMUXC_SELECT_INPUT_UPPER_BOUND           = IOMUXC_USDHC1_WP_ON_SELECT_INPUT,
+} IMX_INPUT_SELECT;
+
+typedef struct {
+  UINT32 GPR0;                          // 0x00 IOMUXC_GPR0
+  UINT32 GPR1;                          // 0x04 IOMUXC_GPR1
+  UINT32 GPR2;                          // 0x08 IOMUXC_GPR2
+  UINT32 GPR3;                          // 0x0C IOMUXC_GPR3
+  UINT32 GPR4;                          // 0x10 IOMUXC_GPR4
+  UINT32 GPR5;                          // 0x14 IOMUXC_GPR5
+  UINT32 GPR6;                          // 0x18 IOMUXC_GPR6
+  UINT32 GPR7;                          // 0x1C IOMUXC_GPR7
+  UINT32 GPR8;                          // 0x20 IOMUXC_GPR8
+  UINT32 GPR9;                          // 0x24 IOMUXC_GPR9
+  UINT32 GPR10;                         // 0x28 IOMUXC_GPR10
+  UINT32 GPR11;                         // 0x2c IOMUXC_GPR11
+  UINT32 GPR12;                         // 0x30 IOMUXC_GPR12
+  UINT32 GPR13;                         // 0x34 IOMUXC_GPR13
+  UINT32 Reserved;                      // 0x38 Reserved
+  UINT32 GPR14;                         // 0x3C IOMUXC_GPR14; see ERR006687
+} IMX_IOMUXC_GPR_REGISTERS;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ACT_CS0                : 1;  // 0
+    UINT32 ADDRS0_10              : 2;  // 1-2
+    UINT32 ACT_CS1                : 1;  // 3
+    UINT32 ADDRS1_10              : 2;  // 4-5
+    UINT32 ACT_CS2                : 1;  // 6
+    UINT32 ADDRS2_10              : 2;  // 7-8
+    UINT32 ACT_CS3                : 1;  // 9
+    UINT32 ADDRS3_10              : 2;  // 10-11 Active Chip Select and Address Space
+    UINT32 GINT                   : 1;  // 12 Global interrupt "0" bit
+                                        //   (connected to ARM IRQ#0 and GPC)
+    UINT32 USB_OTG_ID_SEL         : 1;  // 13 ''usb_otg_id' pin iomux select control.
+    UINT32 SYS_INT                : 1;  // 14 PCIe_CTL
+    UINT32 USB_EXP_MODE           : 1;  // 15 USB Exposure mode
+    UINT32 REF_SSP_EN             : 1;  // 16 PCIe_PHY - Reference Clock Enable
+                                        //   for SS function.
+    UINT32 PU_VPU_MUX             : 1;  // 17 IPU-1/IPU-2 to VPU signals control.
+    UINT32 TEST_POWERDOWN         : 1;  // 18 PCIe_PHY - All Circuits Power-Down
+                                        //   Control Function.
+    UINT32 MIPI_IPU1_MUX          : 1;  // 19 MIPI sensor to IPU-1 mux control.
+    UINT32 MIPI_IPU2_MUX          : 1;  // 20 MIPI sensor to IPU-2 mux control
+    UINT32 ENET_CLK_SEL           : 1;  // 21 ENET TX reference clock
+    UINT32 EXC_MON                : 1;  // 22 Exclusive monitor response select
+                                        //   of illegal command
+    UINT32 reserved1              : 1;  // 23
+    UINT32 MIPI_DPI_OFF           : 1;  // 24 MIPI DPI shutdown request
+    UINT32 MIPI_COLOR_SW          : 1;  // 25 MIPI color switch control
+    UINT32 APP_REQ_ENTR_L1        : 1;  // 26 PCIe_CTL - Application Request to Enter L1
+    UINT32 APP_READY_ENTR_L23     : 1;  // 27 PCIe_CTL - Application Ready to Enter L2/3
+    UINT32 APP_REQ_EXIT_L1        : 1;  // 28 PCIe_CTL - Application Request to Exit L1
+    UINT32 reserved2              : 1;  // 29
+    UINT32 APP_CLK_REQ_N          : 1;  // 30 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Indicates that application logic is
+                                        //   ready to have reference clock removed.
+    UINT32 CFG_L1_CLK_REMOVAL_EN  : 1;  // 31 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Enable the reference clock removal
+                                        //   in L1 state.
+  };
+} IMX_IOMUXC_GPR1_REG;
+
+// USB PHY
+#define IMX_USBPHY1_BASE 0x020C9000
+#define IMX_USBPHY2_BASE 0x020CA000
+#define IMX_USBPHY_LENGTH 0x1000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ENOTG_ID_CHG_IRQ : 1;        // 0 Enable OTG_ID_CHG_IRQ.
+    UINT32 ENHOSTDISCONDETECT : 1;      // 1 For host mode, enables high-speed
+                                        //   disconnect detector.
+    UINT32 ENIRQHOSTDISCON : 1;         // 2 Enables interrupt for detection of
+                                        //   disconnection to Device when in
+                                        //   high-speed host mode.
+    UINT32 HOSTDISCONDETECT_IRQ : 1;    // 3 Indicates that the device has
+                                        //   disconnected in high-speed mode.
+    UINT32 ENDEVPLUGINDETECT : 1;       // 4 For device mode, enables 200-KOhm
+                                        //   pullups for detecting connectivity
+                                        //   to the host.
+    UINT32 DEVPLUGIN_POLARITY : 1;      // 5 For device mode interrupt generation polarity
+    UINT32 OTG_ID_CHG_IRQ : 1;          // 6 OTG ID change interrupt. Indicates
+                                        //   the value of ID pin changed.
+    UINT32 ENOTGIDDETECT : 1;           // 7 Enables circuit to detect resistance
+                                        //   of MiniAB ID pin.
+    UINT32 RESUMEIRQSTICKY : 1;         // 8 1 makes RESUME_IRQ bit a sticky bit.
+    UINT32 ENIRQRESUMEDETECT : 1;       // 9 Enables interrupt for detection of a
+                                        //   non-J state on the USB line.
+    UINT32 RESUME_IRQ : 1;              // 10 Indicates that the host is sending
+                                        //   a wake-up after suspend
+    UINT32 ENIRQDEVPLUGIN : 1;          // 11 Enables interrupt for the detection
+                                        //   of connectivity to the USB line.
+    UINT32 DEVPLUGIN_IRQ : 1;           // 12 Indicates that the device is connected
+    UINT32 DATA_ON_LRADC : 1;           // 13 Enables the LRADC to monitor USB_DP
+                                        //   and USB_DM.
+    UINT32 ENUTMILEVEL2 : 1;            // 14 Enables UTMI+ Level2.
+    UINT32 ENUTMILEVEL3 : 1;            // 15 Enables UTMI+ Level3.
+    UINT32 ENIRQWAKEUP : 1;             // 16 Enables interrupt for the wakeup events
+    UINT32 WAKEUP_IRQ : 1;              // 17 Indicates that there is a wakeup event.
+    UINT32 ENAUTO_PWRON_PLL : 1;        // 18
+    UINT32 ENAUTOCLR_CLKGATE : 1;       // 19 Enables the feature to auto-clear
+                                        //   the CLKGATE bit if there is wakeup
+                                        //   event while USB is suspended.
+    UINT32 ENAUTOCLR_PHY_PWD : 1;       // 20 Enables the feature to auto-clear
+                                        //   the PWD register bits in USBPHYx_PWD
+                                        //   if there is wakeup event while USB
+                                        //   is suspended.
+    UINT32 ENDPDMCHG_WKUP : 1;          // 21 Enables the feature to wakeup USB
+                                        //   if DP/DM is toggled when USB is suspended.
+    UINT32 ENIDCHG_WKUP : 1;            // 22 Enables the feature to wakeup USB
+                                        //   if ID is toggled when USB is suspended.
+    UINT32 ENVBUSCHG_WKUP : 1;          // 23 Enables the feature to wakeup USB
+                                        //   if VBUS is toggled when USB is suspended.
+    UINT32 FSDLL_RST_EN : 1;            // 24 Enables the feature to reset the
+                                        //   FSDLL lock detection logic at the
+                                        //   end of each TX packet.
+    UINT32 ENAUTOCLR_USBCLKGATE : 1;    // 25
+    UINT32 ENAUTOSET_USBCLKS : 1;       // 26
+    UINT32 OTG_ID_VALUE : 1;            // 27
+    UINT32 HOST_FORCE_LS_SE0 : 1;       // 28 Forces the next FS packet that is
+                                        //   transmitted to have a EOP with LS timing.
+    UINT32 UTMI_SUSPENDM : 1;           // 29 Used by the PHY to indicate a powered-down
+                                        //   state.
+    UINT32 CLKGATE : 1;                 // 30 Gate UTMI Clocks. Clear to 0 to run clocks.
+    UINT32 SFTRST : 1;                  // 31 Soft-reset the USBPHYx_PWD, USBPHYx_TX,
+                                        //   USBPHYx_RX, Set to 0 to release the
+                                        //   PHY from reset.
+  };
+} USBPHYx_CTRL_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 STEP : 16;   // 0-15 Stepping of the RTL version.
+    UINT32 MINOR : 8;   // 16-23 MINOR field of the RTL version.
+    UINT32 MAJOR : 8;   // 24-31 MAJOR field of the RTL version
+  };
+} USBPHYx_VERSION_REG;
+
+typedef struct {
+  UINT32 USBPHY_PWD;             // 0x00 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_SET;         // 0x04 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_CLR;         // 0x08 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_TOG;         // 0x0C USB PHY Power-Down Register
+  UINT32 USBPHY_TX;              // 0x10 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_SET;          // 0x14 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_CLR;          // 0x18 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_TOG;          // 0x1C USB PHY Transmitter Control Register
+  UINT32 USBPHY_RX;              // 0x20 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_SET;          // 0x24 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_CLR;          // 0x28 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_TOG;          // 0x2C USB PHY Receiver Control Register
+  UINT32 USBPHY_CTRL;            // 0x30 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_SET;        // 0x34 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_CLR;        // 0x38 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_TOG;        // 0x3C USB PHY General Control Register
+  UINT32 USBPHY_STATUS;          // 0x40 USB PHY Status Register
+  UINT32 reserved1[3];
+  UINT32 USBPHY_DEBUG;           // 0x50 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_SET;       // 0x54 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_CLR;       // 0x58 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_TOG;       // 0x5C USB PHY Debug Register
+  UINT32 USBPHY_DEBUG0_STATUS;   // 0x60 UTMI Debug Status Register 0
+  UINT32 reserved2[3];
+  UINT32 USBPHY_DEBUG1;          // 0x70 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_SET;      // 0x74 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_CLR;      // 0x78 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_TOG;      // 0x7C UTMI Debug Status Register 1
+  UINT32 USBPHY_VERSION;         // 0x80 UTMI RTL Version
+  UINT32 reserved3[3];
+  UINT32 USBPHY_IP;              // 0x90
+  UINT32 USBPHY_IP_SET;          // 0x94
+  UINT32 USBPHY_IP_CLR;          // 0x98
+  UINT32 USBPHY_IP_TOG;          // 0x9C
+} IMX_USBPHY_REGISTERS;
+
+#define IMX_USBPHY_IP_FIX   ((1 << 17) | (1 << 18))
+
+#pragma pack(pop)
+
+#endif // __IMX6_DQ_H__
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h b/Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h
new file mode 100644
index 000000000000..c3a7d59bc655
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h
@@ -0,0 +1,335 @@
+/** @file
+*
+*  Header defining the iMX6DQP constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX6_DQP_H__
+#define __IMX6_DQP_H__
+
+#include "iMX6_common.h"
+
+#pragma pack(push, 1)
+
+// IOMUX Controller (IOMUXC)
+#define IMX_IOMUXC_TZASC1_BYP   0x1
+#define IMX_IOMUXC_TZASC2_BYP   0x2
+
+// IOMUXC Registers
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL0      0x020E01F8
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0      0x020E01FC
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL1      0x020E0200
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1      0x020E0204
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL2      0x020E0208
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2      0x020E020C
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL3      0x020E0210
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3      0x020E0214
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL4      0x020E0218
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4      0x020E021C
+
+// Define base address of Select Input registers to be one word
+// less than the minimum value so that a valid Select Input value
+// is non-zero.
+#define IOMUXC_SELECT_INPUT_BASE_ADDRESS 0x20E07AC
+
+typedef enum {
+  IOMUXC_ASRC_ASRCK_CLOCK_6_SELECT_INPUT = 0x20E07B0,
+  IOMUXC_AUD4_INPUT_DA_AMX_SELECT_INPUT = 0x20E07B4,
+  IOMUXC_AUD4_INPUT_DB_AMX_SELECT_INPUT = 0x20E07B8,
+  IOMUXC_AUD4_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E07BC,
+  IOMUXC_AUD4_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E07C0,
+  IOMUXC_AUD4_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E07C4,
+  IOMUXC_AUD4_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E07C8,
+  IOMUXC_AUD5_INPUT_DA_AMX_SELECT_INPUT = 0x20E07CC,
+  IOMUXC_AUD5_INPUT_DB_AMX_SELECT_INPUT = 0x20E07D0,
+  IOMUXC_AUD5_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E07D4,
+  IOMUXC_AUD5_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E07D8,
+  IOMUXC_AUD5_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E07DC,
+  IOMUXC_AUD5_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E07E0,
+  IOMUXC_FLEXCAN1_RX_SELECT_INPUT = 0x20E07E4,
+  IOMUXC_FLEXCAN2_RX_SELECT_INPUT = 0x20E07E8,
+  IOMUXC_CCM_PMIC_READY_SELECT_INPUT = 0x20E07F0,
+  IOMUXC_ECSPI1_CSPI_CLK_IN_SELECT_INPUT = 0x20E07F4,
+  IOMUXC_ECSPI1_MISO_SELECT_INPUT = 0x20E07F8,
+  IOMUXC_ECSPI1_MOSI_SELECT_INPUT = 0x20E07FC,
+  IOMUXC_ECSPI1_SS0_SELECT_INPUT = 0x20E0800,
+  IOMUXC_ECSPI1_SS1_SELECT_INPUT = 0x20E0804,
+  IOMUXC_ECSPI1_SS2_SELECT_INPUT = 0x20E0808,
+  IOMUXC_ECSPI1_SS3_SELECT_INPUT = 0x20E080C,
+  IOMUXC_ECSPI2_CSPI_CLK_IN_SELECT_INPUT = 0x20E0810,
+  IOMUXC_ECSPI2_MISO_SELECT_INPUT = 0x20E0814,
+  IOMUXC_ECSPI2_MOSI_SELECT_INPUT = 0x20E0818,
+  IOMUXC_ECSPI2_SS0_SELECT_INPUT = 0x20E081C,
+  IOMUXC_ECSPI2_SS1_SELECT_INPUT = 0x20E0820,
+  IOMUXC_ECSPI4_SS0_SELECT_INPUT = 0x20E0824,
+  IOMUXC_ECSPI5_CSPI_CLK_IN_SELECT_INPUT = 0x20E0828,
+  IOMUXC_ECSPI5_MISO_SELECT_INPUT = 0x20E082C,
+  IOMUXC_ECSPI5_MOSI_SELECT_INPUT = 0x20E0830,
+  IOMUXC_ECSPI5_SS0_SELECT_INPUT = 0x20E0834,
+  IOMUXC_ECSPI5_SS1_SELECT_INPUT = 0x20E0838,
+  IOMUXC_ENET_REF_CLK_SELECT_INPUT = 0x20E083C,
+  IOMUXC_ENET_MAC0_MDIO_SELECT_INPUT = 0x20E0840,
+  IOMUXC_ENET_MAC0_RX_CLK_SELECT_INPUT = 0x20E0844,
+  IOMUXC_ENET_MAC0_RX_DATA0_SELECT_INPUT = 0x20E0848,
+  IOMUXC_ENET_MAC0_RX_DATA1_SELECT_INPUT = 0x20E084C,
+  IOMUXC_ENET_MAC0_RX_DATA2_SELECT_INPUT = 0x20E0850,
+  IOMUXC_ENET_MAC0_RX_DATA3_SELECT_INPUT = 0x20E0854,
+  IOMUXC_ENET_MAC0_RX_EN_SELECT_INPUT = 0x20E0858,
+  IOMUXC_ESAI_RX_FS_SELECT_INPUT = 0x20E085C,
+  IOMUXC_ESAI_TX_FS_SELECT_INPUT = 0x20E0860,
+  IOMUXC_ESAI_RX_HF_CLK_SELECT_INPUT = 0x20E0864,
+  IOMUXC_ESAI_TX_HF_CLK_SELECT_INPUT = 0x20E0868,
+  IOMUXC_ESAI_RX_CLK_SELECT_INPUT = 0x20E086C,
+  IOMUXC_ESAI_TX_CLK_SELECT_INPUT = 0x20E0870,
+  IOMUXC_ESAI_SDO0_SELECT_INPUT = 0x20E0874,
+  IOMUXC_ESAI_SDO1_SELECT_INPUT = 0x20E0878,
+  IOMUXC_ESAI_SDO2_SDI3_SELECT_INPUT = 0x20E087C,
+  IOMUXC_ESAI_SDO3_SDI2_SELECT_INPUT = 0x20E0880,
+  IOMUXC_ESAI_SDO4_SDI1_SELECT_INPUT = 0x20E0884,
+  IOMUXC_ESAI_SDO5_SDI0_SELECT_INPUT = 0x20E0888,
+  IOMUXC_HDMI_ICECIN_SELECT_INPUT = 0x20E088C,
+  IOMUXC_HDMI_II2C_CLKIN_SELECT_INPUT = 0x20E0890,
+  IOMUXC_HDMI_II2C_DATAIN_SELECT_INPUT = 0x20E0894,
+  IOMUXC_I2C1_SCL_IN_SELECT_INPUT = 0x20E0898,
+  IOMUXC_I2C1_SDA_IN_SELECT_INPUT = 0x20E089C,
+  IOMUXC_I2C2_SCL_IN_SELECT_INPUT = 0x20E08A0,
+  IOMUXC_I2C2_SDA_IN_SELECT_INPUT = 0x20E08A4,
+  IOMUXC_I2C3_SCL_IN_SELECT_INPUT = 0x20E08A8,
+  IOMUXC_I2C3_SDA_IN_SELECT_INPUT = 0x20E08AC,
+  IOMUXC_IPU2_SENS1_DATA10_SELECT_INPUT = 0x20E08B0,
+  IOMUXC_IPU2_SENS1_DATA11_SELECT_INPUT = 0x20E08B4,
+  IOMUXC_IPU2_SENS1_DATA12_SELECT_INPUT = 0x20E08B8,
+  IOMUXC_IPU2_SENS1_DATA13_SELECT_INPUT = 0x20E08BC,
+  IOMUXC_IPU2_SENS1_DATA14_SELECT_INPUT = 0x20E08C0,
+  IOMUXC_IPU2_SENS1_DATA15_SELECT_INPUT = 0x20E08C4,
+  IOMUXC_IPU2_SENS1_DATA16_SELECT_INPUT = 0x20E08C8,
+  IOMUXC_IPU2_SENS1_DATA17_SELECT_INPUT = 0x20E08CC,
+  IOMUXC_IPU2_SENS1_DATA18_SELECT_INPUT = 0x20E08D0,
+  IOMUXC_IPU2_SENS1_DATA19_SELECT_INPUT = 0x20E08D4,
+  IOMUXC_IPU2_SENS1_DATA_EN_SELECT_INPUT = 0x20E08D8,
+  IOMUXC_IPU2_SENS1_HSYNC_SELECT_INPUT = 0x20E08DC,
+  IOMUXC_IPU2_SENS1_PIX_CLK_SELECT_INPUT = 0x20E08E0,
+  IOMUXC_IPU2_SENS1_VSYNC_SELECT_INPUT = 0x20E08E4,
+  IOMUXC_KEY_COL5_SELECT_INPUT = 0x20E08E8,
+  IOMUXC_KEY_COL6_SELECT_INPUT = 0x20E08EC,
+  IOMUXC_KEY_COL7_SELECT_INPUT = 0x20E08F0,
+  IOMUXC_KEY_ROW5_SELECT_INPUT = 0x20E08F4,
+  IOMUXC_KEY_ROW6_SELECT_INPUT = 0x20E08F8,
+  IOMUXC_KEY_ROW7_SELECT_INPUT = 0x20E08FC,
+  IOMUXC_MLB_MLB_CLK_IN_SELECT_INPUT = 0x20E0900,
+  IOMUXC_MLB_MLB_DATA_IN_SELECT_INPUT = 0x20E0904,
+  IOMUXC_MLB_MLB_SIG_IN_SELECT_INPUT = 0x20E0908,
+  IOMUXC_SDMA_EVENTS14_SELECT_INPUT = 0x20E090C,
+  IOMUXC_SDMA_EVENTS47_SELECT_INPUT = 0x20E0910,
+  IOMUXC_SPDIF_SPDIF_IN1_SELECT_INPUT = 0x20E0914,
+  IOMUXC_SPDIF_TX_CLK2_SELECT_INPUT = 0x20E0918,
+  IOMUXC_UART1_UART_RTS_B_SELECT_INPUT = 0x20E091C,
+  IOMUXC_UART1_UART_RX_DATA_SELECT_INPUT = 0x20E0920,
+  IOMUXC_UART2_UART_RTS_B_SELECT_INPUT = 0x20E0924,
+  IOMUXC_UART2_UART_RX_DATA_SELECT_INPUT = 0x20E0928,
+  IOMUXC_UART3_UART_RTS_B_SELECT_INPUT = 0x20E092C,
+  IOMUXC_UART3_UART_RX_DATA_SELECT_INPUT = 0x20E0930,
+  IOMUXC_UART4_UART_RTS_B_SELECT_INPUT = 0x20E0934,
+  IOMUXC_UART4_UART_RX_DATA_SELECT_INPUT = 0x20E0938,
+  IOMUXC_UART5_UART_RTS_B_SELECT_INPUT = 0x20E093C,
+  IOMUXC_UART5_UART_RX_DATA_SELECT_INPUT = 0x20E0940,
+  IOMUXC_USB_OTG_OC_SELECT_INPUT = 0x20E0944,
+  IOMUXC_USB_H1_OC_SELECT_INPUT = 0x20E0948,
+  IOMUXC_USDHC1_WP_ON_SELECT_INPUT = 0x20E094C,
+  IOMUXC_SELECT_INPUT_UPPER_BOUND = IOMUXC_USDHC1_WP_ON_SELECT_INPUT,
+} IMX_INPUT_SELECT;
+
+typedef struct {
+  UINT32 GPR0;                          // 0x00 IOMUXC_GPR0
+  UINT32 GPR1;                          // 0x04 IOMUXC_GPR1
+  UINT32 GPR2;                          // 0x08 IOMUXC_GPR2
+  UINT32 GPR3;                          // 0x0C IOMUXC_GPR3
+  UINT32 GPR4;                          // 0x10 IOMUXC_GPR4
+  UINT32 GPR5;                          // 0x14 IOMUXC_GPR5
+  UINT32 GPR6;                          // 0x18 IOMUXC_GPR6
+  UINT32 GPR7;                          // 0x1C IOMUXC_GPR7
+  UINT32 GPR8;                          // 0x20 IOMUXC_GPR8
+  UINT32 GPR9;                          // 0x24 IOMUXC_GPR9
+  UINT32 GPR10;                         // 0x28 IOMUXC_GPR10
+  UINT32 GPR11;                         // 0x2c IOMUXC_GPR11
+  UINT32 GPR12;                         // 0x30 IOMUXC_GPR12
+  UINT32 GPR13;                         // 0x34 IOMUXC_GPR13
+  UINT32 Reserved;                      // 0x38 Reserved
+  UINT32 GPR14;                         // 0x3C IOMUXC_GPR14; see ERR006687
+} IMX_IOMUXC_GPR_REGISTERS;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ACT_CS0 : 1;                 // 0
+    UINT32 ADDRS0_10 : 2;               // 1-2
+    UINT32 ACT_CS1 : 1;                 // 3
+    UINT32 ADDRS1_10 : 2;               // 4-5
+    UINT32 ACT_CS2 : 1;                 // 6
+    UINT32 ADDRS2_10 : 2;               // 7-8
+    UINT32 ACT_CS3 : 1;                 // 9
+    UINT32 ADDRS3_10 : 2;               // 10-11 Active Chip Select and Address Space
+    UINT32 GINT : 1;                    // 12 Global interrupt "0" bit
+                                        //   (connected to ARM IRQ#0 and GPC)
+    UINT32 USB_OTG_ID_SEL : 1;          // 13 ''usb_otg_id' pin iomux select control.
+    UINT32 SYS_INT : 1;                 // 14 PCIe_CTL
+    UINT32 USB_EXP_MODE : 1;            // 15 USB Exposure mode
+    UINT32 REF_SSP_EN : 1;              // 16 PCIe_PHY - Reference Clock Enable
+                                        //   for SS function.
+    UINT32 PU_VPU_MUX : 1;              // 17 IPU-1/IPU-2 to VPU signals control.
+    UINT32 TEST_POWERDOWN : 1;          // 18 PCIe_PHY - All Circuits Power-Down
+                                        //   Control Function.
+    UINT32 MIPI_IPU1_MUX : 1;           // 19 MIPI sensor to IPU-1 mux control.
+    UINT32 MIPI_IPU2_MUX : 1;           // 20 MIPI sensor to IPU-2 mux control
+    UINT32 ENET_CLK_SEL : 1;            // 21 ENET TX reference clock
+    UINT32 EXC_MON : 1;                 // 22 Exclusive monitor response select
+                                        //   of illegal command
+    UINT32 reserved1 : 1;               // 23
+    UINT32 MIPI_DPI_OFF : 1;            // 24 MIPI DPI shutdown request
+    UINT32 MIPI_COLOR_SW : 1;           // 25 MIPI color switch control
+    UINT32 APP_REQ_ENTR_L1 : 1;         // 26 PCIe_CTL - Application Request to Enter L1
+    UINT32 APP_READY_ENTR_L23 : 1;      // 27 PCIe_CTL - Application Ready to Enter L23
+    UINT32 APP_REQ_EXIT_L1 : 1;         // 28 PCIe_CTL - Application Request to Exit L1
+    UINT32 PCIE_SW_RST : 1;             // 29 PCIe Software Reset - active high
+    UINT32 APP_CLK_REQ_N : 1;           // 30 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Indicates that application logic is
+                                        //   ready to have reference clock removed.
+    UINT32 CFG_L1_CLK_REMOVAL_EN : 1;   // 31 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Enable the reference clock removal
+                                        //   in L1 state.
+  };
+} IMX_IOMUXC_GPR1_REG;
+
+//
+// USB PHY
+//
+
+#define IMX_USBPHY1_BASE 0x020C9000
+#define IMX_USBPHY2_BASE 0x020CA000
+#define IMX_USBPHY_LENGTH 0x1000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ENOTG_ID_CHG_IRQ : 1;      // 0 Enable OTG_ID_CHG_IRQ.
+    UINT32 ENHOSTDISCONDETECT : 1;    // 1 For host mode, enables high-speed
+                                      //   disconnect detector.
+    UINT32 ENIRQHOSTDISCON : 1;       // 2 Enables interrupt for detection of
+                                      //   disconnection to Device when in
+                                      //   high-speed host mode.
+    UINT32 HOSTDISCONDETECT_IRQ : 1;  // 3 Indicates that the device has
+                                      //   disconnected in high-speed mode.
+    UINT32 ENDEVPLUGINDETECT : 1;     // 4 For device mode, enables 200-KOhm
+                                      //   pullups for detecting connectivity
+                                      //   to the host.
+    UINT32 DEVPLUGIN_POLARITY : 1;    // 5 For device mode interrupt generation polarity
+    UINT32 OTG_ID_CHG_IRQ : 1;        // 6 OTG ID change interrupt. Indicates
+                                      //   the value of ID pin changed.
+    UINT32 ENOTGIDDETECT : 1;         // 7 Enables circuit to detect resistance
+                                      //   of MiniAB ID pin.
+    UINT32 RESUMEIRQSTICKY : 1;       // 8 1 makes RESUME_IRQ bit a sticky bit.
+    UINT32 ENIRQRESUMEDETECT : 1;     // 9 Enables interrupt for detection of a
+                                      //   non-J state on the USB line.
+    UINT32 RESUME_IRQ : 1;            // 10 Indicates that the host is sending
+                                      //   a wake-up after suspend
+    UINT32 ENIRQDEVPLUGIN : 1;        // 11 Enables interrupt for the detection
+                                      //   of connectivity to the USB line.
+    UINT32 DEVPLUGIN_IRQ : 1;         // 12 Indicates that the device is connected
+    UINT32 DATA_ON_LRADC : 1;         // 13 Enables the LRADC to monitor USB_DP
+                                      //   and USB_DM.
+    UINT32 ENUTMILEVEL2 : 1;          // 14 Enables UTMI+ Level2.
+    UINT32 ENUTMILEVEL3 : 1;          // 15 Enables UTMI+ Level3.
+    UINT32 ENIRQWAKEUP : 1;           // 16 Enables interrupt for the wakeup events
+    UINT32 WAKEUP_IRQ : 1;            // 17 Indicates that there is a wakeup event.
+    UINT32 ENAUTO_PWRON_PLL : 1;      // 18
+    UINT32 ENAUTOCLR_CLKGATE : 1;     // 19 Enables the feature to auto-clear the
+                                      //   CLKGATE bit if there is wakeup event
+                                      //   while USB is suspended.
+    UINT32 ENAUTOCLR_PHY_PWD : 1;     // 20 Enables the feature to auto-clear the
+                                      //   PWD register bits in USBPHYx_PWD if
+                                      //   there is wakeup event while USB is
+                                      //   suspended
+    UINT32 ENDPDMCHG_WKUP : 1;        // 21 Enables the feature to wakeup USB
+                                      //   if DP/DM is toggled when USB is suspended
+    UINT32 ENIDCHG_WKUP : 1;          // 22 Enables the feature to wakeup USB
+                                      //   if ID is toggled when USB is suspended
+    UINT32 ENVBUSCHG_WKUP : 1;        // 23 Enables the feature to wakeup USB
+                                      //   if VBUS is toggled when USB is suspended.
+    UINT32 FSDLL_RST_EN : 1;          // 24 Enables the feature to reset the FSDLL
+                                      //   lock detection logic at the end of
+                                      //   each TX packet.
+    UINT32 ENAUTOCLR_USBCLKGATE : 1;  // 25
+    UINT32 ENAUTOSET_USBCLKS : 1;     // 26
+    UINT32 OTG_ID_VALUE : 1;          // 27
+    UINT32 HOST_FORCE_LS_SE0 : 1;     // 28 Forces the next FS packet that is
+                                      //   transmitted to have a EOP with LS timing.
+    UINT32 UTMI_SUSPENDM : 1;         // 29 Used by the PHY to indicate a
+                                      //   powered-down state.
+    UINT32 CLKGATE : 1;               // 30 Gate UTMI Clocks. Clear to 0 to run clocks.
+    UINT32 SFTRST : 1;                // 31 Soft-reset the USBPHYx_PWD, USBPHYx_TX,
+                                      //   USBPHYx_RX, Set to 0 to release the
+                                      //   PHY from reset.
+  };
+} USBPHYx_CTRL_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 STEP : 16;   // 0-15 Read-only value of the stepping of the RTL version.
+    UINT32 MINOR : 8;   // 16-23 Read-only value of the MINOR field of the RTL version.
+    UINT32 MAJOR : 8;   // 24-31 Read-only value of the MAJOR field of the RTL version
+  };
+} USBPHYx_VERSION_REG;
+
+typedef struct {
+  UINT32 USBPHY_PWD;           // 0x00 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_SET;       // 0x04 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_CLR;       // 0x08 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_TOG;       // 0x0C USB PHY Power-Down Register
+  UINT32 USBPHY_TX;            // 0x10 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_SET;        // 0x14 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_CLR;        // 0x18 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_TOG;        // 0x1C USB PHY Transmitter Control Register
+  UINT32 USBPHY_RX;            // 0x20 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_SET;        // 0x24 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_CLR;        // 0x28 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_TOG;        // 0x2C USB PHY Receiver Control Register
+  UINT32 USBPHY_CTRL;          // 0x30 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_SET;      // 0x34 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_CLR;      // 0x38 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_TOG;      // 0x3C USB PHY General Control Register
+  UINT32 USBPHY_STATUS;        // 0x40 USB PHY Status Register
+  UINT32 reserved1[3];
+  UINT32 USBPHY_DEBUG;         // 0x50 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_SET;     // 0x54 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_CLR;     // 0x58 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_TOG;     // 0x5C USB PHY Debug Register
+  UINT32 USBPHY_DEBUG0_STATUS; // 0x60 UTMI Debug Status Register 0
+  UINT32 reserved2[3];
+  UINT32 USBPHY_DEBUG1;        // 0x70 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_SET;    // 0x74 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_CLR;    // 0x78 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_TOG;    // 0x7C UTMI Debug Status Register 1
+  UINT32 USBPHY_VERSION;       // 0x80 UTMI RTL Version
+  UINT32 reserved3[3];
+  UINT32 USBPHY_IP;            // 0x90
+  UINT32 USBPHY_IP_SET;        // 0x94
+  UINT32 USBPHY_IP_CLR;        // 0x98
+  UINT32 USBPHY_IP_TOG;        // 0x9C
+} IMX_USBPHY_REGISTERS;
+
+#define IMX_USBPHY_IP_FIX   ((1 << 17) | (1 << 18))
+
+#pragma pack(pop)
+
+#endif // __IMX6_DQP_H__
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h b/Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h
new file mode 100644
index 000000000000..bde0e905d91f
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h
@@ -0,0 +1,301 @@
+/** @file
+*
+*  Header defining the iMX6 Solo and Dual Lite constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX6_SDL_H__
+#define __IMX6_SDL_H__
+
+#include "iMX6_common.h"
+
+#pragma pack(push, 1)
+
+// IOMUXC Registers
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL0      0x020E0244
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0      0x020E0258
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL1      0x020E0248
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1      0x020E025C
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL2      0x020E024C
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2      0x020E0260
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL3      0x020E0250
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3      0x020E0264
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL4      0x020E0254
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4      0x020E0268
+
+// Define base address of Select Input registers IMX6SDL to be one word
+// less than the minimum value so that a valid Select Input value
+// is non-zero.
+#define IOMUXC_SELECT_INPUT_BASE_ADDRESS 0x20E0790
+
+typedef enum {
+  IOMUXC_ASRC_ASRCK_CLOCK_6_SELECT_INPUT = 0x20E0794,
+  IOMUXC_AUD4_INPUT_DA_AMX_SELECT_INPUT = 0x20E0798,
+  IOMUXC_AUD4_INPUT_DB_AMX_SELECT_INPUT = 0x20E079C,
+  IOMUXC_AUD4_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E07A0,
+  IOMUXC_AUD4_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E07C0,
+  IOMUXC_AUD4_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E07A8,
+  IOMUXC_AUD4_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E07AC,
+  IOMUXC_AUD5_INPUT_DA_AMX_SELECT_INPUT = 0x20E07B0,
+  IOMUXC_AUD5_INPUT_DB_AMX_SELECT_INPUT = 0x20E07B4,
+  IOMUXC_AUD5_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E07B8,
+  IOMUXC_AUD5_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E07BC,
+  IOMUXC_AUD5_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E07C0,
+  IOMUXC_AUD5_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E07C4,
+  IOMUXC_FLEXCAN1_RX_SELECT_INPUT = 0x20E07C8,
+  IOMUXC_FLEXCAN2_RX_SELECT_INPUT = 0x20E07CC,
+  IOMUXC_CCM_PMIC_READY_SELECT_INPUT = 0x20E07D4,
+  IOMUXC_ECSPI1_CSPI_CLK_IN_SELECT_INPUT = 0x20E07D8,
+  IOMUXC_ECSPI1_MISO_SELECT_INPUT = 0x20E07DC,
+  IOMUXC_ECSPI1_MOSI_SELECT_INPUT = 0x20E07E0,
+  IOMUXC_ECSPI1_SS0_SELECT_INPUT = 0x20E07E4,
+  IOMUXC_ECSPI1_SS1_SELECT_INPUT = 0x20E07E8,
+  IOMUXC_ECSPI1_SS2_SELECT_INPUT = 0x20E07EC,
+  IOMUXC_ECSPI1_SS3_SELECT_INPUT = 0x20E07F0,
+  IOMUXC_ECSPI2_CSPI_CLK_IN_SELECT_INPUT = 0x20E07F4,
+  IOMUXC_ECSPI2_MISO_SELECT_INPUT = 0x20E07F8,
+  IOMUXC_ECSPI2_MOSI_SELECT_INPUT = 0x20E07FC,
+  IOMUXC_ECSPI2_SS0_SELECT_INPUT = 0x20E0800,
+  IOMUXC_ECSPI2_SS1_SELECT_INPUT = 0x20E0804,
+  IOMUXC_ECSPI4_SS0_SELECT_INPUT = 0x20E0808,
+  IOMUXC_ENET_REF_CLK_SELECT_INPUT = 0x20E080C,
+  IOMUXC_ENET_MAC0_MDIO_SELECT_INPUT = 0x20E0810,
+  IOMUXC_ENET_MAC0_RX_CLK_SELECT_INPUT = 0x20E0814,
+  IOMUXC_ENET_MAC0_RX_DATA0_SELECT_INPUT = 0x20E0818,
+  IOMUXC_ENET_MAC0_RX_DATA1_SELECT_INPUT = 0x20E081C,
+  IOMUXC_ENET_MAC0_RX_DATA2_SELECT_INPUT = 0x20E0820,
+  IOMUXC_ENET_MAC0_RX_DATA3_SELECT_INPUT = 0x20E0824,
+  IOMUXC_ENET_MAC0_RX_EN_SELECT_INPUT = 0x20E0828,
+  IOMUXC_ESAI_RX_FS_SELECT_INPUT = 0x20E082C,
+  IOMUXC_ESAI_TX_FS_SELECT_INPUT = 0x20E0830,
+  IOMUXC_ESAI_RX_HF_CLK_SELECT_INPUT = 0x20E0834,
+  IOMUXC_ESAI_TX_HF_CLK_SELECT_INPUT = 0x20E0838,
+  IOMUXC_ESAI_RX_CLK_SELECT_INPUT = 0x20E083C,
+  IOMUXC_ESAI_TX_CLK_SELECT_INPUT = 0x20E0840,
+  IOMUXC_ESAI_SDO0_SELECT_INPUT = 0x20E0844,
+  IOMUXC_ESAI_SDO1_SELECT_INPUT = 0x20E0848,
+  IOMUXC_ESAI_SDO2_SDI3_SELECT_INPUT = 0x20E084C,
+  IOMUXC_ESAI_SDO3_SDI2_SELECT_INPUT = 0x20E0850,
+  IOMUXC_ESAI_SDO4_SDI1_SELECT_INPUT = 0x20E0854,
+  IOMUXC_ESAI_SDO5_SDI0_SELECT_INPUT = 0x20E0858,
+  IOMUXC_HDMI_ICECIN_SELECT_INPUT = 0x20E085C,
+  IOMUXC_HDMI_II2C_CLKIN_SELECT_INPUT = 0x20E0860,
+  IOMUXC_HDMI_II2C_DATAIN_SELECT_INPUT = 0x20E0864,
+  IOMUXC_I2C1_SCL_IN_SELECT_INPUT = 0x20E0868,
+  IOMUXC_I2C1_SDA_IN_SELECT_INPUT = 0x20E086C,
+  IOMUXC_I2C2_SCL_IN_SELECT_INPUT = 0x20E0870,
+  IOMUXC_I2C2_SDA_IN_SELECT_INPUT = 0x20E0874,
+  IOMUXC_I2C3_SCL_IN_SELECT_INPUT = 0x20E0878,
+  IOMUXC_I2C3_SDA_IN_SELECT_INPUT = 0x20E087C,
+  IOMUXC_I2C4_SCL_IN_SELECT_INPUT = 0x20E0880,
+  IOMUXC_I2C4_SDA_IN_SELECT_INPUT = 0x20E0884,
+  IOMUXC_KEY_COL5_SELECT_INPUT = 0x20E08C0,
+  IOMUXC_KEY_COL6_SELECT_INPUT = 0x20E08C4,
+  IOMUXC_KEY_COL7_SELECT_INPUT = 0x20E08C8,
+  IOMUXC_KEY_ROW5_SELECT_INPUT = 0x20E08CC,
+  IOMUXC_KEY_ROW6_SELECT_INPUT = 0x20E08D0,
+  IOMUXC_KEY_ROW7_SELECT_INPUT = 0x20E08D4,
+  IOMUXC_MLB_MLB_CLK_IN_SELECT_INPUT = 0x20E08DC,
+  IOMUXC_MLB_MLB_DATA_IN_SELECT_INPUT = 0x20E08E0,
+  IOMUXC_MLB_MLB_SIG_IN_SELECT_INPUT = 0x20E08E4,
+  IOMUXC_SDMA_EVENTS14_SELECT_INPUT = 0x20E08E8,
+  IOMUXC_SPDIF_SPDIF_IN1_SELECT_INPUT = 0x20E08F0,
+  IOMUXC_SPDIF_TX_CLK2_SELECT_INPUT = 0x20E08F4,
+  IOMUXC_UART1_UART_RTS_B_SELECT_INPUT = 0x20E08F8,
+  IOMUXC_UART1_UART_RX_DATA_SELECT_INPUT = 0x20E08FC,
+  IOMUXC_UART2_UART_RTS_B_SELECT_INPUT = 0x20E00900,
+  IOMUXC_UART2_UART_RX_DATA_SELECT_INPUT = 0x20E0904,
+  IOMUXC_UART3_UART_RTS_B_SELECT_INPUT = 0x20E908,
+  IOMUXC_UART3_UART_RX_DATA_SELECT_INPUT = 0x20E090C,
+  IOMUXC_UART4_UART_RTS_B_SELECT_INPUT = 0x20E0910,
+  IOMUXC_UART4_UART_RX_DATA_SELECT_INPUT = 0x20E0914,
+  IOMUXC_UART5_UART_RTS_B_SELECT_INPUT = 0x20E0918,
+  IOMUXC_UART5_UART_RX_DATA_SELECT_INPUT = 0x20E091C,
+  IOMUXC_USB_OTG_OC_SELECT_INPUT = 0x20E0920,
+  IOMUXC_USB_H1_OC_SELECT_INPUT = 0x20E0924,
+  IOMUXC_USDHC1_WP_ON_SELECT_INPUT = 0x20E092C,
+  IOMUXC_SELECT_INPUT_UPPER_BOUND = IOMUXC_USDHC1_WP_ON_SELECT_INPUT,
+} IMX_INPUT_SELECT;
+
+#define IOMUXC_GPR_BASE_ADDRESS 0x020E0000
+
+typedef struct {
+  UINT32 GPR0;                          // 0x00 IOMUXC_GPR0
+  UINT32 GPR1;                          // 0x04 IOMUXC_GPR1
+  UINT32 GPR2;                          // 0x08 IOMUXC_GPR2
+  UINT32 GPR3;                          // 0x0C IOMUXC_GPR3
+  UINT32 GPR4;                          // 0x10 IOMUXC_GPR4
+  UINT32 GPR5;                          // 0x14 IOMUXC_GPR5
+  UINT32 GPR6;                          // 0x18 IOMUXC_GPR6
+  UINT32 GPR7;                          // 0x1C IOMUXC_GPR7
+  UINT32 GPR8;                          // 0x20 IOMUXC_GPR8
+  UINT32 GPR9;                          // 0x24 IOMUXC_GPR9
+  UINT32 GPR10;                         // 0x28 IOMUXC_GPR10
+  UINT32 GPR11;                         // 0x2c IOMUXC_GPR11
+  UINT32 GPR12;                         // 0x30 IOMUXC_GPR12
+  UINT32 GPR13;                         // 0x34 IOMUXC_GPR13
+} IMX_IOMUXC_GPR_REGISTERS;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ACT_CS0 : 1;                 // 0
+    UINT32 ADDRS0_10 : 2;               // 1-2
+    UINT32 ACT_CS1 : 1;                 // 3
+    UINT32 ADDRS1_10 : 2;               // 4-5
+    UINT32 ACT_CS2 : 1;                 // 6
+    UINT32 ADDRS2_10 : 2;               // 7-8
+    UINT32 ACT_CS3 : 1;                 // 9
+    UINT32 ADDRS3_10 : 2;               // 10-11 Active Chip Select and Address Space
+    UINT32 GINT : 1;                    // 12 Global interrupt "0" bit
+                                        //   (connected to ARM IRQ#0 and GPC)
+    UINT32 USB_OTG_ID_SEL : 1;          // 13 ''usb_otg_id' pin iomux select control.
+    UINT32 SYS_INT : 1;                 // 14 PCIe_CTL
+    UINT32 USB_EXP_MODE : 1;            // 15 USB Exposure mode
+    UINT32 REF_SSP_EN : 1;              // 16 PCIe_PHY - Reference Clock Enable
+                                        //   for SS function.
+    UINT32 PU_VPU_MUX : 1;              // 17 IPU-1/IPU-2 to VPU signals control.
+    UINT32 TEST_POWERDOWN : 1;          // 18 PCIe_PHY - All Circuits Power-Down
+                                        //   Control Function.
+    UINT32 MIPI_IPU1_MUX : 1;           // 19 MIPI sensor to IPU-1 mux control.
+    UINT32 MIPI_IPU2_MUX : 1;           // 20 MIPI sensor to IPU-2 mux control
+    UINT32 ENET_CLK_SEL : 1;            // 21 ENET TX reference clock
+    UINT32 EXC_MON : 1;                 // 22 Exclusive monitor response select
+                                        //   of illegal command
+    UINT32 reserved1 : 1;               // 23
+    UINT32 MIPI_DPI_OFF : 1;            // 24 MIPI DPI shutdown request
+    UINT32 MIPI_COLOR_SW : 1;           // 25 MIPI color switch control
+    UINT32 APP_REQ_ENTR_L1 : 1;         // 26 PCIe_CTL - Application Request to Enter L1
+    UINT32 APP_READY_ENTR_L23 : 1;      // 27 PCIe_CTL - Application Ready to Enter L23
+    UINT32 APP_REQ_EXIT_L1 : 1;         // 28 PCIe_CTL - Application Request to Exit L1
+    UINT32 reserved2 : 1;               // 29
+    UINT32 APP_CLK_REQ_N : 1;           // 30 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Indicates that application logic is
+                                        //   ready to have reference clock removed.
+    UINT32 CFG_L1_CLK_REMOVAL_EN : 1;   // 31 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Enable the reference clock removal
+                                        //   in L1 state.
+  };
+} IMX_IOMUXC_GPR1_REG;
+
+// USB PHY
+#define IMX_USBPHY1_BASE 0x020C9000
+#define IMX_USBPHY2_BASE 0x020CA000
+#define IMX_USBPHY_LENGTH 0x1000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ENOTG_ID_CHG_IRQ : 1;      // 0 Enable OTG_ID_CHG_IRQ.
+    UINT32 ENHOSTDISCONDETECT : 1;    // 1 For host mode, enables high-speed
+                                      //   disconnect detector.
+    UINT32 ENIRQHOSTDISCON : 1;       // 2 Enables interrupt for detection of
+                                      //   disconnection to Device when in
+                                      //   high-speed host mode.
+    UINT32 HOSTDISCONDETECT_IRQ : 1;  // 3 Indicates that the device has
+                                      //   disconnected in high-speed mode.
+    UINT32 ENDEVPLUGINDETECT : 1;     // 4 For device mode, enables 200-KOhm
+                                      //   pullups for detecting connectivity
+                                      //   to the host.
+    UINT32 DEVPLUGIN_POLARITY : 1;    // 5 For device mode interrupt generation polarity
+    UINT32 OTG_ID_CHG_IRQ : 1;        // 6 OTG ID change interrupt. Indicates
+                                      //   the value of ID pin changed.
+    UINT32 ENOTGIDDETECT : 1;         // 7 Enables circuit to detect resistance
+                                      //   of MiniAB ID pin.
+    UINT32 RESUMEIRQSTICKY : 1;       // 8 1 makes RESUME_IRQ bit a sticky bit.
+    UINT32 ENIRQRESUMEDETECT : 1;     // 9 Enables interrupt for detection of a
+                                      //   non-J state on the USB line.
+    UINT32 RESUME_IRQ : 1;            // 10 Indicates that the host is sending a
+                                      //   wake-up after suspend
+    UINT32 ENIRQDEVPLUGIN : 1;        // 11 Enables interrupt for the detection
+                                      //   of connectivity to the USB line.
+    UINT32 DEVPLUGIN_IRQ : 1;         // 12 Indicates that the device is connected
+    UINT32 DATA_ON_LRADC : 1;         // 13 Enables the LRADC to monitor USB_DP
+                                      //   and USB_DM.
+    UINT32 ENUTMILEVEL2 : 1;          // 14 Enables UTMI+ Level2.
+    UINT32 ENUTMILEVEL3 : 1;          // 15 Enables UTMI+ Level3.
+    UINT32 ENIRQWAKEUP : 1;           // 16 Enables interrupt for the wakeup events
+    UINT32 WAKEUP_IRQ : 1;            // 17 Indicates that there is a wakeup event.
+    UINT32 reserved1 : 1;             // 18 reserved
+    UINT32 ENAUTOCLR_CLKGATE : 1;     // 19 Enables the feature to auto-clear the
+                                      //   CLKGATE bit if there is wakeup event
+                                      //   while USB is suspended.
+    UINT32 ENAUTOCLR_PHY_PWD : 1;     // 20 Enables the feature to auto-clear the
+                                      //   PWD register bits in USBPHYx_PWD if
+                                      //   there is wakeup event while USB is suspended
+    UINT32 ENDPDMCHG_WKUP : 1;        // 21 Enables the feature to wakeup USB if
+                                      //   DP/DM is toggled when USB is suspended
+    UINT32 ENIDCHG_WKUP : 1;          // 22 Enables the feature to wakeup USB if
+                                      //   ID is toggled when USB is suspended
+    UINT32 ENVBUSCHG_WKUP : 1;        // 23 Enables the feature to wakeup USB if
+                                      //   VBUS is toggled when USB is suspended.
+    UINT32 FSDLL_RST_EN : 1;          // 24 Enables the feature to reset the FSDLL
+                                      //   lock detection logic at the end of
+                                      //   each TX packet.
+    UINT32 reserved2 : 2;             // 25-26
+    UINT32 OTG_ID_VALUE : 1;          // 27
+    UINT32 HOST_FORCE_LS_SE0 : 1;     // 28 Forces the next FS packet that is
+                                      //   transmitted to have a EOP with LS timing.
+    UINT32 UTMI_SUSPENDM : 1;         // 29 Used by the PHY to indicate a
+                                      //   powered-down state.
+    UINT32 CLKGATE : 1;               // 30 Gate UTMI Clocks. Clear to 0 to run clocks.
+    UINT32 SFTRST : 1;                // 31 Soft-reset the USBPHYx_PWD, USBPHYx_TX,
+                                      //   USBPHYx_RX, Set to 0 to release the
+                                      //   PHY from reset.
+  };
+} USBPHYx_CTRL_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 STEP : 16;   // 0-15 Read-only value for the stepping of the RTL version.
+    UINT32 MINOR : 8;   // 16-23 Read-only value for the MINOR field of the RTL version.
+    UINT32 MAJOR : 8;   // 24-31 Read-only value for the MAJOR field of the RTL version
+  };
+} USBPHYx_VERSION_REG;
+
+typedef struct {
+  UINT32 USBPHY_PWD;             // 0x00 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_SET;         // 0x04 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_CLR;         // 0x08 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_TOG;         // 0x0C USB PHY Power-Down Register
+  UINT32 USBPHY_TX;              // 0x10 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_SET;          // 0x14 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_CLR;          // 0x18 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_TOG;          // 0x1C USB PHY Transmitter Control Register
+  UINT32 USBPHY_RX;              // 0x20 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_SET;          // 0x24 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_CLR;          // 0x28 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_TOG;          // 0x2C USB PHY Receiver Control Register
+  UINT32 USBPHY_CTRL;            // 0x30 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_SET;        // 0x34 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_CLR;        // 0x38 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_TOG;        // 0x3C USB PHY General Control Register
+  UINT32 USBPHY_STATUS;          // 0x40 USB PHY Status Register
+  UINT32 reserved1[3];
+  UINT32 USBPHY_DEBUG;           // 0x50 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_SET;       // 0x54 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_CLR;       // 0x58 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_TOG;       // 0x5C USB PHY Debug Register
+  UINT32 USBPHY_DEBUG0_STATUS;   // 0x60 UTMI Debug Status Register 0
+  UINT32 reserved2[3];
+  UINT32 USBPHY_DEBUG1;          // 0x70 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_SET;      // 0x74 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_CLR;      // 0x78 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_TOG;      // 0x7C UTMI Debug Status Register 1
+  UINT32 USBPHY_VERSION;         // 0x80 UTMI RTL Version
+} IMX_USBPHY_REGISTERS;
+
+#pragma pack(pop)
+
+#endif // __IMX6_SDL_H__
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h b/Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h
new file mode 100644
index 000000000000..36b5802cf7de
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h
@@ -0,0 +1,1730 @@
+/** @file
+*
+*  Header defining the iMX6 SoloX constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX6_SX_H__
+#define __IMX6_SX_H__
+
+#pragma pack(push, 1)
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED               ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED             ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+// Boot DRAM region (kernel.img & boot working DRAM)
+#define FRAME_BUFFER_BASE                   0x821D4000
+#define FRAME_BUFFER_SIZE                   0x00800000 // 8MB
+
+#define BOOT_IMAGE_PHYSICAL_BASE            0x82004000
+#define BOOT_IMAGE_PHYSICAL_LENGTH          0x001D0000 // 1MB
+#define BOOT_IMAGE_ATTRIBUTES               CacheAttributes
+
+// The region of registers from 0x00100000 to 0x02300000
+#define SOC_REGISTERS_PHYSICAL_BASE1        0x00100000
+#define SOC_REGISTERS_PHYSICAL_LENGTH1      0x02200000
+#define SOC_REGISTERS_ATTRIBUTES            ARM_MEMORY_REGION_ATTRIBUTE_DEVICE
+
+// PCIE registers and configuration space (0x08000000 - 0x09000000)
+#define PCIE_REGISTERS_PHYSICAL_BASE        0x08000000
+#define PCIE_REGISTERS_PHYSICAL_LENGTH      0x01000000
+
+// The region of registers from 0x0C000000 to 0x80000000
+#define SOC_REGISTERS_PHYSICAL_BASE2        0x0C000000
+#define SOC_REGISTERS_PHYSICAL_LENGTH2      0x74000000
+
+// Main system DRAM as defined by the PCD definitions of system memory.
+
+// MPPP definitions
+#define CPU0_MPPP_PHYSICAL_BASE            0x8080F000
+
+// Interrupt controller
+#define CSP_BASE_REG_PA_IC_IFC              0x00A00100
+#define CSP_BASE_REG_PA_IC_DIST             0x00A01000
+
+// L2 cache controller
+#define CSP_BASE_REG_PA_PL310               0x00A02000
+
+// Timers
+#define CSP_BASE_REG_PA_GPT                 0x02098000
+#define CSP_BASE_REG_PA_EPIT1               0x020D0000
+#define CSP_BASE_REG_PA_EPIT2               0x020D4000
+
+// Timers IRQs
+#define IC_DIST_VECTOR_BASE 0
+#define IRQ_EPIT1           88
+#define IRQ_EPIT2           89
+
+// SDMA (Smart DMA) controller
+#define CSP_BASE_REG_PA_SDMA                0x020EC000
+#define IRQ_SDMA 34
+
+// SOC peripherals
+#define CSP_BASE_REG_PA_UART1               0x02020000
+#define CSP_BASE_REG_PA_UART2               0x021e8000
+#define CSP_BASE_REG_PA_UART3               0x021EC000
+#define CSP_BASE_REG_PA_ESDHC2              0x02194000
+#define CSP_BASE_REG_PA_ESDHC3              0x02198000
+
+#define DBG_PORT_SUBTYPE_IMX6   0x000C
+
+// Timers clock sources
+#define SOC_OSC_FREQUENCY_REF_HZ  24000000  // Oscillator frequency 24Mhz
+#define SOC_HIGH_FREQUENCY_REF_HZ 66000000  // High Frequency reference clock 66Mhz
+#define SOC_LOW_FREQ_REF_HZ       32768     // SNVS RTC frequency 32kHz
+
+// IOMUX Controller (IOMUXC)
+#define IMX_IOMUXC_BASE 0x020E0000
+#define IMX_IOMUXC_LENGTH 0x4000
+
+// Secure Nonvolatile Storage (SNVS)
+#define IMX_SNVS_BASE 0x020CC000
+#define IMX_SNVS_LENGTH 0x4000
+#define IMX_SNVS_IP_ID 0x3E
+#define IMX_SNVS_IRQ 51         // SNVS consolidated interrupt
+
+// IOMUXC Registers
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL0      0x020E00A4
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL1      0x020E00A8
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL2      0x020E00AC
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL3      0x020E00B0
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL4      0x020E00B4
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0      0x020E00B8
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1      0x020E00BC
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2      0x020E00C0
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3      0x020E00C4
+#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4      0x020E00C8
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL0      0x020E03EC
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL1      0x020E03F0
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL2      0x020E03F4
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL3      0x020E03F8
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL4      0x020E03FC
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW0      0x020E0400
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW1      0x020E0404
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW2      0x020E0408
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW3      0x020E040C
+#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW4      0x020E0410
+
+// define base address of Select Input registers to be one word
+// less than the minimum value so that a valid Select Input value
+// is non-zero. (IOMUXC_SW_PAD_CTL_GRP_B3DS)
+#define IOMUXC_SELECT_INPUT_BASE_ADDRESS 0x20E0620
+
+typedef enum {
+  IOMUXC_ANATOP_USB_OTG_ID_SELECT_INPUT = 0x20E0624,
+  IOMUXC_ANATOP_USB_UH1_ID_SELECT_INPUT = 0x20E0628,
+  IOMUXC_AUDMUX_P3_INPUT_DA_AMX_SELECT_INPUT = 0x20E062C,
+  IOMUXC_AUDMUX_P3_INPUT_DB_AMX_SELECT_INPUT = 0x20E0630,
+  IOMUXC_AUDMUX_P3_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E0634,
+  IOMUXC_AUDMUX_P3_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E0638,
+  IOMUXC_AUDMUX_P3_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E063C,
+  IOMUXC_AUDMUX_P3_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E0640,
+  IOMUXC_AUDMUX_P4_INPUT_DA_AMX_SELECT_INPUT = 0x20E0644,
+  IOMUXC_AUDMUX_P4_INPUT_DB_AMX_SELECT_INPUT = 0x20E0648,
+  IOMUXC_AUDMUX_P4_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E064C,
+  IOMUXC_AUDMUX_P4_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E0650,
+  IOMUXC_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E0654,
+  IOMUXC_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E0658,
+  IOMUXC_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT = 0x20E065C,
+  IOMUXC_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT = 0x20E0660,
+  IOMUXC_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E0664,
+  IOMUXC_AUDMUX_P5_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E0668,
+  IOMUXC_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E066C,
+  IOMUXC_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E0670,
+  IOMUXC_AUDMUX_P6_INPUT_DA_AMX_SELECT_INPUT = 0x20E0674,
+  IOMUXC_AUDMUX_P6_INPUT_DB_AMX_SELECT_INPUT = 0x20E0678,
+  IOMUXC_AUDMUX_P6_INPUT_RXCLK_AMX_SELECT_INPUT = 0x20E067C,
+  IOMUXC_AUDMUX_P6_INPUT_RXFS_AMX_SELECT_INPUT = 0x20E0680,
+  IOMUXC_AUDMUX_P6_INPUT_TXCLK_AMX_SELECT_INPUT = 0x20E0684,
+  IOMUXC_AUDMUX_P6_INPUT_TXFS_AMX_SELECT_INPUT = 0x20E0688,
+  IOMUXC_CAN1_IPP_IND_CANRX_SELECT_INPUT = 0x20E068C,
+  IOMUXC_CAN2_IPP_IND_CANRX_SELECT_INPUT = 0x20E0690,
+  IOMUXC_CCM_PMIC_VFUNCIONAL_READY_SELECT_INPUT = 0x20E069C,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_0 = 0x20E06A0,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_1 = 0x20E06A4,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_2 = 0x20E06A8,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_3 = 0x20E06AC,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_4 = 0x20E06B0,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_5 = 0x20E06B4,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_6 = 0x20E06B8,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_7 = 0x20E06BC,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_8 = 0x20E06C0,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_9 = 0x20E06C4,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_11 = 0x20E06C8,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_12 = 0x20E06CC,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_13 = 0x20E06D0,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_14 = 0x20E06D4,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_15 = 0x20E06D8,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_16 = 0x20E06DC,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_17 = 0x20E06E0,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_18 = 0x20E06E4,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_19 = 0x20E06E8,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_20 = 0x20E06EC,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_21 = 0x20E06F0,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_22 = 0x20E06F4,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_23 = 0x20E06F8,
+  IOMUXC_CSI1_IPP_CSI_D_SELECT_INPUT_10 = 0x20E06FC,
+  IOMUXC_CSI1_IPP_CSI_HSYNC_SELECT_INPUT = 0x20E0700,
+  IOMUXC_CSI1_IPP_CSI_PIXCLK_SELECT_INPUT = 0x20E0704,
+  IOMUXC_CSI1_IPP_CSI_VSYNC_SELECT_INPUT = 0x20E0708,
+  IOMUXC_CSI1_TVDECODER_IN_FIELD_SELECT_INPUT = 0x20E070C,
+  IOMUXC_ECSPI1_IPP_CSPI_CLK_IN_SELECT_INPUT = 0x20E0710,
+  IOMUXC_ECSPI1_IPP_IND_MISO_SELECT_INPUT = 0x20E0714,
+  IOMUXC_ECSPI1_IPP_IND_MOSI_SELECT_INPUT = 0x20E0718,
+  IOMUXC_ECSPI1_IPP_IND_SS_B_SELECT_INPUT_0 = 0x20E071C,
+  IOMUXC_ECSPI2_IPP_CSPI_CLK_IN_SELECT_INPUT = 0x20E0720,
+  IOMUXC_ECSPI2_IPP_IND_MISO_SELECT_INPUT = 0x20E0724,
+  IOMUXC_ECSPI2_IPP_IND_MOSI_SELECT_INPUT = 0x20E0728,
+  IOMUXC_ECSPI2_IPP_IND_SS_B_SELECT_INPUT_0 = 0x20E072C,
+  IOMUXC_ECSPI3_IPP_CSPI_CLK_IN_SELECT_INPUT = 0x20E0730,
+  IOMUXC_ECSPI3_IPP_IND_MISO_SELECT_INPUT = 0x20E0734,
+  IOMUXC_ECSPI3_IPP_IND_MOSI_SELECT_INPUT = 0x20E0738,
+  IOMUXC_ECSPI3_IPP_IND_SS_B_SELECT_INPUT_0 = 0x20E073C,
+  IOMUXC_ECSPI4_IPP_CSPI_CLK_IN_SELECT_INPUT = 0x20E0740,
+  IOMUXC_ECSPI4_IPP_IND_MISO_SELECT_INPUT = 0x20E0744,
+  IOMUXC_ECSPI4_IPP_IND_MOSI_SELECT_INPUT = 0x20E0748,
+  IOMUXC_ECSPI4_IPP_IND_SS_B_SELECT_INPUT_0 = 0x20E074C,
+  IOMUXC_ECSPI5_IPP_CSPI_CLK_IN_SELECT_INPUT = 0x20E0750,
+  IOMUXC_ECSPI5_IPP_IND_MISO_SELECT_INPUT = 0x20E0754,
+  IOMUXC_ECSPI5_IPP_IND_MOSI_SELECT_INPUT = 0x20E0758,
+  IOMUXC_ECSPI5_IPP_IND_SS_B_SELECT_INPUT_0 = 0x20E075C,
+  IOMUXC_ENET1_IPG_CLK_RMII_SELECT_INPUT = 0x20E0760,
+  IOMUXC_ENET1_IPP_IND_MAC0_MDIO_SELECT_INPUT = 0x20E0764,
+  IOMUXC_ENET1_IPP_IND_MAC0_RXCLK_SELECT_INPUT = 0x20E0768,
+  IOMUXC_ENET2_IPG_CLK_RMII_SELECT_INPUT = 0x20E076C,
+  IOMUXC_ENET2_IPP_IND_MAC0_MDIO_SELECT_INPUT = 0x20E0770,
+  IOMUXC_ENET2_IPP_IND_MAC0_RXCLK_SELECT_INPUT = 0x20E0774,
+  IOMUXC_ESAI_IPP_IND_FSR_SELECT_INPUT = 0x20E0778,
+  IOMUXC_ESAI_IPP_IND_FST_SELECT_INPUT = 0x20E077C,
+  IOMUXC_ESAI_IPP_IND_HCKR_SELECT_INPUT = 0x20E0780,
+  IOMUXC_ESAI_IPP_IND_HCKT_SELECT_INPUT = 0x20E0784,
+  IOMUXC_ESAI_IPP_IND_SCKR_SELECT_INPUT = 0x20E0788,
+  IOMUXC_ESAI_IPP_IND_SCKT_SELECT_INPUT = 0x20E078C,
+  IOMUXC_ESAI_IPP_IND_SDO0_SELECT_INPUT = 0x20E0790,
+  IOMUXC_ESAI_IPP_IND_SDO1_SELECT_INPUT = 0x20E0794,
+  IOMUXC_ESAI_IPP_IND_SDO2_SDI3_SELECT_INPUT = 0x20E0798,
+  IOMUXC_ESAI_IPP_IND_SDO3_SDI2_SELECT_INPUT = 0x20E079C,
+  IOMUXC_ESAI_IPP_IND_SDO4_SDI1_SELECT_INPUT = 0x20E07A0,
+  IOMUXC_ESAI_IPP_IND_SDO5_SDI0_SELECT_INPUT = 0x20E07A4,
+  IOMUXC_I2C1_IPP_SCL_IN_SELECT_INPUT = 0x20E07A8,
+  IOMUXC_I2C1_IPP_SDA_IN_SELECT_INPUT = 0x20E07AC,
+  IOMUXC_I2C2_IPP_SCL_IN_SELECT_INPUT = 0x20E07B0,
+  IOMUXC_I2C2_IPP_SDA_IN_SELECT_INPUT = 0x20E07B4,
+  IOMUXC_I2C3_IPP_SCL_IN_SELECT_INPUT = 0x20E07B8,
+  IOMUXC_I2C3_IPP_SDA_IN_SELECT_INPUT = 0x20E07BC,
+  IOMUXC_I2C4_IPP_SCL_IN_SELECT_INPUT = 0x20E07C0,
+  IOMUXC_I2C4_IPP_SDA_IN_SELECT_INPUT = 0x20E07C4,
+  IOMUXC_KPP_IPP_IND_COL_SELECT_INPUT_5 = 0x20E07C8,
+  IOMUXC_KPP_IPP_IND_COL_SELECT_INPUT_6 = 0x20E07CC,
+  IOMUXC_KPP_IPP_IND_COL_SELECT_INPUT_7 = 0x20E07D0,
+  IOMUXC_KPP_IPP_IND_ROW_SELECT_INPUT_5 = 0x20E07D4,
+  IOMUXC_KPP_IPP_IND_ROW_SELECT_INPUT_6 = 0x20E07D8,
+  IOMUXC_KPP_IPP_IND_ROW_SELECT_INPUT_7 = 0x20E07DC,
+  IOMUXC_LCD1_BUSY_SELECT_INPUT = 0x20E07E0,
+  IOMUXC_LCD2_BUSY_SELECT_INPUT = 0x20E07E4,
+  IOMUXC_MLB_MLB_CLK_IN_SELECT_INPUT = 0x20E07E8,
+  IOMUXC_MLB_MLB_DATA_IN_SELECT_INPUT = 0x20E07EC,
+  IOMUXC_MLB_MLB_SIG_IN_SELECT_INPUT = 0x20E07F0,
+  IOMUXC_SAI1_IPP_IND_SAI_RXBCLK_SELECT_INPUT = 0x20E07F4,
+  IOMUXC_SAI1_IPP_IND_SAI_RXDATA_SELECT_INPUT_0 = 0x20E07F8,
+  IOMUXC_SAI1_IPP_IND_SAI_RXSYNC_SELECT_INPUT = 0x20E07FC,
+  IOMUXC_SAI1_IPP_IND_SAI_TXBCLK_SELECT_INPUT = 0x20E0800,
+  IOMUXC_SAI1_IPP_IND_SAI_TXSYNC_SELECT_INPUT = 0x20E0804,
+  IOMUXC_SAI2_IPP_IND_SAI_RXBCLK_SELECT_INPUT = 0x20E0808,
+  IOMUXC_SAI2_IPP_IND_SAI_RXDATA_SELECT_INPUT_0 = 0x20E080C,
+  IOMUXC_SAI2_IPP_IND_SAI_RXSYNC_SELECT_INPUT = 0x20E0810,
+  IOMUXC_SAI2_IPP_IND_SAI_TXBCLK_SELECT_INPUT = 0x20E0814,
+  IOMUXC_SAI2_IPP_IND_SAI_TXSYNC_SELECT_INPUT = 0x20E0818,
+  IOMUXC_SDMA_EVENTS_SELECT_INPUT_14 = 0x20E081C,
+  IOMUXC_SDMA_EVENTS_SELECT_INPUT_15 = 0x20E0820,
+  IOMUXC_SPDIF_SPDIF_IN1_SELECT_INPUT = 0x20E0824,
+  IOMUXC_SPDIF_TX_CLK2_SELECT_INPUT = 0x20E0828,
+  IOMUXC_UART1_IPP_UART_RTS_B_SELECT_INPUT = 0x20E082C,
+  IOMUXC_UART1_IPP_UART_RXD_MUX_SELECT_INPUT = 0x20E0830,
+  IOMUXC_UART2_IPP_UART_RTS_B_SELECT_INPUT = 0x20E0834,
+  IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT = 0x20E0838,
+  IOMUXC_UART3_IPP_UART_RTS_B_SELECT_INPUT = 0x20E083C,
+  IOMUXC_UART3_IPP_UART_RXD_MUX_SELECT_INPUT = 0x20E0840,
+  IOMUXC_UART4_IPP_UART_RTS_B_SELECT_INPUT = 0x20E0844,
+  IOMUXC_UART4_IPP_UART_RXD_MUX_SELECT_INPUT = 0x20E0848,
+  IOMUXC_UART5_IPP_UART_RTS_B_SELECT_INPUT = 0x20E084C,
+  IOMUXC_UART5_IPP_UART_RXD_MUX_SELECT_INPUT = 0x20E0850,
+  IOMUXC_UART6_IPP_UART_RTS_B_SELECT_INPUT = 0x20E0854,
+  IOMUXC_UART6_IPP_UART_RXD_MUX_SELECT_INPUT = 0x20E0858,
+  IOMUXC_USB_IPP_IND_OTG2_OC_SELECT_INPUT = 0x20E085C,
+  IOMUXC_USB_IPP_IND_OTG_OC_SELECT_INPUT = 0x20E0860,
+  IOMUXC_USDHC1_IPP_CARD_DET_SELECT_INPUT = 0x20E0864,
+  IOMUXC_USDHC1_IPP_WP_ON_SELECT_INPUT = 0x20E0868,
+  IOMUXC_USDHC2_IPP_CARD_DET_SELECT_INPUT = 0x20E086C,
+  IOMUXC_USDHC2_IPP_WP_ON_SELECT_INPUT = 0x20E0870,
+  IOMUXC_USDHC4_IPP_CARD_DET_SELECT_INPUT = 0x20E0874,
+  IOMUXC_USDHC4_IPP_WP_ON_SELECT_INPUT = 0x20E0878,
+  IOMUXC_SELECT_INPUT_UPPER_BOUND = IOMUXC_USDHC4_IPP_WP_ON_SELECT_INPUT,
+} IMX_INPUT_SELECT;
+
+#define IOMUXC_GPR_BASE_ADDRESS             0x020E4000
+
+typedef struct{
+  UINT32 GPR0;                          // 0x00 IOMUXC_GPR0
+  UINT32 GPR1;                          // 0x04 IOMUXC_GPR1
+  UINT32 GPR2;                          // 0x08 IOMUXC_GPR2
+  UINT32 GPR3;                          // 0x0C IOMUXC_GPR3
+  UINT32 GPR4;                          // 0x10 IOMUXC_GPR4
+  UINT32 GPR5;                          // 0x14 IOMUXC_GPR5
+  UINT32 GPR6;                          // 0x18 IOMUXC_GPR6
+  UINT32 GPR7;                          // 0x1C IOMUXC_GPR7
+  UINT32 GPR8;                          // 0x20 IOMUXC_GPR8
+  UINT32 GPR9;                          // 0x24 IOMUXC_GPR9
+  UINT32 GPR10;                         // 0x28 IOMUXC_GPR10
+  UINT32 GPR11;                         // 0x2c IOMUXC_GPR11
+  UINT32 GPR12;                         // 0x30 IOMUXC_GPR12
+  UINT32 GPR13;                         // 0x34 IOMUXC_GPR13
+} IMX_IOMUXC_GPR_REGISTERS;
+
+typedef enum {
+  IMX_IOMUXC_GPR1_USB_OTG_ID_SEL_ENET_RX_ER,
+  IMX_IOMUXC_GPR1_USB_OTG_ID_SEL_GPIO_1,
+} IMX_IOMUXC_GPR1_USB_OTG_ID_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ACT_CS0 : 1;                 // 0
+    UINT32 ADDRS0_10 : 2;               // 1-2
+    UINT32 ACT_CS1 : 1;                 // 3
+    UINT32 ADDRS1_10 : 2;               // 4-5
+    UINT32 ACT_CS2 : 1;                 // 6
+    UINT32 ADDRS2_10 : 2;               // 7-8
+    UINT32 ACT_CS3 : 1;                 // 9
+    UINT32 ADDRS3_10 : 2;               // 10-11 Active Chip Select and Address Space
+    UINT32 GINT : 1;                    // 12 Global interrupt "0" bit
+                                        //   (connected to ARM IRQ#0 and GPC)
+    UINT32 USB_OTG_ID_SEL : 1;          // 13 ''usb_otg_id' pin iomux select control.
+    UINT32 SYS_INT : 1;                 // 14 PCIe_CTL
+    UINT32 USB_EXP_MODE : 1;            // 15 USB Exposure mode
+    UINT32 REF_SSP_EN : 1;              // 16 PCIe_PHY - Reference Clock Enable
+                                        //   for SS function.
+    UINT32 PU_VPU_MUX : 1;              // 17 IPU-1/IPU-2 to VPU signals control.
+    UINT32 TEST_POWERDOWN : 1;          // 18 PCIe_PHY - All Circuits Power-Down
+                                        //   Control Function.
+    UINT32 MIPI_IPU1_MUX : 1;           // 19 MIPI sensor to IPU-1 mux control.
+    UINT32 MIPI_IPU2_MUX : 1;           // 20 MIPI sensor to IPU-2 mux control
+    UINT32 ENET_CLK_SEL : 1;            // 21 ENET TX reference clock
+    UINT32 EXC_MON : 1;                 // 22 Exclusive monitor response select
+                                        //   of illegal command
+    UINT32 reserved1 : 1;               // 23
+    UINT32 MIPI_DPI_OFF : 1;            // 24 MIPI DPI shutdown request
+    UINT32 MIPI_COLOR_SW : 1;           // 25 MIPI color switch control
+    UINT32 APP_REQ_ENTR_L1 : 1;         // 26 PCIe_CTL - Application Request to Enter L1
+    UINT32 APP_READY_ENTR_L23 : 1;      // 27 PCIe_CTL - Application Ready to Enter L23
+    UINT32 APP_REQ_EXIT_L1 : 1;         // 28 PCIe_CTL - Application Request to Exit L1
+    UINT32 reserved2 : 1;               // 29
+    UINT32 APP_CLK_REQ_N : 1;           // 30 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Indicates that application logic is
+                                        //   ready to have reference clock removed.
+    UINT32 CFG_L1_CLK_REMOVAL_EN : 1;   // 31 PCIe_CTL (CLK LOGIC CONTROLLER GLUE)
+                                        //   Enable the reference clock removal
+                                        //   in L1 state.
+  };
+} IMX_IOMUXC_GPR1_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PCS_TX_DEEMPH_GEN1 : 6;        // 0-5 PCIe_PHY - This static value sets
+                                          //   the launch amplitude of the transmitter
+                                          //   when pipe0_tx_swing is set to
+                                          //   1'b0 (default state).
+    UINT32 PCS_TX_DEEMPH_GEN2_3P5DB : 6;  // 6-11 PCIe_PHY - This static value
+                                          //   sets the Tx driver SWING_FULL value.
+    UINT32 PCS_TX_DEEMPH_GEN2_6DB : 6;    // 12-17 PCIe_PHY - This static value
+                                          //   sets the Tx driver de-emphasis
+                                          //   value in the case where pipe0_tx_deemph
+                                          //   is set to 1'b0 and the PHY is running
+                                          //   at the Gen2 (6db) rate.
+    UINT32 PCS_TX_SWING_FULL : 7;         // 18-24 PCIe_PHY - This static value
+                                          //   sets the Tx driver de-emphasis value
+                                          //   in the case where pipe0_tx_deemph
+                                          //   is set to 1'b1 (the default setting)
+                                          //   and the PHY is running at the
+                                          //   Gen2 (3p5db) rate.
+    UINT32 PCS_TX_SWING_LOW : 7;          // 25-31 PCIe_PHY - This static value
+                                          //   sets the Tx driver de-emphasis
+                                          //   value in the case where pipe0_tx_deemph
+                                          //   is set to 1'b1 (the default setting)
+                                          //   and the PHY is running at the
+                                          //   Gen1 rate.
+  };
+} IMX_IOMUXC_GPR8_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved0 : 2;               // 0-1
+    UINT32 uSDHC_DBG_MUX : 2;           // 2-3 uSDHC debug bus IO mux control
+    UINT32 LOS_LEVEL : 5;               // 4-8 PCIe_PHY - Loss-of-Signal Detector
+                                        //   Sensitivity Level Control Function:
+                                        //   Sets the sensitivity level for the
+                                        //   Loss-of-Signal detector. This signal
+                                        //   must be set to 0x9
+    UINT32 APPS_PM_XMT_PME : 1;         // 9 PCIe_CTL - Wake Up. Used by application
+                                        //   logic to wake up the PMC state machine
+                                        //   from a D1, D2 or D3 power state. Upon
+                                        //   wake up, the core sends a PM_PME Message
+    UINT32 APP_LTSSM_ENABLE : 1;        // 10 PCIe_CTL Driven low by the application
+                                        //   after reset to hold the LTSSM in the
+                                        //   Detect state until the application
+                                        //   is ready.When the application has
+                                        //   finished initializing the core
+                                        //   configuration registers, it asserts
+                                        //   app_ltssm_enable to allow the LTSSM
+                                        //   to continue Link establishment.
+    UINT32 APP_INIT_RST : 1;            // 11 PCIe_PHY - PCIe_CTL - Request from
+                                        //   the application to send a Hot Reset
+                                        //   to the downstream device.
+    UINT32 DEVICE_TYPE : 4;             // 12-15 PCIe_CTL - Device/Port Type.
+                                        //   0000 PCIE_EP - EP Mode
+                                        //   0010 PCIE_RC - RC Mode
+    UINT32 APPS_PM_XMT_TURNOFF : 1;     // 16 PCIe_CTL - Request from the application
+                                        //   to generate a PM_Turn_Off Message.
+    UINT32 DIA_STATUS_BUS_SELECT : 4;   // 17-20 PCIe_CTL - used for debug to select
+                                        //   what part of diag_status_bus will be
+                                        //   reflected on the 32 bits of the iomux
+    UINT32 PCIe_CTL_7 : 3;              // 21-23 PCIe control of diagnostic bus select
+    UINT32 ARMP_APB_CLK_EN : 1;         // 24 ARM platform APB clock enable
+    UINT32 ARMP_ATB_CLK_EN : 1;         // 25 ARM platform ATB clock enable
+    UINT32 ARMP_AHB_CLK_EN : 1;         // 26 ARM platform AHB clock enable
+    UINT32 ARMP_IPG_CLK_EN : 1;         // 27 ARM platform IPG clock enable
+    UINT32 reserved1 : 4;               // 28-31
+  };
+} IMX_IOMUXC_GPR12_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 1;       // 0
+    UINT32 reserved2 : 1;       // 1
+    UINT32 MC_ENV : 1;          // 2 Monotonic Counter Enable and Valid
+    UINT32 reserved3 : 1;       // 3
+    UINT32 reserved4 : 1;       // 4
+    UINT32 DP_EN : 1;           // 5 Dumb PMIC Enabled
+    UINT32 TOP : 1;             // 6 Turn off System Power
+    UINT32 PWR_GLITCH_EN : 1;   // 7 Power Glitch Detection Enable
+    UINT32 reserved5 : 1;       // 8
+    UINT32 reserved6 : 1;       // 9
+    UINT32 reserved7 : 5;       // 10-14
+    UINT32 reserved8 : 1;       // 15
+    UINT32 BTN_PRESS_TIME : 2;  // 16-17 Button press time out values for PMIC Logic.
+    UINT32 DEBOUNCE : 2;        // 18-19 debounce time for the BTN input signal
+    UINT32 ON_TIME : 2;         // 20-21 Time after BTN is asserted before pmic_en_b
+                                //   is asserted
+    UINT32 PK_EN : 1;           // 22 PMIC On Request Enable
+    UINT32 PK_OVERRIDE : 1;     // 23 PMIC On Request Override
+    UINT32 reserved9 : 8;       // 24-31
+  };
+} IMX_SNVS_LPCR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 MINOR_REV : 8;       // 0-7 SNVS block minor version number
+    UINT32 MAJOR_REV : 8;       // 8-15 SNVS block major version number
+    UINT32 IP_ID : 16;          // 16-31 SNVS block ID (IMX_SNVS_IP_ID)
+  };
+} IMX_SNVS_HPVIDR1_REG;
+
+typedef struct {
+  UINT32 HPLR;            // 0x000 SNVS_HP Lock Register
+  UINT32 HPCOMR;          // 0x004 SNVS_HP Command Register
+  UINT32 HPCR;            // 0x008 SNVS_HP Control Register
+  UINT32 reserved1[2];
+  UINT32 HPSR;            // 0x014 SNVS_HP Status Register
+  UINT32 reserved2[3];
+  UINT32 HPRTCMR;         // 0x024 SNVS_HP Real Time Counter MSB Register
+  UINT32 HPRTCLR;         // 0x028 SNVS_HP Real Time Counter LSB Register
+  UINT32 HPTAMR;          // 0x02C SNVS_HP Time Alarm MSB Register
+  UINT32 HPTALR;          // 0x030 SNVS_HP Time Alarm LSB Register
+  UINT32 LPLR;            // 0x034 SNVS_LP Lock Register
+  UINT32 LPCR;            // 0x038 SNVS_LP Control Register
+  UINT32 reserved3[4];
+  UINT32 LPSR;            // 0x04C SNVS_LP Status Register
+  UINT32 reserved4[3];
+  UINT32 LPSMCMR;         // 0x05C SNVS_LP Secure Monotonic Counter MSB Register
+  UINT32 LPSMCLR;         // 0x060 SNVS_LP Secure Monotonic Counter LSB Register
+  UINT32 reserved5[1];
+  UINT32 LPGPR;           // 0x068 SNVS_LP General Purpose Register
+  UINT32 reserved6[739];
+  UINT32 HPVIDR1;         // 0xBF8 SNVS_HP Version ID Register 1
+  UINT32 HPVIDR2;         // 0xBFC SNVS_HP Version ID Register 2
+} IMX_SNVS_REGISTERS;
+
+// System Reset Controller (SRC)
+#define IMX_SRC_BASE 0x020D8000
+#define IMX_SRC_LENGTH 0x4000
+
+// SCR Register Definition
+// SRC_SCR_REG.warm_rst_bypass_count
+typedef enum {
+  IMX_SCR_WARM_RST_BYPASS_COUNT_DISABLED,
+  IMX_SCR_WARM_RST_BYPASS_COUNT_16,
+  IMX_SCR_WARM_RST_BYPASS_COUNT_32,
+  IMX_SCR_WARM_RST_BYPASS_COUNT_64,
+} IMX_SCR_WARM_RST_BYPASS_COUNT;
+
+// SRC_SCR_REG.mask_wdog_rst
+typedef enum {
+  IMX_SRC_MASK_WDOG_RST_B_MASKED = 0x5,
+  IMX_SRC_MASK_WDOG_RST_B_NOT_MASKED = 0xA,
+} IMX_SRC_MASK_WDOG_RST;
+
+// SRC_SCR_REG.mask_tempsense_reset
+typedef enum {
+  IMX_SRC_MASK_TEMPSENSE_RESET_NOT_MASKED = 0x2,
+  IMX_SRC_MASK_TEMPSENSE_RESET_MASKED = 0x5,
+} IMX_SRC_MASK_TEMPSENSE_RESET;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 warm_reset_enable : 1;     // 0 WARM reset enable bit
+    UINT32 sw_gpu_rst : 1;            // 1 Software reset for GPU
+    UINT32 reserved1 : 1;             // 2
+    UINT32 m4c_rst : 1;               // 3 Self-clearing SW reset for M4 core
+    UINT32 m4c_non_sclr_rst : 1;      // 4 Non-self-clearing SW reset for M4 core
+    UINT32 warm_rst_bypass_count : 2; // 5-6 Defines the XTALI cycles to count
+                                      //   before bypassing the MMDC acknowledge
+                                      //   for WARM reset.
+    UINT32 mask_wdog_rst : 4;         // 7-10 Mask wdog_rst_b source
+    UINT32 eim_rst : 1;               // 11 EIM reset is needed in order to
+                                      //   reconfigure the eim chip select.
+    UINT32 m4p_rst : 1;               // 12 Self-clearing SW reset for M4 platform
+    UINT32 core0_rst : 1;             // 13 Software reset for core0 only
+    UINT32 reserved2 : 3;             // 14-16
+    UINT32 core0_dbg_rst : 1;         // 17 Software reset for core0 debug only.
+    UINT32 mask_tempsense_reset : 3;  // 18-20 Mask tempsense_reset source
+    UINT32 cores_dbg_rst : 1;         // 21 Software reset for debug of arm
+                                      //   platform only
+    UINT32 m4_enable : 1;             // 22 Enable M4 core
+    UINT32 wdog3_rst_optn_m4 : 1;     // 23 wdog3_rst_b option for M4. This bit
+                                      //   is only effective when wdog3_rst_option
+                                      //   is set to 1.
+    UINT32 wdog3_rst_optn : 1;        // 24 Wdog3_rst_b option
+    UINT32 dbg_rst_msk_pg : 1;        // 25 Do not assert debug resets after
+                                      //   power gating event of core
+    UINT32 mix_rst_strch : 2;         // 26-27 SoC mix (Audio, ENET, uSDHC,
+                                      //   EIM, QSPI, OCRAM, MMDC, etc) power up
+                                      //   reset stretch mix reset
+                                      //   width = (mix_rst_strtch +1)* 88 ipg_clk
+                                      //   cycles
+    UINT32 mask_wdog3_rst : 4;        // 28-31 Mask wdog3_rst_b source
+  };
+} IMX_SRC_SCR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 BOOT_CFG1 : 8;   // 0-7
+    UINT32 BOOT_CFG2 : 8;   // 8-15
+    UINT32 BOOT_CFG3 : 8;   // 16-23
+    UINT32 BOOT_CFG4 : 8;   // 24-31
+  };
+} IMX_SRC_SBMR1_REG;
+
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 SEC_COFNIG : 2;    // 0-1
+    UINT32 reserved1 : 1;     // 2
+    UINT32 DIR_BT_DIS : 1;    // 3
+    UINT32 BT_FUSE_SEL : 1;   // 4
+    UINT32 reserved2 : 19;    // 5-23
+    UINT32 BMOD : 2;          // 24-25
+    UINT32 reserved3 : 6;     // 26-31
+  };
+} IMX_SRC_SBMR2_REG;
+
+typedef struct {
+  UINT32 SCR;           // 0x00 SRC Control Register (SRC_SCR)
+  UINT32 SBMR1;         // 0x04 SRC Boot Mode Register 1 (SRC_SBMR1)
+  UINT32 SRSR;          // 0x08 SRC Reset Status Register (SRC_SRSR)
+  UINT32 reserved1[2];
+  UINT32 SISR;          // 0x14 SRC Interrupt Status Register (SRC_SISR)
+  UINT32 SIMR;          // 0x18 SRC Interrupt Mask Register (SRC_SIMR)
+  UINT32 SBMR2;         // 0x1C SRC Boot Mode Register 2 (SRC_SBMR2)
+  UINT32 GPR1;          // 0x20 SRC General Purpose Register 1 (SRC_GPR1)
+  UINT32 GPR2;          // 0x24 SRC General Purpose Register 2 (SRC_GPR2)
+  UINT32 GPR3;          // 0x28 SRC General Purpose Register 3 (SRC_GPR3)
+  UINT32 GPR4;          // 0x2C SRC General Purpose Register 4 (SRC_GPR4)
+  UINT32 GPR5;          // 0x30 SRC General Purpose Register 4 (SRC_GPR5)
+  UINT32 GPR6;          // 0x34 SRC General Purpose Register 4 (SRC_GPR6)
+  UINT32 GPR7;          // 0x38 SRC General Purpose Register 4 (SRC_GPR7)
+  UINT32 GPR8;          // 0x3C SRC General Purpose Register 4 (SRC_GPR8)
+  UINT32 GPR9;          // 0x40 SRC General Purpose Register 4 (SRC_GPR9)
+  UINT32 GPR10;         // 0x44 SRC General Purpose Register 4 (SRC_GPR10)
+} IMX_SRC_REGISTERS;
+
+// Watchdog (WDOG)
+#define IMX_WDOG1_BASE 0x020BC000
+#define IMX_WDOG2_BASE 0x020C0000
+#define IMX_WDOG3_BASE 0x02288000
+#define IMX_WDOG_LENGTH 0x4000
+#define IMX_WDOG_WSR_FEED1 0x5555
+#define IMX_WDOG_WSR_FEED2 0xAAAA
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 WDZST : 1;       // 0 Watchdog Low Power
+    UINT16 WDBG : 1;        // 1 Watchdog DEBUG Enable
+    UINT16 WDE : 1;         // 2 Watchdog Enable
+    UINT16 WDT : 1;         // 3 WDOG_B Time-out assertion.
+    UINT16 SRS : 1;         // 4 Software Reset Signal
+    UINT16 WDA : 1;         // 5 WDOG_B assertion
+    UINT16 reserved1 : 1;   // 6
+    UINT16 WDW : 1;         // 7 Watchdog Disable for Wait
+    UINT16 WT : 8;          // 8-15 Watchdog Time-out Field
+  };
+} IMX_WDOG_WCR_REG;
+
+typedef struct {
+  UINT16 WCR;   // 0x0 Watchdog Control Register (WDOG1_WCR)
+  UINT16 WSR;   // 0x2 Watchdog Service Register (WDOG1_WSR)
+  UINT16 WRSR;  // 0x4 Watchdog Reset Status Register (WDOG1_WRSR)
+  UINT16 WICR;  // 0x6 Watchdog Interrupt Control Register (WDOG1_WICR)
+  UINT16 WMCR;  // 0x8 Watchdog Miscellaneous Control Register (WDOG1_WMCR)
+} IMX_WDOG_REGISTERS;
+
+// Clock Control Module (CCM)
+#define IMX6SX_CCM_CLOCK_OFF    0
+#define IMX6SX_RUN_ONLY         1
+#define IMX6SX_RUN_AND_WAIT     3
+#define IMX_CCM_BASE 0x020C4000
+#define IMX_CCM_LENGTH 0x4000
+#define IMX_CCM_ANALOG_BASE  0x020C8000
+#define IMX_CCM_ANALOG_LENGTH 0x1000
+#define IMX_REF_CLK_24M_FREQ 24000000
+
+typedef enum {
+  IMX_CCM_PLL3_SW_CLK_SEL_PLL3_MAIN_CLK,
+  IMX_CCM_PLL3_SW_CLK_SEL_PLL3_BYPASS_CLK,
+} IMX_CCM_PLL3_SW_CLK_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 pll3_sw_clk_sel : 1; // 0 Selects source to generate pll3_sw_clk
+    UINT32 reserved1 : 1;       // 1
+    UINT32 pll1_sw_clk_sel : 1; // 2 Selects source to generate pll1_sw_clk.
+    UINT32 reserved2 : 5;       // 3-7
+    UINT32 step_sel : 1;        // 8 Selects the option for step frequency
+    UINT32 reserved3 : 23;      // 9-31
+  };
+} IMX_CCM_CCSR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 arm_podf : 3;  // 0-3 Divider for ARM clock root
+    UINT32 reserved : 29; // 3-31
+  };
+} IMX_CCM_CACRR_REG;
+
+// CBCMR.gpu_core_sel
+typedef enum {
+  IMX_CCM_GPU_CLK_SEL_PLL3_PFD1,
+  IMX_CCM_GPU_CLK_SEL_PLL3_PFD0,
+  IMX_CCM_GPU_CLK_SEL_PLL2,
+  IMX_CCM_GPU_CLK_SEL_PLL2_PFD2
+} IMX_CCM_GPU_CLK_SEL;
+
+// CBCMR.gpu_axi_sel
+typedef enum {
+  IMX_CCM_GPU_AXI_SEL_PLL2_PFD2,
+  IMX_CCM_GPU_AXI_SEL_PLL3_PFD0,
+  IMX_CCM_GPU_AXI_SEL_PLL3_PFD1,
+  IMX_CCM_GPU_AXI_SEL_PLL2
+} IMX_CCM_GPU_AXI_SEL;
+
+// CBCMR.pcie_axi_clock_sel
+typedef enum {
+  IMX_CCM_PCIE_AXI_CLOCK_SEL_AXI,
+  IMX_CCM_PCIE_AXI_CLOCK_SEL_AHB,
+} IMX_CCM_PCIE_AXI_CLOCK_SEL;
+
+// CBCMR.periph_clk2_sel
+typedef enum {
+  IMX_CCM_PERIPH_CLK2_SEL_PLL3_SW_CLK,
+  IMX_CCM_PERIPH_CLK2_SEL_OSC_CLK,
+  IMX_CCM_PERIPH_CLK2_SEL_PLL2_BYPASS_CLK
+} IMX_CCM_PERIPH_CLK2_SEL;
+
+// CBCMR.pre_periph_clk_sel
+typedef enum {
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2,
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2,
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD0,
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2,
+} IMX_CCM_PRE_PERIPH_CLK_SEL;
+
+// CBCMR.periph2_clk2_sel
+typedef enum {
+  IMX_CCM_PERIPH2_CLK2_SEL_PLL3_SW_CLK,
+  IMX_CCM_PERIPH2_CLK2_SEL_OSC
+} IMX_CCM_PERIPH2_CLK2_SEL;
+
+// CBCMR.pre_periph2_clk_sel
+typedef enum {
+  IMX_CCM_PRE_PERIPH2_CLK_SEL_PLL2,
+  IMX_CCM_PRE_PERIPH2_CLK_SEL_PLL2_PFD2,
+  IMX_CCM_PRE_PERIPH2_CLK_SEL_PLL2_PFD0,
+  IMX_CCM_PRE_PERIPH2_CLK_SEL_PLL4
+} IMX_CCM_PRE_PERIPH2_CLK_SEL;
+
+// CBCMR.podf (divider for lcdif1_podf, gpu_axi_podf, gpu_core_podf)
+typedef enum {
+  IMX_CCM_PODF_DIV1,
+  IMX_CCM_PODF_DIV2,
+  IMX_CCM_PODF_DIV3,
+  IMX_CCM_PODF_DIV4,
+  IMX_CCM_PODF_DIV5,
+  IMX_CCM_PODF_DIV6,
+  IMX_CCM_PODF_DIV7,
+  IMX_CCM_PODF_DIV8
+} IMX_CCM_PODF;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 4;             // 0-3
+    UINT32 gpu_core_sel : 2;          // 4-5 Selector for gpu_core clock multiplexer
+    UINT32 reserved2 : 2;             // 6-7
+    UINT32 gpu_axi_sel : 2;           // 8-9 Selector for gpu_axi clock multiplexer
+    UINT32 pcie_axi_clock_sel : 1;    // 10 Selector for pcie_axi_clock multiplexier
+    UINT32 reserved3 : 1;             // 11
+    UINT32 periph_clk2_sel : 2;       // 12-13 Selector for peripheral clk2 clock
+                                      //   multiplexer
+    UINT32 reserved4 : 4;             // 14-17
+    UINT32 pre_periph_clk_sel : 2;    // 18-19 Selector for pre_periph clock multiplexer
+    UINT32 periph2_clk2_sel : 1;      // 20 Selector for periph2_clk2 clock multiplexer
+    UINT32 pre_periph2_clk_sel : 2;   // 21-22 Selector for pre_periph2 clock multiplexer
+    UINT32 lcdif1_podf : 3;           // 23-25 Post-divider for lcdif1 clock
+    UINT32 gpu_axi_podf : 3;          // 26-28 Divider for gpu_axi_podf
+    UINT32 gpu_core_podf : 3;         // 29-31 Post divider for gpu_core clock
+  };
+} IMX_CCM_CBCMR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ssi1_clk_podf : 6;   // 0-5 Divider for ssi1 clock podf
+    UINT32 ssi1_clk_pred : 3;   // 6-8 Divider for ssi1 clock pred
+    UINT32 esai_clk_pred : 3;   // 9-11 Divider for esai clock pred
+    UINT32 reserved1 : 4;       // 12-15 Reserved
+    UINT32 ssi3_clk_podf : 6;   // 16-21 Divider for ssi3 clock podf
+    UINT32 ssi3_clk_pred : 3;   // 22-24 Divider for ssi3 clock pred
+    UINT32 esai_clk_podf : 3;   // 25-27 Divider for esai clock podf
+    UINT32 reserved2 : 4;       // 28-31 Reserved
+  };
+} IMX_CCM_CS1CDR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ssi2_clk_podf : 6;     // 0-5 Divider for ssi2 clock podf
+    UINT32 ssi2_clk_pred : 3;     // 6-8 Divider for ssi2 clock pred
+    UINT32 ldb_di0_clk_sel : 3;   // 9-11 Selector for ldb_di0 clock multiplexer
+    UINT32 ldb_di1_clk_sel : 3;   // 12-14 Selector for ldb_di1 clock multiplexer
+    UINT32 qspi2_clk_sel : 3;     // 15-17 Selector for QSPI2 clock multiplexer
+    UINT32 qspi2_clk_pred : 3;    // 18-20 Divider for QSPI1 clock pred divider
+    UINT32 qspi2_clk_podf : 6;    // 21-26 Divider for QSPI2 clock divider
+    UINT32 reserved : 5;          // 27-31
+  };
+} IMX_CCM_CS2CDR_REG;
+
+typedef enum {
+  IMX_CCM_CCGR_OFF = 0x0,     // Clock is off during all modes. Stop enter
+                              //   hardware handshake is disabled.
+  IMX_CCM_CCGR_ON_RUN = 0x1,  // Clock is on in run mode,
+                              //   but off in WAIT and STOP modes
+  IMX_CCM_CCGR_ON = 0x3,      // Clock is on during all modes, except STOP mode.
+} IMX_CCM_CCGR;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 aips_tz1_clk_enable : 2;     // 0-1 aips_tz1 clocks
+    UINT32 aips_tz2_clk_enable : 2;     // 2-3 aips_tz2 clocks
+    UINT32 apbhdma_hclk_enable : 2;     // 4-5 apbhdma hclk clock
+    UINT32 asrc_clk_enable : 2;         // 6-7 asrc clock
+    UINT32 caam_secure_mem_clk_enable : 2; // 8-9 caam_secure_mem clock
+    UINT32 caam_wrapper_aclk_enable : 2; // 10-11 caam_wrapper_aclk clock
+    UINT32 caam_wrapper_ipg_enable : 2; // 12-13 caam_wrapper_ipg clock
+    UINT32 can1_clk_enable : 2;         // 14-15 can1 clock
+    UINT32 can1_serial_clk_enable : 2;  // 16-17 can1_serial clock
+    UINT32 can2_clk_enable : 2;         // 18-19 can2 clock
+    UINT32 can2_serial_clk_enable : 2;  // 20-21 can2_serial clock
+    UINT32 arm_dbg_clk_enable : 2;      // 22-23 CPU debug clocks
+    UINT32 dcic1_clk_enable : 2;        // 24-25 dcic 1 clocks
+    UINT32 dcic2_clk_enable : 2;        // 26-27 dcic2 clocks
+    UINT32 reserved : 2;                // 28-29
+    UINT32 aips_tz3_clk_enable : 2;     // 30-31 aips_tz3 clocks
+  };
+} IMX_CCM_CCGR0_REG;
+
+// CHSCCDR.m4_clk_sel
+typedef enum {
+  IMX_CHSCCDR_M4_CLK_SEL_DIVIDED_PRE_MUXED_M4_CLOCK,
+  IMX_CHSCCDR_M4_CLK_SEL_IPP_DI0_CLK,
+  IMX_CHSCCDR_M4_CLK_SEL_IPP_DI1_CLK,
+  IMX_CHSCCDR_M4_CLK_SEL_LDB_DI0_CLK,
+  IMX_CHSCCDR_M4_CLK_SEL_LDB_DI1_CLK
+} IMX_CHSCCDR_M4_CLK_SEL;
+
+// CHSCCDR.m4_pre_clk_sel
+typedef enum {
+  IMX_M4_PRE_CLK_SEL_PLL2,
+  IMX_M4_PRE_CLK_SEL_PLL3_SW_CLK,
+  IMX_M4_PRE_CLK_SEL_OSC_CLK_24M,
+  IMX_M4_PRE_CLK_SEL_PLL2_PFD0,
+  IMX_M4_PRE_CLK_SEL_PLL2_PFD2,
+  IMX_M4_PRE_CLK_SEL_PLL3_PFD3
+} IMX_M4_PRE_CLK_SEL;
+
+// CHSCCDR.enet_clk_sel
+typedef enum {
+  IMX_ENET_CLK_SEL_DIVIDED_PREMUXED_ENET_CLK,
+  IMX_ENET_CLK_SEL_IPP_DI0_CLK,
+  IMX_ENET_CLK_SEL_IPP_DI1_CLK,
+  IMX_ENET_CLK_SEL_LDB_DI0_CLK,
+  IMX_ENET_CLK_SEL_LDB_DI1_CLK
+} IMX_ENET_CLK_SEL;
+
+// CHSCCDR.enet_pre_clk_sel
+typedef enum {
+  IMX_ENET_PRE_CLK_SEL_PLL2,
+  IMX_ENET_PRE_CLK_SEL_PLL3_SW_CLK,
+  IMX_ENET_PRE_CLK_SEL_PLL5,
+  IMX_ENET_PRE_CLK_SEL_PLL2_PFD0,
+  IMX_ENET_PRE_CLK_SEL_PLL2_PFD2,
+  IMX_ENET_PRE_CLK_SEL_PLL3_PFD2
+} IMX_ENET_PRE_CLK_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 m4_clk_sel : 3;        // 0-2 Selector for M4 root clock multiplexer
+    UINT32 m4_podf : 3;           // 3-5 Divider for M4 clock divider
+    UINT32 m4_pre_clk_sel : 3;    // 6-8 Selector for M4 root clock pre-multiplexer
+    UINT32 enet_clk_sel : 3;      // 9-11 Selector for ENET root clock multiplexer
+    UINT32 enet_podf : 3;         // 12-14 Divider for ENET clock divider
+    UINT32 enet_pre_clk_sel : 3;  // 15-17 Selector for ENET root clock pre-multiplexer
+    UINT32 reserved : 14;         // 18-31
+  };
+} IMX_CCM_CHSCCDR_REG;
+
+// NOTE: OPENVG clock cannot be gated without gating GPU2D clock as well.
+//       Configure both CG bits (CCM_ANALOG_CCGR1[CG12] and
+//       CCM_ANALOG_CCGR3[CG15]) to gate OPENVG.
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ecspi1_clk_enable : 2;       // 0-1 ecspi1 clocks
+    UINT32 ecspi2_clk_enable : 2;       // 2-3 ecspi2 clocks
+    UINT32 ecspi3_clk_enable : 2;       // 4-5 ecspi3 clocks
+    UINT32 ecspi4_clk_enable : 2;       // 6-7 ecspi4 clocks
+    UINT32 ecspi5_clk_enable : 2;       // 8-9 ecspi5 clocks
+    UINT32 reserved1 : 2;               // 10-11
+    UINT32 epit1_clk_enable : 2;        // 12-13 epit1 clocks
+    UINT32 epit2_clk_enable : 2;        // 14-15 epit2 clocks
+    UINT32 esai_clk_enable : 2;         // 16-17 esai clocks
+    UINT32 wakeup_clk_enable : 2;       // 18-19 wakeup clock
+    UINT32 gpt_clk_enable : 2;          // 20-21 gpt bus clock
+    UINT32 gpt_serial_clk_enable : 2;   // 22-23 gpt serial clock
+    UINT32 reserved2 : 2;               // 24-25
+    UINT32 gpu_clk_enable : 2;          // 26-27 gpu clock
+    UINT32 ocram_s_clk_enable : 2;      // 28-29 ocram_s clock
+    UINT32 canfd_clk_enable : 2;        // 30-31 canfd clock
+  };
+} IMX_CCM_CCGR1_REG;
+
+// CBCDR.ocram_clk_sel
+typedef enum {
+  IMX_CCM_OCRAM_CLK_SEL_PERIPH_CLK,
+  IMX_CCM_OCRAM_CLK_SEL_AXI_ALT_CLK
+} IMX_CCM_OCRAM_CLK_SEL;
+
+// CBCDR.ocram_alt_clk_sel
+typedef enum {
+  IMX_CCM_OCRAM_ALT_CLK_SEL_PLL2_PFD2,
+  IMX_CCM_OCRAM_ALT_CLK_SEL_PLL3_PFD1
+} IMX_CCM_OCRAM_ALT_CLK_SEL;
+
+// CBCDR.periph_clk_sel
+typedef enum {
+  IMX_CCM_PERIPH_CLK_SEL_PRE_PERIPH_CLK_SEL,
+  IMX_CCM_PERIPH_CLK_SEL_PERIPH_CLK2_CLK_DIVIDED
+} IMX_CCM_PERIPH_CLK_SEL;
+
+// CBCDR.periph2_clk_sel
+typedef enum {
+  IMX_CCM_PERIPH2_CLK_SEL_PRE_PERIPH2_CLK,
+  IMX_CCM_PERIPH2_CLK_SEL_PERIPH2_CLK2_CLK_DIVIDED
+} IMX_CCM_PERIPH2_CLK_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 periph2_clk2_podf : 3;   // 0-2 Divider for periph2_clk2 podf
+    UINT32 fabric_mmdc_podf : 3;    // 3-5 Post divider for fabric / mmdc clock
+    UINT32 ocram_clk_sel : 1;       // 6 OCRAM clock source select
+    UINT32 ocram_alt_clk_sel : 1;   // 7 OCRAM alternative clock select
+    UINT32 ipg_podf : 2;            // 8-9 Divider for ipg podf
+    UINT32 ahb_podf : 3;            // 10-12 Divider for AHB PODF
+    UINT32 reserved1 : 3;           // 13-15
+    UINT32 ocram_podf : 3;          // 16-18 Post divider for ocram clock
+    UINT32 reserved2 : 6;           // 19-24
+    UINT32 periph_clk_sel : 1;      // 25 Selector for peripheral main clock
+    UINT32 periph2_clk_sel : 1;     // 26 Selector for peripheral2 main clock
+                                    //   (source of mmdc_clk_root )
+    UINT32 periph_clk2_podf : 3;    // 27-29 Divider for periph_clk2_podf
+    UINT32 reserved3 : 2;           // 30-31
+  };
+} IMX_CCM_CBCDR_REG;
+
+// CCOSR.CLKO1_SEL
+typedef enum {
+  IMX_CCM_CLKO1_SEL_VID_CLK_ROOT = 4,
+  IMX_CCM_CLKO1_SEL_OCRAM_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_QSPI2_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_M4_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_ENET_AXI_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_LCDIF2_PIX_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_LCDIF1_PIX_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_AHB_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_IPG_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_PERCLK_ROOT,
+  IMX_CCM_CLKO1_SEL_CKIL_SYNC_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_PLL4_MAIN_CLK
+} IMX_CCM_CLKO1_SEL;
+
+// CCOSR.CLKO2_SEL
+typedef enum {
+  IMX_CCM_CLKO2_SEL_MMDC_CLK_ROOT = 1,
+  IMX_CCM_CLKO2_SEL_USDHC4_CLK_ROOT = 2,
+  IMX_CCM_CLKO2_SEL_USDHC1_CLK_ROOT = 3,
+  IMX_CCM_CLKO2_SEL_WRCK_CLK_ROOT = 5,
+  IMX_CCM_CLKO2_SEL_ECSPI_CLK_ROOT = 6,
+  IMX_CCM_CLKO2_SEL_USDHC3_CLK_ROOT = 8,
+  IMX_CCM_CLKO2_SEL_PCIE_CLK_ROOT = 9,
+  IMX_CCM_CLKO2_SEL_ARM_CLK_ROOT = 10,
+  IMX_CCM_CLKO2_SEL_CSI_CORE = 11,
+  IMX_CCM_CLKO2_SEL_DISPLAY_AXI_CLK_ROOT = 12,
+  IMX_CCM_CLKO2_SEL_OSC_CLK = 14,
+  IMX_CCM_CLKO2_SEL_USDHC2_CLK_ROOT = 17,
+  IMX_CCM_CLKO2_SEL_SSI1_CLK_ROOT = 18,
+  IMX_CCM_CLKO2_SEL_SSI2_CLK_ROOT = 19,
+  IMX_CCM_CLKO2_SEL_SSI3_CLK_ROOT = 20,
+  IMX_CCM_CLKO2_SEL_GPU_AXI_CLK_ROOT = 21,
+  IMX_CCM_CLKO2_SEL_CAN_CLK_ROOT = 23,
+  IMX_CCM_CLKO2_SEL_LVDS_CLK_ROOT = 24,
+  IMX_CCM_CLKO2_SEL_QSPI1_CLK_ROOT = 25,
+  IMX_CCM_CLKO2_SEL_ESAI_CLK_ROOT = 26,
+  IMX_CCM_CLKO2_SEL_ACLK_EIM_SLOW_CLK_ROOT = 27,
+  IMX_CCM_CLKO2_SEL_UART_CLK_ROOT = 28,
+  IMX_CCM_CLKO2_SEL_SPDIF0_CLK_ROOT = 29,
+  IMX_CCM_CLKO2_SEL_AUDIO_CLK_ROOT = 36
+} IMX_CCM_CLKO2_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CLKO1_SEL : 4;     // 0-3 Selection of the clock to be generated on CCM_CLKO1
+    UINT32 CLKO1_DIV : 3;     // 4-6 Setting the divider of CCM_CLKO1
+    UINT32 CLKO1_EN : 1;      // 7 Enable of CCM_CLKO1 clock
+    UINT32 CLK_OUT_SEL : 1;   // 8 CCM_CLKO1 output to reflect CCM_CLKO1 or CCM_CLKO2 clocks
+    UINT32 reserved1 : 7;     // 9-15
+    UINT32 CLKO2_SEL : 5;     // 16-20 Selection of the clock to be generated on CCM_CLKO2
+    UINT32 CLKO2_DIV : 3;     // 21-23 Setting the divider of CCM_CLKO2
+    UINT32 CLKO2_EN : 1;      // 24 Enable of CCM_CLKO2 clock
+    UINT32 reserved2 : 7;     // 25-31
+  };
+} IMX_CCM_CCOSR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 2;                 // 0-1
+    UINT32 csi_clk_enable : 2;            // 2-3 csi clock
+    UINT32 reserved2 : 2;                 // 4-5
+    UINT32 i2c1_serial_clk_enable : 2;    // 6-7 i2c1_serial clock
+    UINT32 i2c2_serial_clk_enable : 2;    // 8-9 i2c2_serial clock
+    UINT32 i2c3_serial_clk_enable : 2;    // 10-11 i2c3_serial clock
+    UINT32 iim_clk_enable : 2;            // 12-13 OCOTP_CTRL clock
+    UINT32 iomux_ipt_clk_io_enable : 2;   // 14-15 iomux_ipt_clk_io clock
+    UINT32 ipmux1_clk_enable : 2;         // 16-17 ipmux1 clock
+    UINT32 ipmux2_clk_enable : 2;         // 18-19 ipmux2 clock
+    UINT32 ipmux3_clk_enable : 2;         // 20-21 ipmux3 clock
+    UINT32 ipsync_ip2apb_tzasc1_ipg_master_clk_enable : 2;  // 22-23 ipsync_ip2apb_tzasc1_ipg clocks
+    UINT32 reserved3 : 2;                 // 24-25
+    UINT32 reserved4 : 2;                 // 26-27
+    UINT32 lcd_clk_enable : 2;            // 28-29 lcd clocks
+    UINT32 pxp_clk_enable : 2;            // 30-31 pxp clocks
+  };
+} IMX_CCM_CCGR2_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 2;                          // 0-1
+    UINT32 m4_clk_enable : 2;                      // 2-3 m4 clock
+    UINT32 enet_clk_enable : 2;                    // 4-5 enet clock
+    UINT32 disp_axi_clk_enable : 2;                // 6-7 display axi clock
+    UINT32 lcdif2_pix_clk_enable : 2;              // 8-9 lcdif2 pix clock
+    UINT32 lcdif1_pix_clk_enable : 2;              // 10-11 lcdif1 pix clock
+    UINT32 ldb_di0_clk_enable : 2;                 // 12-13 ldb_di0 clock
+    UINT32 qspi1_clk_enable : 2;                   // 14-15 qspi1 clock
+    UINT32 reserved2 : 2;                          // 16-17
+    UINT32 mlb_clk_enable : 2;                     // 18-19 mlb clock
+    UINT32 mmdc_core_aclk_fast_core_p0_enable : 2; // 20-21 mmdc_core_aclk_fast_core_p0 clock
+    UINT32 reserved3 : 2;                          // 22-23
+    UINT32 mmdc_core_ipg_clk_p0_enable : 2;        // 24-25 mmdc_core_ipg_clk_p0 clock
+    UINT32 mmdc_core_ipg_clk_p1_enable : 2;        // 26-27 mmdc_core_ipg_clk_p1 clock
+    UINT32 ocram_clk_enable : 2;                   // 28-29 ocram clock
+    UINT32 reserved4 : 2;                          // 30-31
+  };
+} IMX_CCM_CCGR3_REG;
+
+typedef enum {
+  IMX_CCM_PERCLK_CLK_SEL_IPG_CLK_ROOT = 0,
+  IMX_CCM_PERCLK_CLK_SEL_OSC_CLK = 1
+} IMX_CCM_PERCLK_CLK_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32  perclk_podf         : 6;  // 0-5 Divider for perclk podf.
+    UINT32  perclk_clk_sel      : 1;  // 6 Selector for the perclk clock multiplexor
+    UINT32  qspi1_sel           : 3;  // 7-9 QSPI1 clock select
+    UINT32  ssi1_clk_sel        : 2;  // 10-11 Selector for ssi1 clock multiplexer
+    UINT32  ssi2_clk_sel        : 2;  // 12-13 Selector for ssi2 clock multiplexer
+    UINT32  ssi3_clk_sel        : 2;  // 14-15 Selector for ssi3 clock multiplexer
+    UINT32  usdhc1_clk_sel      : 1;  // 16 Selector for usdhc1 clock multiplexer
+    UINT32  usdhc2_clk_sel      : 1;  // 17 Selector for usdhc2 clock multiplexer
+    UINT32  usdhc3_clk_sel      : 1;  // 18 Selector for usdhc3 clock multiplexe
+    UINT32  usdhc4_clk_sel      : 1;  // 19 Selector for usdhc4 clock multiplexer
+    UINT32  lcdif2_podf         : 3;  // 20-22 Post-divider for lcdif2 clock.
+    UINT32  aclk_eim_slow_podf  : 3;  // 23-25 Divider for aclk_eim_slow clock root.
+    UINT32  qspi1_podf          : 3;  // 26-28 Divider for QSPI1 clock root
+    UINT32  aclk_eim_slow_sel   : 2;  // 29-30 Selector for aclk_eim_slow root clock
+                                      //   multiplexer
+    UINT32  reserved1           : 1;  // 31
+  };
+} IMX_CCM_CSCMR1_REG;
+
+typedef struct {
+  UINT32 CCR;           // 0x00 CCM Control Register
+  UINT32 CCDR;          // 0x04 CCM Control Divider Register
+  UINT32 CSR;           // 0x08 CCM Status Register
+  UINT32 CCSR;          // 0x0C CCM Clock Switcher Register
+  UINT32 CACRR;         // 0x10 CCM Arm Clock Root Register
+  UINT32 CBCDR;         // 0x14 CCM Bus Clock Divider Register
+  UINT32 CBCMR;         // 0x18 CCM Bus Clock Multiplexer Register
+  UINT32 CSCMR1;        // 0x1C CCM Serial Clock Multiplexer Register 1
+  UINT32 CSCMR2;        // 0x20 CCM Serial Clock Multiplexer Register 2
+  UINT32 CSCDR1;        // 0x24 CCM Serial Clock Divider Register 1
+  UINT32 CS1CDR;        // 0x28 CCM SSI1 Clock Divider Register
+  UINT32 CS2CDR;        // 0x2C CCM SSI2 Clock Divider Register
+  UINT32 CDCDR;         // 0x30 CCM D1 Clock Divider Register
+  UINT32 CHSCCDR;       // 0x34 CCM HSC Clock Divider Register
+  UINT32 CSCDR2;        // 0x38 CCM Serial Clock Divider Register 2
+  UINT32 CSCDR3;        // 0x3C CCM Serial Clock Divider Register 3
+  UINT32 reserved1;
+  UINT32 CWDR;          // 0x44 CCM Wakeup Detector Register
+  UINT32 CDHIPR;        // 0x48 CCM Divider Handshake In-Process Register
+  UINT32 reserved2[2];
+  UINT32 CLPCR;         // 0x54 CCM Low Power Control Register
+  UINT32 CISR;          // 0x58 CCM Interrupt Status Register
+  UINT32 CIMR;          // 0x5C CCM Interrupt Mask Register
+  UINT32 CCOSR;         // 0x60 CCM Clock Output Source Register
+  UINT32 CGPR;          // 0x64 CCM General Purpose Register
+  UINT32 CCGR[7];       // 0x68-80 CCM Clock Gating Register 0-6
+  UINT32 reserved3;
+  UINT32 CMEOR;         // 0x88 CCM Module Enable Override Register
+} IMX_CCM_REGISTERS;
+
+// CCM Analog
+typedef enum {
+  IMX_PLL_BYPASS_CLK_SRC_REF_CLK_24M,
+  IMX_PLL_BYPASS_CLK_SRC_CLK1,
+  IMX_PLL_BYPASS_CLK_SRC_GPANAIO,     // Only for CCM_ANALOG_PLL_SYS
+                                      //   and CCM_ANALOG_PLL_USB1n
+  IMX_PLL_BYPASS_CLK_SRC_CHRG_DET_B   // Only for CCM_ANALOG_PLL_SYS
+                                      //   and CCM_ANALOG_PLL_USB1n
+} IMX_PLL_BYPASS_CLK_SRC;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PFD0_FRAC : 6;     // 0-5 fractional divide value. The resulting
+                              //   frequency shall be 528*18/PFD0_FRAC where
+                              //   PFD0_FRAC is in the range 12-35.
+    UINT32 PFD0_STABLE : 1;   // 6
+    UINT32 PFD0_CLKGATE : 1;  // 7 Set to 1 to gate ref_pfd0
+    UINT32 PFD1_FRAC : 6;     // 8-13 fractional divide value
+    UINT32 PFD1_STABLE : 1;   // 14
+    UINT32 PFD1_CLKGATE : 1;  // 15 Set to 1 to gate ref_pfd1
+    UINT32 PFD2_FRAC : 6;     // 16-21 fractional divide value
+    UINT32 PFD2_STABLE : 1;   // 22
+    UINT32 PFD2_CLKGATE : 1;  // 23 Set to 1 to gate ref_pfd2
+    UINT32 PFD3_FRAC : 6;     // 24-29 fractional divide value
+    UINT32 PFD3_STABLE : 1;   // 30
+    UINT32 PFD3_CLKGATE : 1;  // 31 Set to 1 to gate ref_pfd3
+  };
+} IMX_CCM_PFD_480_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PFD0_FRAC : 6;     // 0-5 fractional divide value. The resulting
+                              //   frequency shall be 528*18/PFD0_FRAC where
+                              //   PFD0_FRAC is in the range 12-35.
+    UINT32 PFD0_STABLE : 1;   // 6
+    UINT32 PFD0_CLKGATE : 1;  // 7 Set to 1 to gate ref_pfd0
+    UINT32 PFD1_FRAC : 6;     // 8-13 fractional divide value
+    UINT32 PFD1_STABLE : 1;   // 14
+    UINT32 PFD1_CLKGATE : 1;  // 15 Set to 1 to gate ref_pfd1
+    UINT32 PFD2_FRAC : 6;     // 16-21 fractional divide value
+    UINT32 PFD2_STABLE : 1;   // 22
+    UINT32 PFD2_CLKGATE : 1;  // 23 Set to 1 to gate ref_pfd2
+    UINT32 PFD3_FRAC : 6;     // 24-29 fractional divide value. The resulting
+                              //   frequency shall be 528*18/PFD3_FRAC where
+                              //   PFD3_FRAC is in the range 12-35
+    UINT32 PFD3_STABLE : 1;   // 30
+    UINT32 PFD3_CLKGATE : 1;  // 31 Set to 1 to gate ref_pfd3
+  };
+} IMX_CCM_PFD_528_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 7;      // 0-6  Valid range for divider value: 54-108.
+                                //   Fout = Fin * div_select/2.0
+    UINT32 reserved1 : 5;       // 7-11
+    UINT32 POWERDOWN : 1;       // 12 Powers down the PLL.
+    UINT32 ENABLE: 1;           // 13 Enable the clock output.
+    UINT32 BYPASS_CLK_SRC : 2;  // 14-15 Determines the bypass and PLL reference
+                                //   clock source.
+    UINT32 BYPASS : 1;          // 16 Bypass the PLL.
+    UINT32 LVDS_SEL : 1;        // 17 Analog Debug Bit
+    UINT32 LVDS_24MHZ_SEL : 1;  // 18 Analog Debug Bit
+    UINT32 reserved2 : 1;       // 19 PLL_SEL (Reserved)
+    UINT32 reserved3 : 11;      // 20-30
+    UINT32 LOCK : 1;            // 31 1 - PLL is currently locked. 0 - PLL is
+                                //   not currently locked.
+  };
+} IMX_CCM_ANALOG_PLL_ARM_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 1;      // 0 0 - Fout=Fref*20; 1 - Fout=Fref*22.
+    UINT32 reserved1 : 11;      // 1-11
+    UINT32 POWERDOWN : 1;       // 12 Powers down the PLL.
+    UINT32 ENABLE : 1;          // 13 Enable PLL output
+    UINT32 BYPASS_CLK_SRC : 2;  // 14-15 Determines the bypass source.
+    UINT32 BYPASS : 1;          // 16 Bypass the PLL.
+    UINT32 reserved2 : 1;       // 17
+    UINT32 PFD_OFFSET_EN : 1;   // 18 Enables an offset in the phase frequency detector
+    UINT32 reserved3 : 12;      // 19-30
+    UINT32 LOCK : 1;            // 31 1 - PLL is currently locked; 0 - PLL is
+                                //   not currently locked.
+  };
+} IMX_CCM_ANALOG_PLL_SYS_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 2;      // 0-1 - Fout=Fref*20; 1 - Fout=Fref*22.
+    UINT32 reserved1 : 4;       // 2-5
+    UINT32 EN_USB_CLKS : 1;     // 6 Powers the 9-phase PLL outputs for USBPHYn
+    UINT32 reserved2 : 5;       // 7-11
+    UINT32 POWER : 1;           // 12 Powers up the PLL.
+    UINT32 ENABLE : 1;          // 13 Enable the PLL clock output
+    UINT32 BYPASS_CLK_SRC : 2;  // 14-15 Determines the bypass source
+    UINT32 BYPASS : 1;          // 16 Bypass the PLL.
+    UINT32 reserved3 : 14;      // 17-30
+    UINT32 LOCK : 1;            // 31 1 - PLL is currently locked
+  };
+} IMX_CCM_ANALOG_PLL_USB1_REG;
+
+typedef enum {
+  IMX_POST_DIV_SELECT_DIVIDE_4,
+  IMX_POST_DIV_SELECT_DIVIDE_2,
+  IMX_POST_DIV_SELECT_DIVIDE_1,
+} IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 7;        // 0-6 This field controls the PLL loop divider.
+                                  //   Valid range for DIV_SELECT divider value: 27~54
+    UINT32 Reserved1 : 5;         // 7-11
+    UINT32 POWERDOWN : 1;         // 12 Powers down the PLL
+    UINT32 ENABLE : 1;            // 13 Enalbe PLL output
+    UINT32 BYPASS_CLK_SRC : 2;    // 14-15 Determines the bypass source
+    UINT32 BYPASS : 1;            // 16 Bypass the PLL
+    UINT32 Reserved2 : 1;         // 17
+    UINT32 PFD_OFFSET_EN : 1;     // 18 Enables an offset in the phase frequency
+                                  //   detector
+    UINT32 POST_DIV_SELECT : 2;   // 19-20 These bits implement a divider after
+                                  //   the PLL, but before the enable and bypass mux.
+    UINT32 Reserved3 : 1;         // 21
+    UINT32 Reserved4 : 9;         // 22-30 Always set to zero
+    UINT32 LOCK : 1;              // 31 PLL is/not currently locked
+  };
+} IMX_CCM_PLL_VIDEO_CTRL_REG;
+
+// Power Management Unit
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 REG0_TARG : 5;   // 0-4 target voltage for the ARM core power domain
+    UINT32 reserved1 : 4;   // 5-8
+    UINT32 REG1_TARG : 5;   // 9-13 target voltage for the VPU/GPU power domain
+    UINT32 reserved2 : 4;   // 14-17
+    UINT32 REG2_TARG : 5;   // 18-22 target voltage for the SOC power domain
+    UINT32 reserved3 : 4;   // 23-26
+    UINT32 RAMP_RATE : 2;   // 27-28 Regulator voltage ramp rate
+    UINT32 FET_ODRIVE : 1;  // 29 increases the gate drive on power gating FET
+    UINT32 reserved4 : 2;   // 30-31
+  };
+} IMX_PMU_REG_CORE_REG;
+
+typedef enum {
+  PLL_ENET_DIV_SELECT_25MHZ = 0,
+  PLL_ENET_DIV_SELECT_50MHZ = 1,
+  PLL_ENET_DIV_SELECT_100MHZ = 2,
+  PLL_ENET_DIV_SELECT_125MHZ = 3,
+} CCM_ANALOG_PLL_ENET_DIV_SELECT;
+
+// CCM ANALOG PLL Ethernet(n) register
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 2;       // 0-1
+    UINT32 Zero1 : 5;            // 2-6
+    UINT32 Reserved1 : 5;        // 7-11
+    UINT32 POWERDOWN : 1;        // 12
+    UINT32 ENABLE : 1;           // 13
+    UINT32 BYPASS_CLK_SRC : 2;   // 14-15
+    UINT32 BYPASS : 1;           // 16
+    UINT32 Reserved2 : 1;        // 17
+    UINT32 PFD_OFFSET_EN : 1;    // 18
+    UINT32 ENABLE_125M : 1;      // 19
+    UINT32 ENABLE_100M : 1;      // 20
+    UINT32 Zero2 : 10;           // 21-30
+    UINT32 LOCK : 1;             // 31
+  };
+} IMX_CCM_ANALOG_PLL_ENET_REG;
+
+// CCM ANALOG PLL Ethernet(n) register
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 LVDS1_CLK_SEL : 5;    // 0-4
+    UINT32 LVDS2_CLK_SEL : 5;    // 5-9
+    UINT32 LVDSCLK1_OBEN : 1;    // 10
+    UINT32 LVDSCLK2_OBEN : 1;    // 11
+    UINT32 LVDSCLK1_IBEN : 1;    // 12
+    UINT32 LVDSCLK2_IBEN : 1;    // 13
+    UINT32 Reserved0 : 15;       // 14-28
+    UINT32 IRQ_TEMPSENSE : 1;    // 29
+    UINT32 IRQ_ANA_BO : 1;       // 30
+    UINT32 IRQ_DIG_BO : 1;       // 31
+  };
+} IMX_CCM_ANALOG_MISC1_REG;
+
+typedef struct {
+  UINT32 PLL_ARM;           // 0x000 Analog ARM PLL control Register
+  UINT32 PLL_ARM_SET;       // 0x004 Analog ARM PLL control Register
+  UINT32 PLL_ARM_CLR;       // 0x008 Analog ARM PLL control Register
+  UINT32 PLL_ARM_TOG;       // 0x00C Analog ARM PLL control Register
+  UINT32 PLL_USB1;          // 0x010 Analog USB1 480MHz PLL Control Register
+  UINT32 PLL_USB1_SET;      // 0x014 Analog USB1 480MHz PLL Control Register
+  UINT32 PLL_USB1_CLR;      // 0x018 Analog USB1 480MHz PLL Control Register
+  UINT32 PLL_USB1_TOG;      // 0x01C Analog USB1 480MHz PLL Control Register
+  UINT32 PLL_USB2;          // 0x020 Analog USB2 480MHz PLL Control Register
+  UINT32 PLL_USB2_SET;      // 0x024 Analog USB2 480MHz PLL Control Register
+  UINT32 PLL_USB2_CLR;      // 0x028 Analog USB2 480MHz PLL Control Register
+  UINT32 PLL_USB2_TOG;      // 0x02C Analog USB2 480MHz PLL Control Register
+  UINT32 PLL_SYS;           // 0x030 Analog System PLL Control Register
+  UINT32 PLL_SYS_SET;       // 0x034 Analog System PLL Control Register
+  UINT32 PLL_SYS_CLR;       // 0x038 Analog System PLL Control Register
+  UINT32 PLL_SYS_TOG;       // 0x03C Analog System PLL Control Register
+  UINT32 PLL_SYS_SS;        // 0x040 528MHz System PLL Spread Spectrum Register
+  UINT32 reserved1[11];
+  UINT32 PLL_AUDIO;         // 0x070 Analog Audio PLL control Register
+  UINT32 PLL_AUDIO_SET;     // 0x074 Analog Audio PLL control Register
+  UINT32 PLL_AUDIO_CLR;     // 0x078 Analog Audio PLL control Register
+  UINT32 PLL_AUDIO_TOG;     // 0x07C Analog Audio PLL control Register
+  UINT32 PLL_AUDIO_NUM;     // 0x080 Numerator of Audio PLL Fractional Loop Divider
+                            //   Register
+  UINT32 reserved2[3];
+  UINT32 PLL_AUDIO_DENOM;   // 0x090 Denominator of Audio PLL Fractional Loop
+                            //   Divider Register
+  UINT32 reserved3[3];
+  UINT32 PLL_VIDEO;         // 0x0A0 Analog Video PLL control Register
+  UINT32 PLL_VIDEO_SET;     // 0x0A4 Analog Video PLL control Register
+  UINT32 PLL_VIDEO_CLR;     // 0x0A8 Analog Video PLL control Register
+  UINT32 PLL_VIDEO_TOG;     // 0x0AC Analog Video PLL control Register
+  UINT32 PLL_VIDEO_NUM;     // 0x0B0 Numerator of Video PLL Fractional Loop Divider
+                            //   Register
+  UINT32 reserved4[3];
+  UINT32 PLL_VIDEO_DENOM;   // 0x0C0 Denominator of Video PLL Fractional Loop
+                            //   Divider Register
+  UINT32 reserved5[7];
+  UINT32 PLL_ENET;          // 0x0E0 Analog ENET PLL Control Register
+  UINT32 PLL_ENET_SET;      // 0x0E4 Analog ENET PLL Control Register
+  UINT32 PLL_ENET_CLR;      // 0x0E8 Analog ENET PLL Control Register
+  UINT32 PLL_ENET_TOG;      // 0x0EC Analog ENET PLL Control Register
+  UINT32 PFD_480;           // 0x0F0 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_480_SET;       // 0x0F4 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_480_CLR;       // 0x0F8 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_480_TOG;       // 0x0FC 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_528;           // 0x100 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_528_SET;       // 0x104 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_528_CLR;       // 0x108 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register
+  UINT32 PFD_528_TOG;       // 0x10C 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register
+  UINT32 reserved6[16];
+  UINT32 MISC0;             // 0x150 Miscellaneous Register 0
+  UINT32 MISC0_SET;         // 0x154 Miscellaneous Register 0
+  UINT32 MISC0_CLR;         // 0x158 Miscellaneous Register 0
+  UINT32 MISC0_TOG;         // 0x15C Miscellaneous Register 0
+  UINT32 MISC1;             // 0x160 Miscellaneous Register 1
+  UINT32 MISC1_SET;         // 0x164 Miscellaneous Register 1
+  UINT32 MISC1_CLR;         // 0x168 Miscellaneous Register 1
+  UINT32 MISC1_TOG;         // 0x16C Miscellaneous Register 1
+  UINT32 MISC2;             // 0x170 Miscellaneous Register 2
+  UINT32 MISC2_SET;         // 0x174 Miscellaneous Register 2
+  UINT32 MISC2_CLR;         // 0x178 Miscellaneous Register 2
+  UINT32 MISC2_TOG;         // 0x17C Miscellaneous Register 2
+} IMX_CCM_ANALOG_REGISTERS;
+
+// General Power Controller (GPC)
+#define IMX_GPC_BASE 0x020DC000
+#define IMX_GPC_LENGTH 0x1000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PCR : 1;         // 0 Power Control
+    UINT32 reserved : 31;   // 1-31
+  };
+} IMX_GPC_PGC_PGCR_REG;
+
+#define IMX_GPC_PGC_PUPSCR_SW_DEFAULT 1
+#define IMX_GPC_PGC_PUPSCR_SW2ISO_DEFAULT 0xf
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 SW : 6;            // 0-5 number of IPG clock cycles before asserting
+                              //   power toggle on/off signal (switch_b)
+    UINT32 reserved1 : 2;     // 6-7
+    UINT32 SW2ISO : 6;        // 8-13 IPG clock cycles before negating isolation
+    UINT32 reserved2 : 18;    // 14-31
+  };
+} IMX_GPC_PGC_PUPSCR_REG;
+
+#define IMX_GPC_PGC_PDNSCR_ISO_DEFAULT 1
+#define IMX_GPC_PGC_PDNSCR_ISO2SW_DEFAULT 1
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ISO : 6;         // 0-5 number of IPG clocks before isolation
+    UINT32 reserved1 : 2;   // 6-7
+    UINT32 ISO2SW : 6;      // 8-13 number of IPG clocks before negating power
+                            //   toggle on/off signal (switch_b)
+    UINT32 reserved2 : 18;  // 14-31
+  };
+} IMX_GPC_PGC_PDNSCR_REG;
+
+typedef struct {
+  UINT32 CTRL;      // 0x0 PGC Control Register (PGC_GPU/CPU_CTRL)
+  UINT32 PUPSCR;    // 0x4 Power Up Sequence Control Register (PGC_GPU/CPU_PUPSCR)
+  UINT32 PDNSCR;    // 0x8 Pull Down Sequence Control Register (PGC_GPU/CPU_PDNSCR)
+  UINT32 SR;        // 0xC Power Gating Controller Status Register (PGC_GPU/CPU_SR)
+} IMX_GPC_PGC_REGISTERS;
+
+// General Power Controller (GPC)
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 gpu_vpu_pdn_req : 1;   // 0 GPU/VPU Power Down request. Self-cleared bit.
+    UINT32 gpu_vpu_pup_req : 1;   // 1 GPU/VPU Power Up request. Self-cleared bit.
+    UINT32 MEGA_PDN_REQ : 1;      // 2 MEGA domain power down request. Self-clear bit.
+    UINT32 MEGA_PUP_REQ : 1;      // 3 MEGA domain power up request. Self-clear bit.
+    UINT32 DISPLAY_PDN_REQ : 1;   // 4 Display Power Down request. Self-cleared bit.
+    UINT32 DISPLAY_PUP_REQ : 1;   // 5 Display Power Up request. Self-cleared bit.
+    UINT32 PCIE_PHY_PDN_REQ : 1;  // 6 PCIE PHY power down request. Self-clear bit.
+    UINT32 PCIE_PHY_PUP_REQ : 1;  // 7 PCIE PHY power up request. Self-clear bit.
+    UINT32 reserved1 : 8;         // 8-15
+    UINT32 DVFS0CR : 1;           // 16 DVFS0 (ARM) Change request (bit is read-only)
+    UINT32 VADC_ANALOG_OFF : 1;   // 17 Indication to VADC whether the analog power
+                                  //   to VADC is available or not
+    UINT32 VADC_EXT_PWD_N : 1;    // 18 VADC power down bit
+    UINT32 reserved2 : 2;         // 19-20
+    UINT32 GPCIRQM : 1;           // 21 GPC interrupt/event masking
+    UINT32 L2_PGE : 1;            // 22 L2 Cache Power Gate Enable
+    UINT32 reserved3 : 9;         // 23-31
+  };
+} IMX_GPC_CNTR_REG;
+
+typedef struct {
+  UINT32 CNTR;                    // 0x000 GPC Interface control register (GPC_CNTR)
+  UINT32 PGR;                     // 0x004 GPC Power Gating Register (GPC_PGR)
+  UINT32 IMR1;                    // 0x008 IRQ masking register 1 (GPC_IMR1)
+  UINT32 IMR2;                    // 0x00C IRQ masking register 2 (GPC_IMR2)
+  UINT32 IMR3;                    // 0x010 IRQ masking register 3 (GPC_IMR3)
+  UINT32 IMR4;                    // 0x014 IRQ masking register 4 (GPC_IMR4)
+  UINT32 ISR1;                    // 0x018 IRQ status resister 1 (GPC_ISR1)
+  UINT32 ISR2;                    // 0x01C IRQ status resister 2 (GPC_ISR2)
+  UINT32 ISR3;                    // 0x020 IRQ status resister 3 (GPC_ISR3)
+  UINT32 ISR4;                    // 0x024 IRQ status resister 4 (GPC_ISR4)
+  UINT32 reserved1[142];
+  IMX_GPC_PGC_REGISTERS PGC_GPU;  // 0x260-0x26C GPU PGC Control
+  UINT32 reserved2[12];
+  IMX_GPC_PGC_REGISTERS PGC_CPU;  // 0x2A0-0x2AC CPU PGC Control
+} IMX_GPC_REGISTERS;
+
+// Ethernet controller (ENET)
+#define IMX_ENET_BASE 0x02188000
+#define IMX_ENET_LENGTH 0x4000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 RESET : 1;       // 0 Ethernet MAC Reset
+    UINT32 ETHEREN : 1;     // 1 Ethernet Enable
+    UINT32 MAGICEN : 1;     // 2 Magic Packet Detection Enable
+    UINT32 SLEEP : 1;       // 3 Sleep Mode Enable
+    UINT32 EN1588 : 1;      // 4 EN1588 Enable
+    UINT32 SPEED : 1;       // 5 Selects between 10/100 and 1000 Mbps modes of operation
+    UINT32 DBGEN : 1;       // 6 Debug Enable
+    UINT32 reserved1 : 1;   // 7
+    UINT32 DBSWP : 1;       // 8 Descriptor Byte Swapping Enable
+    UINT32 SVLANEN : 1;     // 9 Enable additional detection of S-VLAN tag according
+                            //   to IEEE802.1Q
+    UINT32 VLANUSE2ND : 1;  // 10 VLAN use second tag
+    UINT32 SVLANDBL : 1;    // 11 S-VLAN double tag
+    UINT32 reserved2 : 4;   // 12-15 This field must be set to 0
+    UINT32 TXC_DLY : 1;     // 16 Transmit clock delay
+    UINT32 RXC_DLY : 1;     // 17 Receive clock delay
+    UINT32 reserved3 : 14;  // 18-31 This field must be set to 01110000000000b = 0x1C00
+  };
+} IMX_ENET_ECR_REG;
+
+#define IMX_ENET_ECR_REG_SET_RESERVED(ecrReg) (ecrReg)->reserved3 = 0x1C00
+
+typedef struct {
+  UINT32 reserved0;     // 0
+  UINT32 EIR;           // 4
+  UINT32 EIMR;          // 8
+  UINT32 reserved1;     // Ch
+  UINT32 RDAR;          // 10h
+  UINT32 TDAR;          // 14h
+  UINT32 reserved2[3];  // 18h - 20h
+  UINT32 ECR;           // 24h Ethernet Control Register (ENET_ECR)
+  UINT32 reserved3[6];  // 28h - 3Ch
+  UINT32 MMFR;          // 40h
+  UINT32 MSCR;          // 44h
+  UINT32 reserved4[7];  // 48h - 60h
+  UINT32 MIBC;          // 64h
+  UINT32 reserved5[7];  //
+  UINT32 RCR;           // 84h
+  UINT32 reserved6[15]; //
+  UINT32 TCR;           // C4h
+  UINT32 reserved7[7];
+  UINT32 PALR;          // E4h
+  UINT32 PAUR;          // E8h
+  UINT32 OPD;           // ECh
+  UINT32 reserved8[322];
+} IMX_ENET_REGISTERS;
+
+// GPIO Controller (GPIO)
+#define IMX_GPIO_BASE 0x0209C000
+#define IMX_GPIO_LENGTH (7 * 0x4000)
+
+// USB CORE (EHCI)
+#define IMX_USBCORE_BASE 0x02184000
+#define IMX_USBCORE_LENGTH 0x200
+#define IMX_USBCMD_OFFSET 0x140
+#define IMX_USBMODE_OFFSET 0x1A8
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 RS : 1;          // 0 Run/Stop (RS) . Read/Write. Default 0b. 1=Run. 0=Stop.
+    UINT32 RST : 1;         // 1 Controller Reset (RESET) - Read/Write.
+    UINT32 FS_1 : 2;        // 2-3 Frame List Size (Read/Write or Read Only). Default 000b.
+    UINT32 PSE : 1;         // 4 Periodic Schedule Enable- Read/Write. Default 0b.
+    UINT32 ASE : 1;         // 5 Asynchronous Schedule Enable Read/Write. Default 0b.
+    UINT32 IAA : 1;         // 6 Interrupt on Async Advance Doorbell Read/Write.
+    UINT32 reserved1 : 1;   // 7
+    UINT32 ASP : 2;         // 8-9 Asynchronous Schedule Park Mode Count (OPTIONAL)
+    UINT32 reserved2 : 1;   // 10
+    UINT32 ASPE : 1;        // 11 Asynchronous Schedule Park Mode Enable (OPTIONAL)
+    UINT32 ATDTW : 1;       // 12 Add dTD TripWire - Read/Write. [device mode only]
+    UINT32 SUTW : 1;        // 13 Setup TripWire - Read/Write. [device mode only]
+    UINT32 reserved3 : 1;   // 14
+    UINT32 FS2 : 1;         // 15 Frame List Size [host mode only]
+    UINT32 ITC : 8;         // 16-23 Interrupt Threshold Control Read/Write. Default 08h.
+    UINT32 reserved : 8;    // 24-31
+  };
+} USB_USBCMD_REG;
+
+typedef enum {
+  IMX_USBMODE_IDLE = 0,
+  IMX_USBMODE_DEVICE = 2,
+  IMX_USBMODE_HOST = 3,
+} IMX_USBMODE_CM;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CM : 2;          // 0-1 Controller Mode.
+    UINT32 ES : 1;          // 1 Endian Select (0- Little, 1-Big)
+    UINT32 SLOM : 1;        // 3 Setup Lockout Mode
+    UINT32 SDIS : 1;        // 4 Stream Disable Mode
+    UINT32 reserved : 26;   // 5-31
+  };
+} USB_USBMODE_REG;
+
+// USB Non-CORE
+#define IMX_USBNONCORE_BASE 0x02184800
+#define IMX_USBNONCORE_LENGTH 0x20
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 7;       // 0-6
+    UINT32 OVER_CUR_DIS : 1;    // 7 Disable Overcurrent Detection
+    UINT32 OVER_CUR_POL : 1;    // 8 Polarity of Overcurrent (1-active low, 0-active high)
+    UINT32 PWR_POL : 1;         // 9 Power Polarity (1-active high, 0-active low)
+    UINT32 WIE : 1;             // 10 Wake-up Interrupt Enable
+    UINT32 RESET : 1;           // 11 Force Host 1 UTMI PHY Reset.
+    UINT32 SUSPENDM : 1;        // 12 Force Host 1 UTMI PHY Suspend.
+    UINT32 UTMI_ON_CLOCK : 1;   // 13 Force UTMI PHY clock output on even if in
+                                //   low-power suspend mode.
+    UINT32 WKUP_SW_EN : 1;      // 14 Software Wake-up Enable
+    UINT32 WKUP_SW : 1;         // 15 Software Wake-up
+    UINT32 WKUP_ID_EN : 1;      // 16 Wake-up on ID change enable
+    UINT32 WKUP_VBUS_EN : 1;    // 17 wake-up on VBUS change enable
+    UINT32 reserved2 : 13;      // 18-30
+    UINT32 WIR : 1;             // 31 Wake-up Interrupt Request
+  };
+} USBNC_USB_UH_CTRL_REG;
+
+typedef struct {
+  UINT32 USBNC_USB_OTG_CTRL;          // 0x00 USB OTG Control Register
+  UINT32 USBNC_USB_UH1_CTRL;          // 0x04 USB Host1 Control Register
+  UINT32 USBNC_USB_UH2_CTRL;          // 0x08 USB Host2 Control Register
+  UINT32 USBNC_USB_UH3_CTRL;          // 0x0C USB Host3 Control Register
+  UINT32 USBNC_USB_UH2_HSIC_CTRL;     // 0x10 USB Host2 HSIC Control Register
+  UINT32 USBNC_USB_UH3_HSIC_CTRL;     // 0x14 USB Host3 HSIC Control Register
+  UINT32 USBNC_USB_OTG_PHY_CTRL_0;    // 0x18 OTG UTMI PHY Control 0 Register
+  UINT32 USBNC_USB_UH1_PHY_CTRL_0;    // 0x1C Host1 UTMI PHY Control 0 Register
+} IMX_USBNONCORE_REGISTERS;
+
+// USB PHY
+#define IMX_USBPHY1_BASE 0x020C9000
+#define IMX_USBPHY2_BASE 0x020CA000
+#define IMX_USBPHY_LENGTH 0x1000
+
+typedef enum {
+  IMX_USBPHY0, // OTG
+  IMX_USBPHY1,
+  IMX_USBPHY_COUNT
+} IMX_USBPHY_ID;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ENOTG_ID_CHG_IRQ : 1;      // 0 Enable OTG_ID_CHG_IRQ.
+    UINT32 ENHOSTDISCONDETECT : 1;    // 1 For host mode, enables high-speed
+                                      //   disconnect detector.
+    UINT32 ENIRQHOSTDISCON : 1;       // 2 Enables interrupt for detection of
+                                      //   disconnection to Device when in
+                                      //   high-speed host mode.
+    UINT32 HOSTDISCONDETECT_IRQ : 1;  // 3 Indicates that the device has
+                                      //   disconnected in high-speed mode.
+    UINT32 ENDEVPLUGINDETECT : 1;     // 4 For device mode, enables 200-KOhm
+                                      //   pullups for detecting connectivity
+                                      //   to the host.
+    UINT32 DEVPLUGIN_POLARITY : 1;    // 5 For device mode interrupt generation
+                                      //   polarity
+    UINT32 OTG_ID_CHG_IRQ : 1;        // 6 OTG ID change interrupt. Indicates
+                                      //   the value of ID pin changed.
+    UINT32 ENOTGIDDETECT : 1;         // 7 Enables circuit to detect resistance
+                                      //   of MiniAB ID pin.
+    UINT32 RESUMEIRQSTICKY : 1;       // 8 1 makes RESUME_IRQ bit a sticky bit.
+    UINT32 ENIRQRESUMEDETECT : 1;     // 9 Enables interrupt for detection of a
+                                      //   non-J state on the USB line.
+    UINT32 RESUME_IRQ : 1;            // 10 Indicates that the host is sending a
+                                      //   wake-up after suspend
+    UINT32 ENIRQDEVPLUGIN : 1;        // 11 Enables interrupt for the detection
+                                      //   of connectivity to the USB line.
+    UINT32 DEVPLUGIN_IRQ : 1;         // 12 Indicates that the device is connected
+    UINT32 DATA_ON_LRADC : 1;         // 13 Enables the LRADC to monitor USB_DP
+                                      //   and USB_DM.
+    UINT32 ENUTMILEVEL2 : 1;          // 14 Enables UTMI+ Level2.
+    UINT32 ENUTMILEVEL3 : 1;          // 15 Enables UTMI+ Level3.
+    UINT32 ENIRQWAKEUP : 1;           // 16 Enables interrupt for the wakeup events
+    UINT32 WAKEUP_IRQ : 1;            // 17 Indicates that there is a wakeup event.
+    UINT32 reserved1 : 1;             // 18 reserved
+    UINT32 ENAUTOCLR_CLKGATE : 1;     // 19 Enables the feature to auto-clear
+                                      //   the CLKGATE bit if there is wakeup
+                                      //   event while USB is suspended.
+    UINT32 ENAUTOCLR_PHY_PWD : 1;     // 20 Enables the feature to auto-clear
+                                      //   the PWD register bits in USBPHYx_PWD
+                                      //   if there is wakeup event while USB is
+                                      //   suspended
+    UINT32 ENDPDMCHG_WKUP : 1;        // 21 Enables the feature to wakeup USB if
+                                      //   DP/DM is toggled when USB is suspended
+    UINT32 ENIDCHG_WKUP : 1;          // 22 Enables the feature to wakeup USB if
+                                      //   ID is toggled when USB is suspended
+    UINT32 ENVBUSCHG_WKUP : 1;        // 23 Enables the feature to wakeup USB if
+                                      //   VBUS is toggled when USB is suspended.
+    UINT32 FSDLL_RST_EN : 1;          // 24 Enables the feature to reset the FSDLL
+                                      //   lock detection logic at the end of
+                                      //   each TX packet.
+    UINT32 reserved2 : 2;             // 25-26
+    UINT32 OTG_ID_VALUE : 1;          // 27
+    UINT32 HOST_FORCE_LS_SE0 : 1;     // 28 Forces the next FS packet that is
+                                      //   transmitted to have a EOP with LS timing.
+    UINT32 UTMI_SUSPENDM : 1;         // 29 Used by the PHY to indicate a
+                                      //   powered-down state.
+    UINT32 CLKGATE : 1;               // 30 Gate UTMI Clocks. Clear to 0 to
+                                      //   run clocks.
+    UINT32 SFTRST : 1;                // 31 Soft-reset the USBPHYx_PWD,
+                                      //   USBPHYx_TX, USBPHYx_RX, Set to 0 to
+                                      //   release the PHY from reset.
+  };
+} USBPHYx_CTRL_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 STEP : 16; // 0-15 Read-only value for the stepping of the RTL version.
+    UINT32 MINOR : 8; // 16-23 Read-only value for the MINOR field of the RTL version.
+    UINT32 MAJOR : 8; // 24-31 Read-only value for the MAJOR field of the RTL version
+  };
+} USBPHYx_VERSION_REG;
+
+typedef struct {
+  UINT32 USBPHY_PWD;             // 0x00 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_SET;         // 0x04 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_CLR;         // 0x08 USB PHY Power-Down Register
+  UINT32 USBPHY_PWD_TOG;         // 0x0C USB PHY Power-Down Register
+  UINT32 USBPHY_TX;              // 0x10 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_SET;          // 0x14 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_CLR;          // 0x18 USB PHY Transmitter Control Register
+  UINT32 USBPHY_TX_TOG;          // 0x1C USB PHY Transmitter Control Register
+  UINT32 USBPHY_RX;              // 0x20 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_SET;          // 0x24 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_CLR;          // 0x28 USB PHY Receiver Control Register
+  UINT32 USBPHY_RX_TOG;          // 0x2C USB PHY Receiver Control Register
+  UINT32 USBPHY_CTRL;            // 0x30 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_SET;        // 0x34 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_CLR;        // 0x38 USB PHY General Control Register
+  UINT32 USBPHY_CTRL_TOG;        // 0x3C USB PHY General Control Register
+  UINT32 USBPHY_STATUS;          // 0x40 USB PHY Status Register
+  UINT32 reserved1[3];
+  UINT32 USBPHY_DEBUG;           // 0x50 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_SET;       // 0x54 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_CLR;       // 0x58 USB PHY Debug Register
+  UINT32 USBPHY_DEBUG_TOG;       // 0x5C USB PHY Debug Register
+  UINT32 USBPHY_DEBUG0_STATUS;   // 0x60 UTMI Debug Status Register 0
+  UINT32 reserved2[3];
+  UINT32 USBPHY_DEBUG1;          // 0x70 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_SET;      // 0x74 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_CLR;      // 0x78 UTMI Debug Status Register 1
+  UINT32 USBPHY_DEBUG1_TOG;      // 0x7C UTMI Debug Status Register 1
+  UINT32 USBPHY_VERSION;         // 0x80 UTMI RTL Version
+} IMX_USBPHY_REGISTERS;
+
+// USB Analog
+#define IMX_USBANA_BASE 0x020C81A0
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 18;  // 0-17
+    UINT32 CHK_CONTACT : 1; // 18
+    UINT32 CHK_CHRG_B : 1;  // 19
+    UINT32 EN_B : 1;        // 20
+    UINT32 reserved2 : 11;  // 21-31
+  };
+} USB_ANALOG_USB_CHRG_DETECT_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 HS_USE_EXTERNAL_R : 1;   // 0 Use external resistor to generate the
+                                    //   current bias for the high speed transmitter.
+    UINT32 EN_DEGLITCH : 1;         // 1 Enable the deglitching circuit of the
+                                    //   USB PLL output.
+    UINT32 reserved1 : 28;          // 2-29
+    UINT32 EN_CLK_UTMI : 1;         // 30 Enables the clk to the UTMI block.
+    UINT32 reserved2 : 1;           // 31
+  };
+} USB_ANALOG_USB_MISC_REG;
+
+typedef struct {
+  UINT32 USB_ANALOG_USB_VBUS_DETECT;       // 0x00 USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_SET;   // 0x04 USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_CLR;   // 0x08 USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_TOG;   // 0x0C USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT;       // 0x10 USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_SET;   // 0x14 USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_CLR;   // 0x18 USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_TOG;   // 0x1C USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_STAT;  // 0x20 USB VBUS Detect Status Register
+  UINT32 reserved1[3];
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_STAT;  // 0x30 USB Charger Detect Status Register
+  UINT32 reserved2[7];
+  UINT32 USB_ANALOG_USB_MISC;              // 0x50 USB Misc Register
+  UINT32 USB_ANALOG_USB_MISC_SET;          // 0x54 USB Misc Register
+  UINT32 USB_ANALOG_USB_MISC_CLR;          // 0x58 USB Misc Register
+  UINT32 USB_ANALOG_USB_MISC_TOG;          // 0x5C USB Misc Register
+} IMX_USBANA_USB_REGISTERS;
+
+typedef struct {
+  IMX_USBANA_USB_REGISTERS USBANA[IMX_USBPHY_COUNT];
+  UINT32 USB_ANALOG_DIGPROG;                // 0xC0 Chip Silicon Version
+} IMX_USBANA_REGISTERS;
+
+#pragma pack(pop)
+
+#endif // __IMX6_SX_H__
diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6_common.h b/Silicon/NXP/iMX6Pkg/Include/iMX6_common.h
new file mode 100644
index 000000000000..4326e3af1c6d
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6_common.h
@@ -0,0 +1,1350 @@
+/** @file
+*
+*  Common settings shared between i.MX6 Solo, DualLite, Dual, DualPlus, Quad
+*  and QuadPlus families
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX6_COMMON_H__
+#define __IMX6_COMMON_H__
+
+#pragma pack(push, 1)
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED               ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED             ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+// Boot DRAM region (kernel.img & boot working DRAM)
+#define FRAME_BUFFER_BASE                   0x10000000
+#define FRAME_BUFFER_SIZE                   0x00800000 // 8MB
+
+#define BOOT_IMAGE_PHYSICAL_BASE            0x10800000
+#define BOOT_IMAGE_PHYSICAL_LENGTH          0x001D0000 // 1.8MB
+#define BOOT_IMAGE_ATTRIBUTES               CacheAttributes
+
+// The region of registers from 0x00100000 to 0x00D00000
+#define SOC_REGISTERS_PHYSICAL_BASE1        0x00100000
+#define SOC_REGISTERS_PHYSICAL_LENGTH1      0x00C00000
+#define SOC_REGISTERS_ATTRIBUTES            ARM_MEMORY_REGION_ATTRIBUTE_DEVICE
+
+// PCIE registers and configuration space (0x01000000 - 0x02000000)
+#define PCIE_REGISTERS_PHYSICAL_BASE        0x01000000
+#define PCIE_REGISTERS_PHYSICAL_LENGTH      0x01000000
+
+// The region of registers from 0x02000000 to 0x02A00000
+#define SOC_REGISTERS_PHYSICAL_BASE2        0x02000000
+#define SOC_REGISTERS_PHYSICAL_LENGTH2      0x00A00000
+
+// Main system DRAM as defined by the PCD definitions of system memory.
+
+// MPPP definitions
+#define CPU0_MPPP_PHYSICAL_BASE            0x1080F000
+#define CPU1_MPPP_PHYSICAL_BASE            0x10810000
+#define CPU2_MPPP_PHYSICAL_BASE            0x10811000
+#define CPU3_MPPP_PHYSICAL_BASE            0x10812000
+
+// Interrupt controller
+#define CSP_BASE_REG_PA_IC_IFC              0x00A00100
+#define CSP_BASE_REG_PA_IC_DIST             0x00A01000
+
+// L2 cache controller
+#define CSP_BASE_REG_PA_PL310               0x00A02000
+
+// Timers
+#define CSP_BASE_REG_PA_GPT                 0x02098000
+#define CSP_BASE_REG_PA_EPIT1               0x020D0000
+#define CSP_BASE_REG_PA_EPIT2               0x020D4000
+
+// Timers IRQs
+#define IC_DIST_VECTOR_BASE 0
+#define IRQ_EPIT1           88
+#define IRQ_EPIT2           89
+
+// SDMA (Smart DMA) controller
+#define CSP_BASE_REG_PA_SDMA                0x020EC000
+#define IRQ_SDMA 34
+
+// SOC peripherals
+#define CSP_BASE_REG_PA_UART1               0x02020000
+#define CSP_BASE_REG_PA_UART2               0x021E8000
+#define CSP_BASE_REG_PA_UART3               0x021EC000
+#define CSP_BASE_REG_PA_UART4               0x021F0000
+#define CSP_BASE_REG_PA_UART5               0x021F4000
+
+#define CSP_BASE_REG_PA_ESDHC1              0x02190000
+#define CSP_BASE_REG_PA_ESDHC2              0x02194000
+#define CSP_BASE_REG_PA_ESDHC3              0x02198000
+#define CSP_BASE_REG_PA_ESDHC4              0x0219C000
+
+#define DBG_PORT_SUBTYPE_IMX6   0x000C
+
+// Timers clock sources
+#define SOC_OSC_FREQUENCY_REF_HZ  24000000  // Oscillator frequency 24Mhz
+#define SOC_HIGH_FREQUENCY_REF_HZ 66000000  // High Frequency reference clock 66Mhz
+#define SOC_LOW_FREQ_REF_HZ       32768     // SNVS RTC frequency 32kHz
+
+#define IMX_GPU3D_BASE 0x00130000
+#define IMX_GPU3D_LENGTH 0x4000
+
+#define IMX_GPU2D_BASE 0x00134000
+#define IMX_GPU2D_LENGTH 0x4000
+
+// IOMUX Controller (IOMUXC)
+#define IMX_IOMUXC_BASE 0x020E0000
+#define IMX_IOMUXC_LENGTH 0x4000
+
+// Secure Nonvolatile Storage (SNVS)
+#define IMX_SNVS_BASE 0x020CC000
+#define IMX_SNVS_LENGTH 0x4000
+#define IMX_SNVS_IP_ID 0x3E
+#define IMX_SNVS_IRQ 51         // SNVS consolidated interrupt
+
+#define IOMUXC_GPR_BASE_ADDRESS             0x020E0000
+
+typedef enum {
+  IMX_IOMUXC_GPR1_USB_OTG_ID_SEL_ENET_RX_ER,
+  IMX_IOMUXC_GPR1_USB_OTG_ID_SEL_GPIO_1,
+} IMX_IOMUXC_GPR1_USB_OTG_ID_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PCS_TX_DEEMPH_GEN1 : 6;        // 0-5 PCIe_PHY - Sets the launch amplitude
+                                          //   of the transmitter when pipe0_tx_swing
+                                          //   is set to 1'b0 (default state).
+    UINT32 PCS_TX_DEEMPH_GEN2_3P5DB : 6;  // 6-11 PCIe_PHY - Sets the Tx driver
+                                          //   SWING_FULL value.
+    UINT32 PCS_TX_DEEMPH_GEN2_6DB : 6;    // 12-17 PCIe_PHY - Sets the Tx driver
+                                          //   de-emphasis value in the case where
+                                          //   pipe0_tx_deemph is set to 1'b0 and
+                                          //   the PHY is running at the Gen2 (6db) rate.
+    UINT32 PCS_TX_SWING_FULL : 7;         // 18-24 PCIe_PHY - Sets the Tx driver
+                                          //   de-emphasis value in the case where
+                                          //   pipe0_tx_deemph is set to 1'b1
+                                          //   (the default setting) and the PHY
+                                          //   is running at the Gen2 (3p5db) rate.
+    UINT32 PCS_TX_SWING_LOW : 7;          // 25-31 PCIe_PHY - Sets the Tx driver
+                                          //   de-emphasis value in the case where
+                                          //   pipe0_tx_deemph is set to 1'b1
+                                          //   (the default setting) and the PHY
+                                          //   is running at the Gen1 rate.
+  };
+} IMX_IOMUXC_GPR8_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved0              : 2;  // 0-1
+    UINT32 uSDHC_DBG_MUX          : 2;  // 2-3 uSDHC debug bus IO mux control
+    UINT32 LOS_LEVEL              : 5;  // 4-8 PCIe_PHY - Loss-of-Signal Detector
+                                        //   Sensitivity Level Control Function:
+                                        //   Sets the sensitivity level for the Loss-of-Signal
+                                        //   detector.This signal must be set to 0x9
+    UINT32 APPS_PM_XMT_PME        : 1;  // 9 PCIe_CTL - Wake Up.
+                                        //   Used by application logic to wake up
+                                        //   the PMC state machine from a D1, D2
+                                        //   or D3 power state.
+                                        //   Upon wakeup, the core sends a PM_PME Message.
+    UINT32 APP_LTSSM_ENABLE       : 1;  // 10 PCIe_CTL
+                                        //   Driven low by the application after
+                                        //   reset to hold the LTSSM in the Detect
+                                        //   state until the application is ready.
+                                        //   When the application has finished
+                                        //   initializing the core configuration
+                                        //   registers, it asserts app_ltssm_enable
+                                        //   to allow the LTSSM to continue Link establishment.
+    UINT32 APP_INIT_RST           : 1;  // 11 PCIe_PHY
+                                        //   Request from the application to send
+                                        //   a Hot Reset to the downstream device.
+    UINT32 DEVICE_TYPE            : 4;  // 12-15 PCIe_CTL - Device/Port Type.
+                                        //   0000 PCIE_EP EP Mode, 0010 PCIE_RC RC Mode
+    UINT32 APPS_PM_XMT_TURNOFF    : 1;  // 16 PCIe_CTL
+                                        //   Request from the application to generate
+                                        //   a PM_Turn_Off Message.
+    UINT32 DIA_STATUS_BUS_SELECT  : 4;  // 17-20 PCIe_CTL
+                                        //   Used for debug to select what part of
+                                        //   diag_status_bus will be reflected on
+                                        //   the 32 bits of the iomux.
+    UINT32 PCIe_CTL_7             : 3;  // 21-23 PCIe control of diagnostic bus select
+    UINT32 ARMP_APB_CLK_EN        : 1;  // 24 ARM platform APB clock enable
+    UINT32 ARMP_ATB_CLK_EN        : 1;  // 25 ARM platform ATB clock enable
+    UINT32 ARMP_AHB_CLK_EN        : 1;  // 26 ARM platform AHB clock enable
+    UINT32 ARMP_IPG_CLK_EN        : 1;  // 27 ARM platform IPG clock enable
+    UINT32 reserved1              : 4;  // 28-31
+  };
+} IMX_IOMUXC_GPR12_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1        : 1;  // 0
+    UINT32 reserved2        : 1;  // 1
+    UINT32 MC_ENV           : 1;  // 2 Monotonic Counter Enable and Valid
+    UINT32 reserved3        : 1;  // 3
+    UINT32 reserved4        : 1;  // 4
+    UINT32 DP_EN            : 1;  // 5 Dumb PMIC Enabled
+    UINT32 TOP              : 1;  // 6 Turn off System Power
+    UINT32 PWR_GLITCH_EN    : 1;  // 7 Power Glitch Detection Enable
+    UINT32 reserved5        : 1;  // 8
+    UINT32 reserved6        : 1;  // 9
+    UINT32 reserved7        : 5;  // 10-14
+    UINT32 reserved8        : 1;  // 15
+    UINT32 BTN_PRESS_TIME   : 2;  // 16-17 Button press time out values for PMIC Logic.
+    UINT32 DEBOUNCE         : 2;  // 18-19 Debounce time for the BTN input signal
+    UINT32 ON_TIME          : 2;  // 20-21 Time after BTN is asserted before
+                                  //   pmic_en_b is asserted.
+    UINT32 PK_EN            : 1;  // 22 PMIC On Request Enable
+    UINT32 PK_OVERRIDE      : 1;  // 23 PMIC On Request Override
+    UINT32 reserved9        : 8;  // 24-31
+  };
+} IMX_SNVS_LPCR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 MINOR_REV  : 8;    // 0-7 SNVS block minor version number
+    UINT32 MAJOR_REV  : 8;    // 8-15 SNVS block major version number
+    UINT32 IP_ID      : 16;   // 16-31 SNVS block ID (IMX_SNVS_IP_ID)
+  };
+} IMX_SNVS_HPVIDR1_REG;
+
+typedef struct {
+  UINT32 HPLR;            // 0x000 SNVS_HP Lock Register
+  UINT32 HPCOMR;          // 0x004 SNVS_HP Command Register
+  UINT32 HPCR;            // 0x008 SNVS_HP Control Register
+  UINT32 reserved1[2];
+  UINT32 HPSR;            // 0x014 SNVS_HP Status Register
+  UINT32 reserved2[3];
+  UINT32 HPRTCMR;         // 0x024 SNVS_HP Real Time Counter MSB Register
+  UINT32 HPRTCLR;         // 0x028 SNVS_HP Real Time Counter LSB Register
+  UINT32 HPTAMR;          // 0x02C SNVS_HP Time Alarm MSB Register
+  UINT32 HPTALR;          // 0x030 SNVS_HP Time Alarm LSB Register
+  UINT32 LPLR;            // 0x034 SNVS_LP Lock Register
+  UINT32 LPCR;            // 0x038 SNVS_LP Control Register
+  UINT32 reserved3[4];
+  UINT32 LPSR;            // 0x04C SNVS_LP Status Register
+  UINT32 reserved4[3];
+  UINT32 LPSMCMR;         // 0x05C SNVS_LP Secure Monotonic Counter MSB Register
+  UINT32 LPSMCLR;         // 0x060 SNVS_LP Secure Monotonic Counter LSB Register
+  UINT32 reserved5[1];
+  UINT32 LPGPR;           // 0x068 SNVS_LP General Purpose Register
+  UINT32 reserved6[739];
+  UINT32 HPVIDR1;         // 0xBF8 SNVS_HP Version ID Register 1
+  UINT32 HPVIDR2;         // 0xBFC SNVS_HP Version ID Register 2
+} IMX_SNVS_REGISTERS;
+
+// System Reset Controller (SRC)
+#define IMX_SRC_BASE 0x020D8000
+#define IMX_SRC_LENGTH 0x4000
+
+// SCR Register Definition
+typedef enum {
+  IMX_SCR_WARM_RST_BYPASS_COUNT_DISABLED,
+  IMX_SCR_WARM_RST_BYPASS_COUNT_16,
+  IMX_SCR_WARM_RST_BYPASS_COUNT_32,
+  IMX_SCR_WARM_RST_BYPASS_COUNT_64,
+} IMX_SCR_WARM_RST_BYPASS_COUNT;
+
+typedef enum {
+  IMX_SRC_MASK_WDOG_RST_B_MASKED      = 0x5,
+  IMX_SRC_MASK_WDOG_RST_B_NOT_MASKED  = 0xA,
+} IMX_SRC_MASK_WDOG_RST;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 warm_reset_enable : 1;       // 0 WARM reset enable bit
+    UINT32 sw_gpu_rst : 1;              // 1 Software reset for GPU
+    UINT32 sw_vpu_rst : 1;              // 2 Software reset for VPU
+    UINT32 sw_ipu1_rst : 1;             // 3 Software reset for IPU1
+    UINT32 sw_open_vg_rst : 1;          // 4 Software reset for open_vg
+    UINT32 warm_rst_bypass_count : 2;   // 5-6 Defines the XTALI cycles to count
+                                        //   before bypassing the MMDC acknowledge
+                                        //   for WARM reset (IMX_SCR_WARM_RST_BYPASS_COUNT)
+    UINT32 mask_wdog_rst : 4;           // 7-10 Mask wdog_rst_b source (IMX_SRC_MASK_WDOG_RST)
+    UINT32 eim_rst : 1;                 // 11 EIM reset is needed in order to reconfigure
+                                        //   the eim chip select.
+    UINT32 sw_ipu2_rst : 1;             // 12 Software reset for ipu2
+    UINT32 core0_rst : 1;               // 13 Software reset for core0 only.
+    UINT32 core1_rst : 1;               // 14 Software reset for core1 only.
+    UINT32 core2_rst : 1;               // 15 Software reset for core2 only
+    UINT32 core3_rst : 1;               // 16 Software reset for core3 only.
+    UINT32 core0_dbg_rst : 1;           // 17 Software reset for core0 debug only.
+    UINT32 core1_dbg_rst : 1;           // 18 Software reset for core1 debug only.
+    UINT32 core2_dbg_rst : 1;           // 19 Software reset for core2 debug only.
+    UINT32 core3_dbg_rst : 1;           // 20 Software reset for core3 debug only.
+    UINT32 cores_dbg_rst : 1;           // 21 Software reset for arm platform debug only.
+    UINT32 core1_enable : 1;            // 22 core1 enable
+    UINT32 core2_enable : 1;            // 23 core2 enable
+    UINT32 core3_enable : 1;            // 24 core3 enable
+    UINT32 dbg_rst_msk_pg : 1;          // 25 Do not assert debug resets after
+                                        //   power gating event of core.
+    UINT32 reserved : 6;                // 26-31 reserved
+  };
+} IMX_SRC_SCR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 BOOT_CFG1 : 8;   // 0-7
+    UINT32 BOOT_CFG2 : 8;   // 8-15
+    UINT32 BOOT_CFG3 : 8;   // 16-23
+    UINT32 BOOT_CFG4 : 8;   // 24-31
+  };
+} IMX_SRC_SBMR1_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 SEC_COFNIG : 2;    // 0-1
+    UINT32 reserved1 : 1;     // 2
+    UINT32 DIR_BT_DIS : 1;    // 3
+    UINT32 BT_FUSE_SEL : 1;   // 4
+    UINT32 reserved2 : 19;    // 5-23
+    UINT32 BMOD : 2;          // 24-25
+    UINT32 reserved3 : 6;     // 26-31
+  };
+} IMX_SRC_SBMR2_REG;
+
+typedef struct {
+  UINT32 SCR;           // 0x00 SRC Control Register (SRC_SCR)
+  UINT32 SBMR1;         // 0x04 SRC Boot Mode Register 1 (SRC_SBMR1)
+  UINT32 SRSR;          // 0x08 SRC Reset Status Register (SRC_SRSR)
+  UINT32 reserved1[2];
+  UINT32 SISR;          // 0x14 SRC Interrupt Status Register (SRC_SISR)
+  UINT32 SIMR;          // 0x18 SRC Interrupt Mask Register (SRC_SIMR)
+  UINT32 SBMR2;         // 0x1C SRC Boot Mode Register 2 (SRC_SBMR2)
+  UINT32 GPR1;          // 0x20 SRC General Purpose Register 1 (SRC_GPR1)
+  UINT32 GPR2;          // 0x24 SRC General Purpose Register 2 (SRC_GPR2)
+  UINT32 GPR3;          // 0x28 SRC General Purpose Register 3 (SRC_GPR3)
+  UINT32 GPR4;          // 0x2C SRC General Purpose Register 4 (SRC_GPR4)
+  UINT32 GPR5;          // 0x30 SRC General Purpose Register 4 (SRC_GPR5)
+  UINT32 GPR6;          // 0x34 SRC General Purpose Register 4 (SRC_GPR6)
+  UINT32 GPR7;          // 0x38 SRC General Purpose Register 4 (SRC_GPR7)
+  UINT32 GPR8;          // 0x3C SRC General Purpose Register 4 (SRC_GPR8)
+  UINT32 GPR9;          // 0x40 SRC General Purpose Register 4 (SRC_GPR9)
+  UINT32 GPR10;         // 0x44 SRC General Purpose Register 4 (SRC_GPR10)
+} IMX_SRC_REGISTERS;
+
+// Watchdog (WDOG)
+#define IMX_WDOG1_BASE 0x020BC000
+#define IMX_WDOG2_BASE 0x020C0000
+#define IMX_WDOG_LENGTH 0x4000
+#define IMX_WDOG_WSR_FEED1 0x5555
+#define IMX_WDOG_WSR_FEED2 0xAAAA
+
+typedef union {
+  UINT16 AsUint16;
+  struct {
+    UINT16 WDZST : 1;                   // 0 Watchdog Low Power
+    UINT16 WDBG : 1;                    // 1 Watchdog DEBUG Enable
+    UINT16 WDE : 1;                     // 2 Watchdog Enable
+    UINT16 WDT : 1;                     // 3 WDOG_B Time-out assertion.
+    UINT16 SRS : 1;                     // 4 Software Reset Signal
+    UINT16 WDA : 1;                     // 5 WDOG_B assertion
+    UINT16 reserved1 : 1;               // 6
+    UINT16 WDW : 1;                     // 7 Watchdog Disable for Wait
+    UINT16 WT : 8;                      // 8-15 Watchdog Time-out Field
+  };
+} IMX_WDOG_WCR_REG;
+
+typedef struct {
+  UINT16 WCR;   // 0x0 Watchdog Control Register (WDOG1_WCR)
+  UINT16 WSR;   // 0x2 Watchdog Service Register (WDOG1_WSR)
+  UINT16 WRSR;  // 0x4 Watchdog Reset Status Register (WDOG1_WRSR)
+  UINT16 WICR;  // 0x6 Watchdog Interrupt Control Register (WDOG1_WICR)
+  UINT16 WMCR;  // 0x8 Watchdog Miscellaneous Control Register (WDOG1_WMCR)
+} IMX_WDOG_REGISTERS;
+
+// Clock Control Module (CCM)
+#define IMX_CCM_BASE 0x020C4000
+#define IMX_CCM_LENGTH 0x4000
+#define IMX_CCM_ANALOG_BASE  0x020C8000
+#define IMX_CCM_ANALOG_LENGTH 0x1000
+
+#define IMX_GPU2D_CORE_CLK_MAX 532000000 // 532Mhz
+#define IMX_GPU3D_CORE_CLK_MAX 540000000 // 540Mhz
+#define IMX_GPU3D_SHADER_CLK_MAX 660000000 // 660Mhz
+#define IMX_REF_CLK_24M_FREQ 24000000
+
+typedef enum {
+  IMX_CCM_PLL3_SW_CLK_SEL_PLL3_MAIN_CLK,
+  IMX_CCM_PLL3_SW_CLK_SEL_PLL3_BYPASS_CLK,
+} IMX_CCM_PLL3_SW_CLK_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 pll3_sw_clk_sel : 1;     // 0 Selects source to generate pll3_sw_clk
+    UINT32 reserved1 : 1;           // 1 reserved
+    UINT32 pll1_sw_clk_sel : 1;     // 2 Selects source to generate pll1_sw_clk.
+    UINT32 reserved2 : 5;           // 3-7
+    UINT32 step_sel : 1;            // 8 Selects the option to be chosen for the
+                                    //   step frequency
+    UINT32 pfd_396m_dis_mask : 1;   // 9 Mask of 396M PFD auto-disable
+    UINT32 pfd_352m_dis_mask : 1;   // 10 Mask of 352M PFD auto-disable.
+    UINT32 pfd_594_dis_mask : 1;    // 11 Mask of 594M PFD auto-disable.
+    UINT32 pfd_508m_dis_mask : 1;   // 12 Mask of 508M PFD auto-disable
+    UINT32 pfd_454m_dis_mask : 1;   // 13 Mask of 454M PFD auto-disable.
+    UINT32 pfd_720m_dis_mask : 1;   // 14 Mask of 720M PFD auto-disable.
+    UINT32 pfd_540m_dis_mask : 1;   // 15 Mask of 540M PFD auto-disable.
+    UINT32 reserved3 : 16;          // 16-31
+  };
+} IMX_CCM_CCSR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 arm_podf : 3;    // 0-3 Divider for ARM clock root
+    UINT32 reserved : 29;   // 3-31
+  };
+} IMX_CCM_CACRR_REG;
+
+// CBCMR.gpu2d_axi_clk_sel
+typedef enum {
+  IMX_CCM_GPU2D_AXI_CLK_SEL_AXI,
+  IMX_CCM_GPU2D_AXI_CLK_SEL_AHB,
+} IMX_CCM_GPU2D_AXI_CLK_SEL;
+
+// CBCMR.gpu3d_axi_clk_sel
+typedef enum {
+  IMX_CCM_GPU3D_AXI_CLK_SEL_AXI,
+  IMX_CCM_GPU3D_AXI_CLK_SEL_AHB,
+} IMX_CCM_GPU3D_AXI_CLK_SEL;
+
+// CBCMR.gpu2d_core_clk_sel
+typedef enum {
+  IMX_CCM_GPU2D_CORE_CLK_SEL_AXI,
+  IMX_CCM_GPU2D_CORE_CLK_SEL_PLL3_SW,
+  IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0,
+  IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD2,
+} IMX_CCM_GPU2D_CORE_CLK_SEL;
+
+// CBCMR.pre_periph_clk_sel
+typedef enum {
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2,
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2,
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD0,
+  IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2,
+} IMX_CCM_PRE_PERIPH_CLK_SEL;
+
+// CBCMR.gpu3d_core_clk_sel
+typedef enum {
+  IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI,
+  IMX_CCM_GPU3D_CORE_CLK_SEL_PLL3_SW,
+  IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD1,
+  IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD2,
+} IMX_CCM_GPU3D_CORE_CLK_SEL;
+
+// CBCMR.gpu3d_shader_clk_sel
+typedef enum {
+  IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI,
+  IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_SW,
+  IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL2_PFD1,
+  IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_PFD0,
+} IMX_CCM_GPU3D_SHADER_CLK_SEL;
+
+// CBCMR.periph_clk2_sel
+typedef enum {
+  IMX_CCM_PERIPH_CLK2_SEL_PLL3_SW_CLK,
+  IMX_CCM_PERIPH_CLK2_SEL_OSC_CLK,
+  IMX_CCM_PERIPH_CLK2_SEL_PLL2,
+} IMX_CCM_PERIPH_CLK2_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 gpu2d_axi_clk_sel : 1;       // 0 Selector for gpu2d_axi clock
+    UINT32 gpu3d_axi_clk_sel : 1;       // 1 Selector for gpu3d_axi clock
+    UINT32 reserved1 : 2;               // 2-3
+    UINT32 gpu3d_core_clk_sel : 2;      // 4-5 Selector for gpu3d_core clock
+    UINT32 reserved2 : 2;               // 6-7
+    UINT32 gpu3d_shader_clk_sel : 2;    // 8-9 Selector for gpu3d_shader clock
+    UINT32 pcie_axi_clk_sel : 1;        // 10 Selector for pcie_axi clock
+    UINT32 vdoaxi_clk_sel : 1;          // 11 Selector for vdoaxi clock
+    UINT32 periph_clk2_sel : 2;         // 12-13 Selector for peripheral clk2 clock
+    UINT32 vpu_axi_clk_sel : 2;         // 14-15 Selector for VPU axi clock
+    UINT32 gpu2d_core_clk_sel : 2;      // 16-17 Selector for open vg (GPU2D Core) clock
+    UINT32 pre_periph_clk_sel : 2;      // 18-19 Selector for pre_periph clock
+    UINT32 periph2_clk2_sel : 1;        // 20 Selector for periph2_clk2 clock
+    UINT32 pre_periph2_clk_sel : 2;     // 21-22 Selector for pre_periph2 clock
+    UINT32 gpu2d_core_clk_podf : 3;     // 23-25 Divider for gpu2d_core clock.
+    UINT32 gpu3d_core_podf : 3;         // 26-28 Divider for gpu3d_core clock
+    UINT32 gpu3d_shader_podf : 3;       // 29-31 Divider for gpu3d_shader clock.
+  };
+} IMX_CCM_CBCMR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ssi1_clk_podf : 6;           // 0-5 Divider for ssi1 clock podf
+    UINT32 ssi1_clk_pred : 3;           // 6-8 Divider for ssi1 clock pred
+    UINT32 esai_clk_pred : 3;           // 9-11 Divider for esai clock pred
+    UINT32 reserved1 : 4;               // 12-15 Reserved
+    UINT32 ssi3_clk_podf : 6;           // 16-21 Divider for ssi3 clock podf
+    UINT32 ssi3_clk_pred : 3;           // 22-24 Divider for ssi3 clock pred
+    UINT32 esai_clk_podf : 3;           // 25-27 Divider for esai clock podf
+    UINT32 reserved2 : 4;               // 28-31 Reserved
+  };
+} IMX_CCM_CS1CDR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ssi2_clk_podf : 6;           // 0-5 Divider for ssi2 clock podf
+    UINT32 ssi2_clk_pred : 3;           // 6-8 Divider for ssi2 clock pred
+    UINT32 ldb_di0_clk_sel : 3;         // 9-11 Selector for ldb_di0 clock
+    UINT32 ldb_di1_clk_sel : 3;         // 12-14 Selector for ldb_di1 clock
+    UINT32 reserved1 : 1;               // 15 Reserved
+    UINT32 enfc_clk_sel : 2;            // 16-17 Selector for enfc clock
+    UINT32 enfc_clk_pred : 3;           // 18-20 Divider for enfc clock pred divider
+    UINT32 esai_clk_podf : 6;           // 21-26 Divider for enfc clock divider
+    UINT32 reserved2 : 5;               // 27-31 Reserved
+  };
+} IMX_CCM_CS2CDR_REG;
+
+typedef enum {
+  IMX_CCM_CCGR_OFF      = 0x0,  // Clock is off during all modes. Stop enter
+                                //   hardware handshake is disabled.
+  IMX_CCM_CCGR_ON_RUN   = 0x1,  // Clock is on in run mode, but off in WAIT and STOP modes
+  IMX_CCM_CCGR_ON       = 0x3,  // Clock is on during all modes, except STOP mode.
+} IMX_CCM_CCGR;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 aips_tz1_clk_enable : 2;         // 0-1 aips_tz1 clock enable.
+    UINT32 aips_tz2_clk_enable : 2;         // 2-3 aips_tz2 clock enable.
+    UINT32 apbhdma_hclk_enable : 2;         // 4-5 apbhdma hclk clock enable.
+    UINT32 asrc_clk_enable : 2;             // 6-7 asrc clock enable.
+    UINT32 caam_secure_mem_clk_enable : 2;  // 8-9 caam_secure_mem clock enable.
+    UINT32 caam_wrapper_aclk_enable : 2;    // 10-11 caam_wrapper_aclk clock enable.
+    UINT32 caam_wrapper_ipg_enable : 2;     // 12-13 caam_wrapper_ipg clock enable.
+    UINT32 can1_clk_enable : 2;             // 14-15 can1 clock enable.
+    UINT32 can1_serial_clk_enable : 2;      // 16-17 can1_serial clock enable.
+    UINT32 can2_clk_enable : 2;             // 18-19 can2 clock enable.
+    UINT32 can2_serial_clk_enable : 2;      // 20-21 can2_serial clock enable.
+    UINT32 arm_dbg_clk_enable : 2;          // 22-23 CPU debug clock enable.
+    UINT32 dcic1_clk_enable : 2;            // 24-25 dcic 1 clock enable.
+    UINT32 dcic2_clk_enable : 2;            // 26-27 dcic2 clock enable.
+    UINT32 dtcp_clk_enable : 2;             // 28-29 dtcp clock enable.
+    UINT32 reserved : 2;                    // 30-31
+  };
+} IMX_CCM_CCGR0_REG;
+
+// CHSCCDR.ipu1_di0_clk_sel
+typedef enum {
+  IMX_CHSCCDR_IPU1_DI0_CLK_SEL_PREMUX,
+  IMX_CHSCCDR_IPU1_DI0_CLK_SEL_IPP_DI0_CLK,
+  IMX_CHSCCDR_IPU1_DI0_CLK_SEL_IPP_DI1_CLK,
+  IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK,
+  IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI1_CLK,
+} IMX_CHSCCDR_IPU1_DI0_CLK_SEL;
+
+// CHSCCDR.ipu1_di0_podf
+typedef enum {
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_1,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_2,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_3,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_4,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_5,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_6,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_7,
+  IMX_CHSCCDR_IPU1_DI0_PODF_DIV_8,
+} IMX_CHSCCDR_IPU1_DI0_PODF;
+
+// CHSCCDR.ipu1_di0_pre_clk_sel
+typedef enum {
+  IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MMDC_CH0,
+  IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL3_SW_CLK,
+  IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL5,
+  IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL2_PFD0,
+  IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL2_PFD2,
+  IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL3_PFD1,
+} IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL;
+
+// CHSCCDR.ipu1_di1_clk_sel
+typedef enum {
+  IMX_CHSCCDR_IPU1_DI1_CLK_SEL_PREMUX,
+  IMX_CHSCCDR_IPU1_DI1_CLK_SEL_IPP_DI0_CLK,
+  IMX_CHSCCDR_IPU1_DI1_CLK_SEL_IPP_DI1_CLK,
+  IMX_CHSCCDR_IPU1_DI1_CLK_SEL_LDB_DI0_CLK,
+  IMX_CHSCCDR_IPU1_DI1_CLK_SEL_LDB_DI1_CLK,
+} IMX_CHSCCDR_IPU1_DI1_CLK_SEL;
+
+// CHSCCDR.ipu1_di1_podf
+typedef enum {
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_1,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_2,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_3,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_4,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_5,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_6,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_7,
+  IMX_CHSCCDR_IPU1_DI1_PODF_DIV_8,
+} IMX_CHSCCDR_IPU1_DI1_PODF;
+
+// CHSCCDR.ipu1_di1_pre_clk_sel
+typedef enum {
+  IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MMDC_CH0,
+  IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL3_SW_CLK,
+  IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL5,
+  IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL2_PFD0,
+  IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL2_PFD2,
+  IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL3_PFD1,
+} IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ipu1_di0_clk_sel : 3;        // 0-2 Selector for ipu1 di0 root clock
+    UINT32 ipu1_di0_podf : 3;           // 3-5 Divider for ipu1_di0 clock divider
+    UINT32 ipu1_di0_pre_clk_sel : 3;    // 6-8 Selector for ipu1 di0 root clock
+    UINT32 ipu1_di1_clk_sel : 3;        // 9-11 Selector for ipu1 di1 root clock
+    UINT32 ipu1_di1_podf : 3;           // 12-14 Divider for ipu1_di clock divider
+    UINT32 ipu1_di1_pre_clk_sel : 3;    // 15-17 Selector for ipu1 di1 root clock
+    UINT32 reserved : 14;               // 18-31
+  };
+} IMX_CCM_CHSCCDR_REG;
+
+// NOTE: OPENVG clock cannot be gated without gating GPU2D clock as well.
+//       Configure both CG bits (CCM_ANALOG_CCGR1[CG12] and
+//       CCM_ANALOG_CCGR3[CG15]) to gate OPENVG.
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ecspi1_clk_enable : 2;       // 0-1 ecspi1 clock enable.
+    UINT32 ecspi2_clk_enable : 2;       // 2-3 ecspi2 clock enable.
+    UINT32 ecspi3_clk_enable : 2;       // 4-5 ecspi3 clock enable.
+    UINT32 ecspi4_clk_enable : 2;       // 6-7 ecspi4 clock enable.
+    UINT32 ecspi5_clk_enable : 2;       // 8-9 ecspi5 clock enable.
+    UINT32 enet_clk_enable : 2;         // 10-11 enet clock enable.
+    UINT32 epit1_clk_enable : 2;        // 12-13 epit1 clock enable.
+    UINT32 epit2_clk_enable : 2;        // 14-15 epit2 clock enable.
+    UINT32 esai_clk_enable : 2;         // 16-17 esai clock enable.
+    UINT32 reserved1 : 2;               // 18-19
+    UINT32 gpt_clk_enable : 2;          // 20-21 gpt bus clock enable.
+    UINT32 gpt_serial_clk_enable : 2;   // 22-23 gpt serial clock enable.
+    UINT32 gpu2d_clk_enable : 2;        // 24-25 gpu2d clock enable.
+    UINT32 gpu3d_clk_enable : 2;        // 26-27 gpu3d clock enable.
+    UINT32 reserved2 : 4;               // 28-31
+  };
+} IMX_CCM_CCGR1_REG;
+
+// CBCDR.axi_sel
+typedef enum {
+  IMX_CCM_AXI_SEL_PERIPH_CLK,
+  IMX_CCM_AXI_SEL_AXI_ALT,
+} IMX_CCM_AXI_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 periph2_clk2_podf : 3;   // 0-2 Divider for periph2_clk2 podf
+    UINT32 mmdc_ch1_axi_podf : 3;   // 3-5 Divider for mmdc_ch1_axi podf
+    UINT32 axi_sel : 1;             // 6 AXI clock source select (IMX_CCM_AXI_SEL)
+    UINT32 axi_alt_sel : 1;         // 7 AXI alternative clock select
+    UINT32 ipg_podf : 2;            // 8-9 Divider for ipg podf.
+    UINT32 ahb_podf : 3;            // 10-12 Divider for AHB PODF.
+    UINT32 reserved1 : 3;           // 13-15
+    UINT32 axi_podf : 3;            // 16-18 Divider for axi podf
+    UINT32 mmdc_ch0_axi_podf : 3;   // 19-21 Divider for mmdc_ch0_axi podf.
+    UINT32 reserved2 : 3;           // 22-24
+    UINT32 periph_clk_sel : 1;      // 25 Selector for peripheral main clock
+                                    //   (source of MMDC_CH0_CLK_ROOT).
+    UINT32 periph2_clk_sel : 1;     // 16 Selector for peripheral2 main clock
+                                    //   (source of mmdc_ch1_clk_root
+    UINT32 periph_clk2_podf : 3;    // 27-29 Divider for periph2 clock podf.
+    UINT32 reserved3 : 2;           // 30-31
+  };
+} IMX_CCM_CBCDR_REG;
+
+// CCOSR.CLKO1_SEL
+typedef enum {
+  IMX_CCM_CLKO1_SEL_PLL3_SW_CLK_2,
+  IMX_CCM_CLKO1_SEL_PLL2_MAIN_CLK_2,
+  IMX_CCM_CLKO1_SEL_PLL1_MAIN_CLK_2,
+  IMX_CCM_CLKO1_SEL_PLL5_MAIN_CLK_2,
+  IMX_CCM_CLKO1_SEL_VIDEO_27M_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_AXI_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_ENFC_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_IPU1_DI0_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_IPU1_DI1_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_IPU2_DI0_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_IPU2_DI1_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_AHB_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_IPG_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_PERCLK_ROOT,
+  IMX_CCM_CLKO1_SEL_CKIL_SYNC_CLK_ROOT,
+  IMX_CCM_CLKO1_SEL_PLL4_MAIN_CLK,
+} IMX_CCM_CLKO1_SEL;
+
+// CCOSR.CLK_OUT_SEL
+typedef enum {
+  IMX_CCM_CLK_OUT_SEL_CCM_CLKO1,
+  IMX_CCM_CLK_OUT_SEL_CCM_CLKO2,
+} IMX_CCM_CLK_OUT_SEL;
+
+// CCOSR.CLKO2_SEL
+typedef enum {
+  IMX_CCM_CLKO2_SEL_MMDC_CH0_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_MMDC_CH1_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_USDHC4_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_USDHC1_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_GPU2D_AXI_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_WRCK_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_ECSPI_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_GPU3D_AXI_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_USDHC3_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_125M_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_ARM_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_IPU1_HSP_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_IPU2_HSP_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_VDO_AXI_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_OSC_CLK,
+  IMX_CCM_CLKO2_SEL_GPU2D_CORE_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_GPU3D_CORE_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_USDHC2_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_SSI1_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_SSI2_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_SSI3_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_GPU3D_SHADER_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_VPU_AXI_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_CAN_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_LDB_DI0_SERIAL_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_LDB_DI1_SERIAL_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_ESAI_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_ACLK_EIM_SLOW_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_UART_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_SPDIF0_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_SPDIF1_CLK_ROOT,
+  IMX_CCM_CLKO2_SEL_HSI_TX_CLK_ROOT,
+} IMX_CCM_CLKO2_SEL;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CLKO1_SEL : 4;     // 0-3 Selection of the clock to be generated on
+                              //   CCM_CLKO1 (IMX_CCM_CLKO1_SEL)
+    UINT32 CLKO1_DIV : 3;     // 4-6 Setting the divider of CCM_CLKO1
+    UINT32 CLKO1_EN : 1;      // 7 Enable of CCM_CLKO1 clock
+    UINT32 CLK_OUT_SEL : 1;   // 8 CCM_CLKO1 output to reflect CCM_CLKO1 or
+                              //   CCM_CLKO2 clocks
+    UINT32 reserved1 : 7;     // 9-15
+    UINT32 CLKO2_SEL : 5;     // 16-20 Selection of the clock to be generated on
+                              //   CCM_CLKO2 (IMX_CCM_CLKO2_SEL)
+    UINT32 CLKO2_DIV : 3;     // 21-23 Setting the divider of CCM_CLKO2
+    UINT32 CLKO2_EN : 1;      // 24 Enable of CCM_CLKO2 clock
+    UINT32 reserved2 : 7;     // 25-31
+  };
+} IMX_CCM_CCOSR_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ipu1_ipu_clk_enable : 2;     // 0-1 ipu1_ipu clock
+    UINT32 ipu1_ipu_di0_clk_enable : 2; // 2-3 ipu1_di0 clock and pre-clock
+    UINT32 ipu1_ipu_di1_clk_enable : 2; // 4-5 ipu1_di1 clock and pre-clock
+    UINT32 ipu2_ipu_clk_enable : 2;     // 6-7 ipu2_ipu clock
+    UINT32 ipu2_ipu_di0_clk_enable : 2; // 8-9 ipu2_di0 clock and pre-clock
+    UINT32 ipu2_ipu_di1_clk_enable : 2; // 10-11 ipu2_di1 clock and pre-clock
+    UINT32 ldb_di0_clk_enable : 2;      // 12-13 ldb_di0 clock
+    UINT32 ldb_di1_clk_enable : 2;      // 14-15 ldb_di1 clock
+    UINT32 mipi_core_cfg_clk_enable : 2; // 16-17 mipi_core_cfg clock
+    UINT32 mlb_clk_enable : 2;          // 18-19 mlb clock
+    UINT32 mmdc_core_aclk_fast_core_p0_enable : 2; // 20-21 mmdc_core_aclk_fast_core_p0 clock
+    UINT32 reserved1 : 2;               // 22-23
+    UINT32 mmdc_core_ipg_clk_p0_enable : 2; // 24-25 mmdc_core_ipg_clk_p0 clock
+    UINT32 reserved2 : 2;               // 26-27
+    UINT32 ocram_clk_enable : 2;        // 28-29 ocram clock
+    UINT32 openvgaxiclk_clk_root_enable : 2; // 30-31 openvgaxiclk clock
+  };
+} IMX_CCM_CCGR3_REG;
+
+typedef struct {
+  UINT32 CCR;           // 0x00 CCM Control Register (CCM_CCR)
+  UINT32 CCDR;          // 0x04 CCM Control Divider Register (CCM_CCDR)
+  UINT32 CSR;           // 0x08 CCM Status Register (CCM_CSR)
+  UINT32 CCSR;          // 0x0C CCM Clock Switcher Register (CCM_CCSR)
+  UINT32 CACRR;         // 0x10 CCM Arm Clock Root Register (CCM_CACRR)
+  UINT32 CBCDR;         // 0x14 CCM Bus Clock Divider Register (CCM_CBCDR)
+  UINT32 CBCMR;         // 0x18 CCM Bus Clock Multiplexer Register (CCM_CBCMR)
+  UINT32 CSCMR1;        // 0x1C CCM Serial Clock Multiplexer Register 1 (CCM_CSCMR1)
+  UINT32 CSCMR2;        // 0x20 CCM Serial Clock Multiplexer Register 2 (CCM_CSCMR2)
+  UINT32 CSCDR1;        // 0x24 CCM Serial Clock Divider Register 1 (CCM_CSCDR1)
+  UINT32 CS1CDR;        // 0x28 CCM SSI1 Clock Divider Register (CCM_CS1CDR)
+  UINT32 CS2CDR;        // 0x2C CCM SSI2 Clock Divider Register (CCM_CS2CDR)
+  UINT32 CDCDR;         // 0x30 CCM D1 Clock Divider Register (CCM_CDCDR)
+  UINT32 CHSCCDR;       // 0x34 CCM HSC Clock Divider Register (CCM_CHSCCDR)
+  UINT32 CSCDR2;        // 0x38 CCM Serial Clock Divider Register 2 (CCM_CSCDR2)
+  UINT32 CSCDR3;        // 0x3C CCM Serial Clock Divider Register 3 (CCM_CSCDR3)
+  UINT32 reserved1[2];
+  UINT32 CDHIPR;        // 0x48 CCM Divider Handshake In-Process Register (CCM_CDHIPR)
+  UINT32 reserved2[2];
+  UINT32 CLPCR;         // 0x54 CCM Low Power Control Register (CCM_CLPCR)
+  UINT32 CISR;          // 0x58 CCM Interrupt Status Register (CCM_CISR)
+  UINT32 CIMR;          // 0x5C CCM Interrupt Mask Register (CCM_CIMR)
+  UINT32 CCOSR;         // 0x60 CCM Clock Output Source Register (CCM_CCOSR)
+  UINT32 CGPR;          // 0x64 CCM General Purpose Register (CCM_CGPR)
+  UINT32 CCGR[7];       // 0x68-7C CCM Clock Gating Register 0-6 (CCM_CCGR0-CCM_CCGR6)
+  UINT32 reserved3[1];
+  UINT32 CMEOR;         // 0x88 CCM Module Enable Override Register (CCM_CMEOR)
+} IMX_CCM_REGISTERS;
+
+// CCM Analog
+typedef enum {
+  IMX_PLL_BYPASS_CLK_SRC_REF_CLK_24M,
+  IMX_PLL_BYPASS_CLK_SRC_CLK1,
+  IMX_PLL_BYPASS_CLK_SRC_CLK2,
+  IMX_PLL_BYPASS_CLK_SRC_XOR,
+} IMX_PLL_BYPASS_CLK_SRC;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 7;      // 0-6  Valid range for divider value:
+                                //   Fout = Fin * div_select/2.0
+    UINT32 reserved1 : 5;       // 7-11
+    UINT32 POWERDOWN : 1;       // 12 Powers down the PLL.
+    UINT32 ENABLE: 1;           // 13 Enable the clock output.
+    UINT32 BYPASS_CLK_SRC : 2;  // 14-15 Determines the bypass and PLL reference clock source.
+    UINT32 BYPASS : 1;          // 16 Bypass the PLL.
+    UINT32 LVDS_SEL : 1;        // 17 Analog Debug Bit
+    UINT32 LVDS_24MHZ_SEL : 1;  // 18 Analog Debug Bit
+    UINT32 reserved2 : 1;       // 19 PLL_SEL (Reserved)
+    UINT32 reserved3 : 11;      // 20-30
+    UINT32 LOCK : 1;            // 31 PLL lock status
+  };
+} IMX_CCM_ANALOG_PLL_ARM_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 1;      // 0 0 - Fout=Fref*20; 1 - Fout=Fref*22.
+    UINT32 reserved1 : 11;      // 1-11
+    UINT32 POWERDOWN : 1;       // 12 Powers down the PLL.
+    UINT32 ENABLE : 1;          // 13 Enable PLL output
+    UINT32 BYPASS_CLK_SRC : 2;  // 14-15 Determines the bypass source.
+    UINT32 BYPASS : 1;          // 16 Bypass the PLL.
+    UINT32 reserved2 : 1;       // 17
+    UINT32 PFD_OFFSET_EN : 1;   // 18 Enables an offset in the phase frequency detector
+    UINT32 reserved3 : 12;      // 19-30
+    UINT32 LOCK : 1;            // 31 PLL Lock status
+  };
+} IMX_CCM_ANALOG_PLL_SYS_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 2;      // 0-1 - Fout=Fref*20; 1 - Fout=Fref*22.
+    UINT32 reserved1 : 4;       // 2-5
+    UINT32 EN_USB_CLKS : 1;     // 6 Powers the 9-phase PLL outputs for USBPHYn
+    UINT32 reserved2 : 5;       // 7-11
+    UINT32 POWER : 1;           // 12 Powers up the PLL.
+    UINT32 ENABLE : 1;          // 13 Enable the PLL clock output
+    UINT32 BYPASS_CLK_SRC : 2;  // 14-15 Determines the bypass source
+    UINT32 BYPASS : 1;          // 16 Bypass the PLL.
+    UINT32 reserved3 : 14;      // 17-30
+    UINT32 LOCK : 1;            // 31 PLL Lock status
+  };
+} IMX_CCM_ANALOG_PLL_USB1_REG;
+
+typedef enum {
+  IMX_POST_DIV_SELECT_DIVIDE_4,
+  IMX_POST_DIV_SELECT_DIVIDE_2,
+  IMX_POST_DIV_SELECT_DIVIDE_1,
+} IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 7;        // 0-6 This field controls the PLL loop divider.
+                                  //   Valid range for DIV_SELECT divider value: 27~54
+    UINT32 Reserved1 : 5;         // 7-11
+    UINT32 POWERDOWN : 1;         // 12 Powers down the PLL
+    UINT32 ENABLE : 1;            // 13 Enalbe PLL output
+    UINT32 BYPASS_CLK_SRC : 2;    // 14-15 Determines the bypass source
+    UINT32 BYPASS : 1;            // 16 Bypass the PLL
+    UINT32 Reserved2 : 1;         // 17
+    UINT32 PFD_OFFSET_EN : 1;     // 18 Enables an offset in the phase frequency detector
+    UINT32 POST_DIV_SELECT : 2;   // 19-20 These bits implement a divider after
+                                  //   the PLL, but before the enable and bypass mux.
+    UINT32 Reserved3 : 1;         // 21
+    UINT32 Reserved4 : 9;         // 22-30 Always set to zero
+    UINT32 LOCK : 1;              // 31 PLL is/not currently locked
+  };
+} IMX_CCM_PLL_VIDEO_CTRL_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PFD0_FRAC : 6;     // 0-5 fractional divide value. The resulting
+                              //   frequency shall be 528*18/PFD0_FRAC where
+                              //   PFD0_FRAC is in the range 12-35.
+    UINT32 PFD0_STABLE : 1;   // 6
+    UINT32 PFD0_CLKGATE : 1;  // 7 Set to 1 to gate ref_pfd0
+    UINT32 PFD1_FRAC : 6;     // 8-13 fractional divide value
+    UINT32 PFD1_STABLE : 1;   // 14
+    UINT32 PFD1_CLKGATE : 1;  // 15 Set to 1 to gate ref_pfd1
+    UINT32 PFD2_FRAC : 6;     // 16-21 fractional divide value
+    UINT32 PFD2_STABLE : 1;   // 22
+    UINT32 PFD2_CLKGATE : 1;  // 23 Set to 1 to gate ref_pfd2
+    UINT32 PFD3_FRAC : 6;     // 24-29 fractional divide value
+    UINT32 PFD3_STABLE : 1;   // 30
+    UINT32 PFD3_CLKGATE : 1;  // 31 Set to 1 to gate ref_pfd3
+  };
+} IMX_CCM_PFD_480_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PFD0_FRAC : 6;     // 0-5 fractional divide value. The resulting
+                              //   frequency shall be 528*18/PFD0_FRAC where
+                              //   PFD0_FRAC is in the range 12-35.
+    UINT32 PFD0_STABLE : 1;   // 6
+    UINT32 PFD0_CLKGATE : 1;  // 7 Set to 1 to gate ref_pfd0
+    UINT32 PFD1_FRAC : 6;     // 8-13 fractional divide value
+    UINT32 PFD1_STABLE : 1;   // 14
+    UINT32 PFD1_CLKGATE : 1;  // 15 Set to 1 to gate ref_pfd1
+    UINT32 PFD2_FRAC : 6;     // 16-21 fractional divide value
+    UINT32 PFD2_STABLE : 1;   // 22
+    UINT32 PFD2_CLKGATE : 1;  // 23 Set to 1 to gate ref_pfd2
+    UINT32 reserved : 8;      // 24-31
+  };
+} IMX_CCM_PFD_528_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 REG0_TARG : 5;   // 0-4 target voltage for the ARM core power domain
+    UINT32 reserved1 : 4;   // 5-8
+    UINT32 REG1_TARG : 5;   // 9-13 target voltage for the VPU/GPU power domain
+    UINT32 reserved2 : 4;   // 14-17
+    UINT32 REG2_TARG : 5;   // 18-22 target voltage for the SOC power domain
+    UINT32 reserved3 : 6;   // 23-28
+    UINT32 FET_ODRIVE : 1;  // 29 increases the gate drive on power gating FET
+    UINT32 reserved4 : 2;   // 30-31
+  };
+} IMX_PMU_REG_CORE_REG;
+
+typedef enum {
+  PLL_ENET_DIV_SELECT_25MHZ = 0,
+  PLL_ENET_DIV_SELECT_50MHZ = 1,
+  PLL_ENET_DIV_SELECT_100MHZ = 2,
+  PLL_ENET_DIV_SELECT_125MHZ = 3,
+} CCM_ANALOG_PLL_ENET_DIV_SELECT;
+
+// CCM ANALOG PLL Ethernet(n) register
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DIV_SELECT : 2;       // 0-1
+    UINT32 Zero1 : 5;            // 2-6
+    UINT32 Reserved1 : 5;        // 7-11
+    UINT32 POWERDOWN : 1;        // 12
+    UINT32 ENABLE : 1;           // 13
+    UINT32 BYPASS_CLK_SRC : 2;   // 14-15
+    UINT32 BYPASS : 1;           // 16
+    UINT32 Reserved2 : 1;        // 17
+    UINT32 PFD_OFFSET_EN : 1;    // 18
+    UINT32 ENABLE_125M : 1;      // 19
+    UINT32 ENABLE_100M : 1;      // 20
+    UINT32 Zero2 : 10;           // 21-30
+    UINT32 LOCK : 1;             // 31
+  };
+} IMX_CCM_ANALOG_PLL_ENET_REG;
+
+// CCM ANALOG PLL Ethernet(n) register
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 LVDS1_CLK_SEL : 5;    // 0-4
+    UINT32 LVDS2_CLK_SEL : 5;    // 5-9
+    UINT32 LVDSCLK1_OBEN : 1;    // 10
+    UINT32 LVDSCLK2_OBEN : 1;    // 11
+    UINT32 LVDSCLK1_IBEN : 1;    // 12
+    UINT32 LVDSCLK2_IBEN : 1;    // 13
+    UINT32 Reserved0 : 15;       // 14-28
+    UINT32 IRQ_TEMPSENSE : 1;    // 29
+    UINT32 IRQ_ANA_BO : 1;       // 30
+    UINT32 IRQ_DIG_BO : 1;       // 31
+  };
+} IMX_CCM_ANALOG_MISC1_REG;
+
+typedef struct {
+  UINT32 PLL_ARM;           // 0x000 Analog ARM PLL control Register (CCM_ANALOG_PLL_ARM)
+  UINT32 PLL_ARM_SET;       // 0x004 Analog ARM PLL control Register (CCM_ANALOG_PLL_ARM_SET)
+  UINT32 PLL_ARM_CLR;       // 0x008 Analog ARM PLL control Register (CCM_ANALOG_PLL_ARM_CLR)
+  UINT32 PLL_ARM_TOG;       // 0x00C Analog ARM PLL control Register (CCM_ANALOG_PLL_ARM_TOG)
+  UINT32 PLL_USB1;          // 0x010 Analog USB1 480MHz PLL Control Register (CCM_ANALOG_PLL_USB1)
+  UINT32 PLL_USB1_SET;      // 0x014 Analog USB1 480MHz PLL Control Register (CCM_ANALOG_PLL_USB1_SET)
+  UINT32 PLL_USB1_CLR;      // 0x018 Analog USB1 480MHz PLL Control Register (CCM_ANALOG_PLL_USB1_CLR)
+  UINT32 PLL_USB1_TOG;      // 0x01C Analog USB1 480MHz PLL Control Register (CCM_ANALOG_PLL_USB1_TOG)
+  UINT32 PLL_USB2;          // 0x020 Analog USB2 480MHz PLL Control Register (CCM_ANALOG_PLL_USB2)
+  UINT32 PLL_USB2_SET;      // 0x024 Analog USB2 480MHz PLL Control Register (CCM_ANALOG_PLL_USB2_SET)
+  UINT32 PLL_USB2_CLR;      // 0x028 Analog USB2 480MHz PLL Control Register (CCM_ANALOG_PLL_USB2_CLR)
+  UINT32 PLL_USB2_TOG;      // 0x02C Analog USB2 480MHz PLL Control Register (CCM_ANALOG_PLL_USB2_TOG)
+  UINT32 PLL_SYS;           // 0x030 Analog System PLL Control Register (CCM_ANALOG_PLL_SYS)
+  UINT32 PLL_SYS_SET;       // 0x034 Analog System PLL Control Register (CCM_ANALOG_PLL_SYS_SET)
+  UINT32 PLL_SYS_CLR;       // 0x038 Analog System PLL Control Register (CCM_ANALOG_PLL_SYS_CLR)
+  UINT32 PLL_SYS_TOG;       // 0x03C Analog System PLL Control Register (CCM_ANALOG_PLL_SYS_CLR)
+  UINT32 PLL_SYS_SS;        // 0x040 528MHz System PLL Spread Spectrum Register (CCM_ANALOG_PLL_SYS_SS)
+  UINT32 reserved1[3];
+  UINT32 PLL_SYS_NUM;       // 0x050 Numerator of 528MHz System PLL Fractional Loop
+                            //   Divider Register (CCM_ANALOG_PLL_SYS_NUM)
+  UINT32 reserved2[3];
+  UINT32 PLL_SYS_DENOM;     // 0x060 Denominator of 528MHz System PLL Fractional Loop
+                            //   Divider Register (CCM_ANALOG_PLL_SYS_DENOM)
+  UINT32 reserved3[3];
+  UINT32 PLL_AUDIO;         // 0x070 Analog Audio PLL control Register (CCM_ANALOG_PLL_AUDIO)
+  UINT32 PLL_AUDIO_SET;     // 0x074 Analog Audio PLL control Register (CCM_ANALOG_PLL_AUDIO_SET)
+  UINT32 PLL_AUDIO_CLR;     // 0x078 Analog Audio PLL control Register (CCM_ANALOG_PLL_AUDIO_CLR)
+  UINT32 PLL_AUDIO_TOG;     // 0x07C Analog Audio PLL control Register (CCM_ANALOG_PLL_AUDIO_TOG)
+  UINT32 PLL_AUDIO_NUM;     // 0x080 Numerator of Audio PLL Fractional Loop Divider
+                            //   Register (CCM_ANALOG_PLL_AUDIO_NUM)
+  UINT32 reserved4[3];
+  UINT32 PLL_AUDIO_DENOM;   // 0x090 Denominator of Audio PLL Fractional Loop Divider
+                            //   Register (CCM_ANALOG_PLL_AUDIO_DENOM)
+  UINT32 reserved5[3];
+  UINT32 PLL_VIDEO;         // 0x0A0 Analog Video PLL control Register (CCM_ANALOG_PLL_VIDEO)
+  UINT32 PLL_VIDEO_SET;     // 0x0A4 Analog Video PLL control Register (CCM_ANALOG_PLL_VIDEO_SET)
+  UINT32 PLL_VIDEO_CLR;     // 0x0A8 Analog Video PLL control Register (CCM_ANALOG_PLL_VIDEO_CLR)
+  UINT32 PLL_VIDEO_TOG;     // 0x0AC Analog Video PLL control Register (CCM_ANALOG_PLL_VIDEO_TOG)
+  UINT32 PLL_VIDEO_NUM;     // 0x0B0 Numerator of Video PLL Fractional Loop Divider
+                            //   Register (CCM_ANALOG_PLL_VIDEO_NUM)
+  UINT32 reserved6[3];
+  UINT32 PLL_VIDEO_DENOM;   // 0x0C0 Denominator of Video PLL Fractional Loop Divider
+                            //   Register (CCM_ANALOG_PLL_VIDEO_DENOM)
+  UINT32 reserved7[3];
+  UINT32 PLL_MLB;           // 0x0D0 MLB PLL Control Register (CCM_ANALOG_PLL_MLB)
+  UINT32 PLL_MLB_SET;       // 0x0D4 MLB PLL Control Register (CCM_ANALOG_PLL_MLB_SET)
+  UINT32 PLL_MLB_CLR;       // 0x0D8 MLB PLL Control Register (CCM_ANALOG_PLL_MLB_CLR)
+  UINT32 PLL_MLB_TOG;       // 0x0DC MLB PLL Control Register (CCM_ANALOG_PLL_MLB_TOG)
+  UINT32 PLL_ENET;          // 0x0E0 Analog ENET PLL Control Register (CCM_ANALOG_PLL_ENET)
+  UINT32 PLL_ENET_SET;      // 0x0E4 Analog ENET PLL Control Register (CCM_ANALOG_PLL_ENET_SET)
+  UINT32 PLL_ENET_CLR;      // 0x0E8 Analog ENET PLL Control Register (CCM_ANALOG_PLL_ENET_CLR)
+  UINT32 PLL_ENET_TOG;      // 0x0EC Analog ENET PLL Control Register (CCM_ANALOG_PLL_ENET_TOG)
+  UINT32 PFD_480;           // 0x0F0 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_480)
+  UINT32 PFD_480_SET;       // 0x0F4 480MHz Clock (PLL3) Phase Fractional Divider Control
+                            //   Register (CCM_ANALOG_PFD_480_SET)
+  UINT32 PFD_480_CLR;       // 0x0F8 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_480_CLR)
+  UINT32 PFD_480_TOG;       // 0x0FC 480MHz Clock (PLL3) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_480_TOG)
+  UINT32 PFD_528;           // 0x100 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_528)
+  UINT32 PFD_528_SET;       // 0x104 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_528_SET)
+  UINT32 PFD_528_CLR;       // 0x108 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_528_CLR)
+  UINT32 PFD_528_TOG;       // 0x10C 528MHz Clock (PLL2) Phase Fractional Divider
+                            //   Control Register (CCM_ANALOG_PFD_528_TOG)
+  UINT32 PMU_REG_1P1;       // 0x110 Regulator 1P1 Register (PMU_REG_1P1)
+  UINT32 PMU_REG_1P1_SET;   // 0x114
+  UINT32 PMU_REG_1P1_CLR;   // 0x118
+  UINT32 PMU_REG_1P1_TOG;   // 0x11C
+  UINT32 PMU_REG_3P0;       // 0X120 Regulator 3P0 Register (PMU_REG_3P0)
+  UINT32 PMU_REG_3P0_SET;   // 0x124
+  UINT32 PMU_REG_3P0_CLR;   // 0x128
+  UINT32 PMU_REG_3P0_TOG;   // 0x12C
+  UINT32 PMU_REG_2P5;       // 0x130 Regulator 2P5 Register (PMU_REG_2P5)
+  UINT32 PMU_REG_2P5_SET;   // 0x134
+  UINT32 PMU_REG_2P5_CLR;   // 0x138
+  UINT32 PMU_REG_2P5_TOG;   // 0x13C
+  UINT32 PMU_REG_CORE;      // 0x140 Digital Regulator Core Register (PMU_REG_CORE)
+  UINT32 PMU_REG_CORE_SET;  // 0x144
+  UINT32 PMU_REG_CORE_CLR;  // 0x148
+  UINT32 PMU_REG_CORE_TOG;  // 0x14C
+  UINT32 MISC0;             // 0x150 Miscellaneous Register 0 (CCM_ANALOG_MISC0)
+  UINT32 MISC0_SET;         // 0x154 Miscellaneous Register 0 (CCM_ANALOG_MISC0_SET)
+  UINT32 MISC0_CLR;         // 0x158 Miscellaneous Register 0 (CCM_ANALOG_MISC0_CLR)
+  UINT32 MISC0_TOG;         // 0x15C Miscellaneous Register 0 (CCM_ANALOG_MISC0_TOG)
+  UINT32 MISC1;             // 0x160 Miscellaneous Register 1 (CCM_ANALOG_MISC1)
+  UINT32 MISC1_SET;         // 0x164 Miscellaneous Register 1 (CCM_ANALOG_MISC1_SET)
+  UINT32 MISC1_CLR;         // 0x168 Miscellaneous Register 1 (CCM_ANALOG_MISC1_CLR)
+  UINT32 MISC1_TOG;         // 0x16C Miscellaneous Register 1 (CCM_ANALOG_MISC1_TOG)
+  UINT32 MISC2;             // 0x170 Miscellaneous Register 2 (CCM_ANALOG_MISC2)
+  UINT32 MISC2_SET;         // 0x174 Miscellaneous Register 2 (CCM_ANALOG_MISC2_SET)
+  UINT32 MISC2_CLR;         // 0x178 Miscellaneous Register 2 (CCM_ANALOG_MISC2_CLR)
+  UINT32 MISC2_TOG;         // 0x17C Miscellaneous Register 2 (CCM_ANALOG_MISC2_TOG)
+} IMX_CCM_ANALOG_REGISTERS;
+
+// General Power Controller (GPC)
+#define IMX_GPC_BASE 0x020DC000
+#define IMX_GPC_LENGTH 0x1000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 PCR : 1;         // 0 Power Control
+    UINT32 reserved : 31;   // 1-31
+  };
+} IMX_GPC_PGC_PGCR_REG;
+
+#define IMX_GPC_PGC_PUPSCR_SW_DEFAULT 1
+#define IMX_GPC_PGC_PUPSCR_SW2ISO_DEFAULT 0xf
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 SW : 6;          // 0-5 Number of IPG clock cycles before asserting
+                            //   power toggle on/off signal (switch_b)
+    UINT32 reserved1 : 2;   // 6-7
+    UINT32 SW2ISO : 6;      // 8-13 IPG clock cycles before negating isolation
+    UINT32 reserved2 : 18;  // 14-31
+  };
+} IMX_GPC_PGC_PUPSCR_REG;
+
+#define IMX_GPC_PGC_PDNSCR_ISO_DEFAULT 1
+#define IMX_GPC_PGC_PDNSCR_ISO2SW_DEFAULT 1
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 ISO : 6;         // 0-5 Number of IPG clocks before isolation
+    UINT32 reserved1 : 2;   // 6-7
+    UINT32 ISO2SW : 6;      // 8-13 number of IPG clocks before negating power
+                            //   toggle on/off signal (switch_b)
+    UINT32 reserved2 : 18;  // 14-31
+  };
+} IMX_GPC_PGC_PDNSCR_REG;
+
+typedef struct {
+  UINT32 CTRL;      // 0x0 PGC Control Register (PGC_GPU/CPU_CTRL)
+  UINT32 PUPSCR;    // 0x4 Power Up Sequence Control Register (PGC_GPU/CPU_PUPSCR)
+  UINT32 PDNSCR;    // 0x8 Pull Down Sequence Control Register (PGC_GPU/CPU_PDNSCR)
+  UINT32 SR;        // 0xC Power Gating Controller Status Register (PGC_GPU/CPU_SR)
+} IMX_GPC_PGC_REGISTERS;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 gpu_vpu_pdn_req : 1;   // 0 GPU/VPU Power Down request. Self-cleared bit.
+    UINT32 gpu_vpu_pup_req : 1;   // 1 GPU/VPU Power Up request. Self-cleared bit.
+    UINT32 reserved1 : 14;        // 2-15
+    UINT32 DVFS0CR : 1;           // 16 DVFS0 (ARM) Change request (bit is read-only)
+    UINT32 reserved2 : 4;         // 17-20
+    UINT32 GPCIRQM : 1;           // 21 GPC interrupt/event masking
+    UINT32 reserved3 : 10;        // 22-31
+  };
+} IMX_GPC_CNTR_REG;
+
+typedef struct {
+  UINT32 CNTR;                    // 0x000 GPC Interface control register (GPC_CNTR)
+  UINT32 PGR;                     // 0x004 GPC Power Gating Register (GPC_PGR)
+  UINT32 IMR1;                    // 0x008 IRQ masking register 1 (GPC_IMR1)
+  UINT32 IMR2;                    // 0x00C IRQ masking register 2 (GPC_IMR2)
+  UINT32 IMR3;                    // 0x010 IRQ masking register 3 (GPC_IMR3)
+  UINT32 IMR4;                    // 0x014 IRQ masking register 4 (GPC_IMR4)
+  UINT32 ISR1;                    // 0x018 IRQ status resister 1 (GPC_ISR1)
+  UINT32 ISR2;                    // 0x01C IRQ status resister 2 (GPC_ISR2)
+  UINT32 ISR3;                    // 0x020 IRQ status resister 3 (GPC_ISR3)
+  UINT32 ISR4;                    // 0x024 IRQ status resister 4 (GPC_ISR4)
+  UINT32 reserved1[142];
+  IMX_GPC_PGC_REGISTERS PGC_GPU;  // 0x260-0x26C GPU PGC Control
+  UINT32 reserved2[12];
+  IMX_GPC_PGC_REGISTERS PGC_CPU;  // 0x2A0-0x2AC CPU PGC Control
+} IMX_GPC_REGISTERS;
+
+// Ethernet controller (ENET)
+#define IMX_ENET_BASE 0x02188000
+#define IMX_ENET_LENGTH 0x4000
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 RESET : 1;       // 0 Ethernet MAC Reset
+    UINT32 ETHEREN : 1;     // 1 Ethernet Enable
+    UINT32 MAGICEN : 1;     // 2 Magic Packet Detection Enable
+    UINT32 SLEEP : 1;       // 3 Sleep Mode Enable
+    UINT32 EN1588 : 1;      // 4 EN1588 Enable
+    UINT32 SPEED : 1;       // 5 Selects between 10/100 and 1000 Mbps modes of operation
+    UINT32 DBGEN : 1;       // 6 Debug Enable
+    UINT32 STOPEN : 1;      // 7 STOPEN Signal Control
+    UINT32 DBSWP : 1;       // 8 Descriptor Byte Swapping Enable
+    UINT32 reserved1 : 3;   // 9-11
+    UINT32 reserved2 : 20;  // 12-31 This field must be set to F_0000h
+  };
+} IMX_ENET_ECR_REG;
+
+typedef struct {
+  UINT32 reserved0;     // 0
+  UINT32 EIR;           // 4
+  UINT32 EIMR;          // 8
+  UINT32 reserved1;     // Ch
+  UINT32 RDAR;          // 10h
+  UINT32 TDAR;          // 14h
+  UINT32 reserved2[3];  // 18h - 20h
+  UINT32 ECR;           // 24h Ethernet Control Register (ENET_ECR)
+  UINT32 reserved3[6];  // 28h - 3Ch
+  UINT32 MMFR;          // 40h
+  UINT32 MSCR;          // 44h
+  UINT32 reserved4[7];  // 48h - 60h
+  UINT32 MIBC;          // 64h
+  UINT32 reserved5[7];  //
+  UINT32 RCR;           // 84h
+  UINT32 reserved6[15]; //
+  UINT32 TCR;           // C4h
+  UINT32 reserved7[7];
+  UINT32 PALR;          // E4h
+  UINT32 PAUR;          // E8h
+  UINT32 OPD;           // ECh
+  UINT32 reserved8[322];
+} IMX_ENET_REGISTERS;
+
+// GPIO Controller (GPIO)
+#define IMX_GPIO_BASE 0x0209C000
+#define IMX_GPIO_LENGTH (7 * 0x4000)
+
+// USB CORE (EHCI)
+#define IMX_USBCORE_BASE    0x02184000
+#define IMX_USBCORE_LENGTH  0x200
+#define IMX_USBCMD_OFFSET   0x140
+#define IMX_USBMODE_OFFSET  0x1A8
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 RS : 1;          // 0 Run/Stop (RS). Default 0b. 1=Run. 0=Stop.
+    UINT32 RST : 1;         // 1 Controller Reset (RESET).
+    UINT32 FS_1 : 2;        // 2-3 Frame List Size. Default 000b.
+    UINT32 PSE : 1;         // 4 Periodic Schedule Enable. Default 0b.
+    UINT32 ASE : 1;         // 5 Asynchronous Schedule Enable. Default 0b.
+    UINT32 IAA : 1;         // 6 Interrupt on Async Advance Doorbell.
+    UINT32 reserved1 : 1;   // 7
+    UINT32 ASP : 2;         // 8-9 Asynchronous Schedule Park Mode Count (OPTIONAL).
+    UINT32 reserved2 : 1;   // 10 Reserved
+    UINT32 ASPE : 1;        // 11 Asynchronous Schedule Park Mode Enable (OPTIONAL).
+    UINT32 ATDTW : 1;       // 12 Add dTD TripWire C. [device mode only]
+    UINT32 SUTW : 1;        // 13 Setup TripWire C. [device mode only]
+    UINT32 reserved3 : 1;   // 14
+    UINT32 FS2 : 1;         // 15 Frame List Size. [host mode only]
+    UINT32 ITC : 8;         // 16-23 Interrupt Threshold Control. Default 08h.
+    UINT32 reserved : 8;    // 24-31 Reserved
+  };
+} USB_USBCMD_REG;
+
+typedef enum {
+  IMX_USBMODE_IDLE = 0,
+  IMX_USBMODE_DEVICE = 2,
+  IMX_USBMODE_HOST = 3,
+} IMX_USBMODE_CM;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CM : 2;          // 0-1 Controller Mode.
+    UINT32 ES : 1;          // 1 Endian Select (0- Little, 1-Big)
+    UINT32 SLOM : 1;        // 3 Setup Lockout Mode
+    UINT32 SDIS : 1;        // 4 Stream Disable Mode
+    UINT32 reserved : 26;   // 5-31
+  };
+} USB_USBMODE_REG;
+
+// USB Non-CORE
+#define IMX_USBNONCORE_BASE 0x02184800
+#define IMX_USBNONCORE_LENGTH 0x20
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 7;       // 0-6
+    UINT32 OVER_CUR_DIS : 1;    // 7 Disable Overcurrent Detection
+    UINT32 OVER_CUR_POL : 1;    // 8 Polarity of Overcurrent (1-active low, 0-active high)
+    UINT32 PWR_POL : 1;         // 9 Power Polarity (1-active high, 0-active low)
+    UINT32 WIE : 1;             // 10 Wake-up Interrupt Enable
+    UINT32 RESET : 1;           // 11 Force Host 1 UTMI PHY Reset.
+    UINT32 SUSPENDM : 1;        // 12 Force Host 1 UTMI PHY Suspend.
+    UINT32 UTMI_ON_CLOCK : 1;   // 13 Force UTMI PHY clock output on even if in
+                                //   low-power suspend mode.
+    UINT32 WKUP_SW_EN : 1;      // 14 Software Wake-up Enable
+    UINT32 WKUP_SW : 1;         // 15 Software Wake-up
+    UINT32 WKUP_ID_EN : 1;      // 16 Wake-up on ID change enable
+    UINT32 WKUP_VBUS_EN : 1;    // 17 wake-up on VBUS change enable
+    UINT32 reserved2 : 13;      // 18-30
+    UINT32 WIR : 1;             // 31 Wake-up Interrupt Request
+  };
+} USBNC_USB_UH_CTRL_REG;
+
+typedef struct {
+  UINT32 USBNC_USB_OTG_CTRL;          // 0x00 USB OTG Control Register
+  UINT32 USBNC_USB_UH1_CTRL;          // 0x04 USB Host1 Control Register
+  UINT32 USBNC_USB_UH2_CTRL;          // 0x08 USB Host2 Control Register
+  UINT32 USBNC_USB_UH3_CTRL;          // 0x0C USB Host3 Control Register
+  UINT32 USBNC_USB_UH2_HSIC_CTRL;     // 0x10 USB Host2 HSIC Control Register
+  UINT32 USBNC_USB_UH3_HSIC_CTRL;     // 0x14 USB Host3 HSIC Control Register
+  UINT32 USBNC_USB_OTG_PHY_CTRL_0;    // 0x18 OTG UTMI PHY Control 0 Register
+  UINT32 USBNC_USB_UH1_PHY_CTRL_0;    // 0x1C Host1 UTMI PHY Control 0 Register
+} IMX_USBNONCORE_REGISTERS;
+
+typedef enum {
+  IMX_USBPHY0, // OTG
+  IMX_USBPHY1,
+  IMX_USBPHY_COUNT
+} IMX_USBPHY_ID;
+
+// USB Analog
+#define IMX_USBANA_BASE 0x020C81A0
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 reserved1 : 18;  // 0-17
+    UINT32 CHK_CONTACT : 1; // 18
+    UINT32 CHK_CHRG_B : 1;  // 19
+    UINT32 EN_B : 1;        // 20
+    UINT32 reserved2 : 11;  // 21-31
+  };
+} USB_ANALOG_USB_CHRG_DETECT_REG;
+
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 HS_USE_EXTERNAL_R : 1;   // 0 Use external resistor to generate the
+                                    //   current bias for the high speed transmitter.
+    UINT32 EN_DEGLITCH : 1;         // 1 Enable the deglitching circuit of the
+                                    //   USB PLL output.
+    UINT32 reserved1 : 28;          // 2-29
+    UINT32 EN_CLK_UTMI : 1;         // 30 Enables the clk to the UTMI block.
+    UINT32 reserved2 : 1;           // 31
+  };
+} USB_ANALOG_USB_MISC_REG;
+
+typedef struct {
+  UINT32 USB_ANALOG_USB_VBUS_DETECT;       // 0x00 USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_SET;   // 0x04 USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_CLR;   // 0x08 USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_TOG;   // 0x0C USB VBUS Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT;       // 0x10 USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_SET;   // 0x14 USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_CLR;   // 0x18 USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_TOG;   // 0x1C USB Charger Detect Register
+  UINT32 USB_ANALOG_USB_VBUS_DETECT_STAT;  // 0x20 USB VBUS Detect Status Register
+  UINT32 reserved1[3];
+  UINT32 USB_ANALOG_USB_CHRG_DETECT_STAT;  // 0x30 USB Charger Detect Status Register
+  UINT32 reserved2[7];
+  UINT32 USB_ANALOG_USB_MISC;              // 0x50 USB Misc Register
+  UINT32 USB_ANALOG_USB_MISC_SET;          // 0x54 USB Misc Register
+  UINT32 USB_ANALOG_USB_MISC_CLR;          // 0x58 USB Misc Register
+  UINT32 USB_ANALOG_USB_MISC_TOG;          // 0x5C USB Misc Register
+} IMX_USBANA_USB_REGISTERS;
+
+typedef struct {
+  IMX_USBANA_USB_REGISTERS USBANA[IMX_USBPHY_COUNT];
+  UINT32 USB_ANALOG_DIGPROG;                // 0xC0 Chip Silicon Version
+} IMX_USBANA_REGISTERS;
+
+#pragma pack(pop)
+
+#endif // __IMX6_COMMON_H__
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (10 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 11/27] Silicon/NXP: Add i.MX6 SoC header files Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-11-08 18:00   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 13/27] Silicon/NXP: Add support for iMX SDHC Chris Co
                   ` (15 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for initializing and manipulating the I/O Pads
on NXP i.MX6 SoCs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c      | 151 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf |  41 ++++++
 2 files changed, 192 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
new file mode 100644
index 000000000000..7c0c7b54a2fe
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
@@ -0,0 +1,151 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+
+#include <iMX6.h>
+#include <iMX6IoMux.h>
+
+// Muxing functions
+VOID
+ImxPadConfig (
+  IN  IMX_PAD     Pad,
+  IN  IMX_PADCFG  PadConfig
+  )
+{
+  // Configure Mux Control
+  MmioWrite32 (
+    IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad),
+    _IMX_PADCFG_MUX_CTL (PadConfig));
+
+  // Configure Select Input Control
+  if (_IMX_PADCFG_SEL_INP (PadConfig) != 0) {
+    DEBUG ((DEBUG_INFO, "Setting INPUT_SELECT %x value %x\n",
+            _IMX_SEL_INP_REGISTER (_IMX_PADCFG_SEL_INP (PadConfig)),
+            _IMX_SEL_INP_VALUE (_IMX_PADCFG_SEL_INP (PadConfig))));
+
+    MmioWrite32 (
+      _IMX_SEL_INP_REGISTER (_IMX_PADCFG_SEL_INP (PadConfig)),
+      _IMX_SEL_INP_VALUE (_IMX_PADCFG_SEL_INP (PadConfig)));
+  }
+
+  // Configure Pad Control
+  MmioWrite32 (
+    IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad),
+    _IMX_PADCFG_PAD_CTL (PadConfig));
+}
+
+VOID
+ImxPadDumpConfig (
+  IN  CHAR8 *SignalFriendlyName,
+  IN  IMX_PAD Pad
+  )
+{
+  IMX_IOMUXC_MUX_CTL  MuxCtl;
+  IMX_IOMUXC_PAD_CTL  PadCtl;
+
+  MuxCtl.AsUint32 = MmioRead32 (
+                      IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad));
+
+  DEBUG ((
+           DEBUG_INIT,
+           "- %a MUX_CTL(0x%p)=0x%08x: MUX_MODE:%d SION:%d | ",
+           SignalFriendlyName,
+           IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad),
+           MuxCtl.AsUint32,
+           MuxCtl.Fields.MUX_MODE,
+           MuxCtl.Fields.SION));
+
+  PadCtl.AsUint32 = MmioRead32 (
+                      IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad));
+
+  DEBUG ((
+           DEBUG_INIT,
+           "PAD_CTL(0x%p)=0x%08x: SRE:%d DSE:%d SPEED:%d ODE:%d PKE:%d PUE:%d PUS:%d HYS:%d\n",
+           IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad),
+           PadCtl.AsUint32,
+           PadCtl.Fields.SRE,
+           PadCtl.Fields.DSE,
+           PadCtl.Fields.SPEED,
+           PadCtl.Fields.ODE,
+           PadCtl.Fields.PKE,
+           PadCtl.Fields.PUE,
+           PadCtl.Fields.PUS,
+           PadCtl.Fields.HYS));
+}
+
+// GPIO functions
+VOID
+ImxGpioDirection (
+  IN  IMX_GPIO_BANK   Bank,
+  IN  UINT32          IoNumber,
+  IN  IMX_GPIO_DIR    Direction
+  )
+{
+  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
+
+  ASSERT (IoNumber < 32);
+
+  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;
+  if (Direction == IMX_GPIO_DIR_INPUT) {
+    MmioAnd32 ((UINTN) &gpioRegisters->Banks[Bank - 1].GDIR, ~ (1 << IoNumber));
+  } else {
+    MmioOr32 ((UINTN) &gpioRegisters->Banks[Bank - 1].GDIR, 1 << IoNumber);
+  }
+}
+
+VOID
+ImxGpioWrite (
+  IN  IMX_GPIO_BANK   Bank,
+  IN  UINT32          IoNumber,
+  IN  IMX_GPIO_VALUE  Value
+  )
+{
+  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
+
+  ASSERT (IoNumber < 32);
+
+  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;
+  if (Value == IMX_GPIO_LOW) {
+    MmioAnd32 ((UINTN) &gpioRegisters->Banks[Bank - 1].DR, ~ (1 << IoNumber));
+  } else {
+    MmioOr32 ((UINTN) &gpioRegisters->Banks[Bank - 1].DR, 1 << IoNumber);
+  }
+}
+
+IMX_GPIO_VALUE
+ImxGpioRead (
+  IN  IMX_GPIO_BANK   Bank,
+  IN  UINT32          IoNumber
+  )
+{
+  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
+  UINT32                        Mask;
+  UINT32                        Psr;
+
+  ASSERT (IoNumber < 32);
+
+  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;
+  Mask = (1 << IoNumber);
+  Psr = MmioRead32 ((UINTN) &gpioRegisters->Banks[Bank - 1].PSR);
+
+  if (Psr & Mask) {
+    return IMX_GPIO_HIGH;
+  } else {
+    return IMX_GPIO_LOW;
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
new file mode 100644
index 000000000000..84bbbee5c1db
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
@@ -0,0 +1,41 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMX6IoMuxLib
+  FILE_GUID                      = FA41BEF0-0666-4C07-9EC3-47F61C36EDBE
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = iMX6IoMuxLib
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  TimerLib
+
+[Sources.common]
+  iMX6IoMux.c
+
+ [FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 13/27] Silicon/NXP: Add support for iMX SDHC
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (11 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-05 10:31   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers Chris Co
                   ` (14 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for using the SD host controller on
NXP i.MX platforms.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c   | 1246 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h   |   81 ++
 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf |   70 ++
 Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h          |  277 +++++
 4 files changed, 1674 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
new file mode 100644
index 000000000000..9fe0bc3792a9
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
@@ -0,0 +1,1246 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DmaLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/Sdhc.h>
+
+#include <iMXuSdhc.h>
+#include <iMXGpio.h>
+#include "SdhcDxe.h"
+
+VOID
+DumpState (
+  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
+  )
+{
+  DEBUG_CODE_BEGIN ();
+
+  USDHC_REGISTERS         *Reg;
+  USDHC_BLK_ATT_REG       BlkAtt;
+  UINT32                  CmdArg;
+  USDHC_CMD_XFR_TYP_REG   CmdXfrTyp;
+  UINT32                  IntSignalEn;
+  USDHC_INT_STATUS_REG    IntStatus;
+  UINT32                  IntStatusEn;
+  USDHC_MIX_CTRL_REG      MixCtrl;
+  UINT32                  MmcBoot;
+  USDHC_PRES_STATE_REG    PresState;
+  USDHC_PROT_CTRL_REG     ProtCtrl;
+  USDHC_WTMK_LVL_REG      WtmkLvl;
+  UINT32                  VendSpec;
+  UINT32                  VendSpec2;
+
+  Reg = SdhcCtx->RegistersBase;
+  BlkAtt.AsUint32 = MmioRead32 ((UINTN)&Reg->BLK_ATT);
+  CmdArg = MmioRead32 ((UINTN)&Reg->CMD_ARG);
+  CmdXfrTyp.AsUint32 = MmioRead32 ((UINTN)&Reg->CMD_XFR_TYP);
+  ProtCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->PROT_CTRL);
+  WtmkLvl.AsUint32 = MmioRead32 ((UINTN)&Reg->WTMK_LVL);
+  MixCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->MIX_CTRL);
+  IntStatusEn = MmioRead32 ((UINTN)&Reg->INT_STATUS_EN);
+  IntSignalEn = MmioRead32 ((UINTN)&Reg->INT_SIGNAL_EN);
+  VendSpec = MmioRead32 ((UINTN)&Reg->VEND_SPEC);
+  MmcBoot = MmioRead32 ((UINTN)&Reg->MMC_BOOT);
+  VendSpec2 = MmioRead32 ((UINTN)&Reg->VEND_SPEC2);
+  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+  PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+
+  LOG_INFO (
+    " - BLK_ATT\t:0x%08x BLKSIZE:0x%x BLKCNT:0x%08x",
+    BlkAtt.AsUint32,
+    BlkAtt.Fields.BLKSIZE,
+    BlkAtt.Fields.BLKCNT);
+
+  LOG_INFO (" - CMD_ARG\t:0x%08x", CmdArg);
+
+  LOG_INFO (
+    " - CMD_XFR_TYP\t:0x%08x RSPTYP:%d CCCEN:%d CICEN:%d DPSEL:%d CMDTYP:%d CMDINX:%d",
+    CmdXfrTyp.AsUint32,
+    CmdXfrTyp.Fields.RSPTYP,
+    CmdXfrTyp.Fields.CCCEN,
+    CmdXfrTyp.Fields.CICEN,
+    CmdXfrTyp.Fields.DPSEL,
+    CmdXfrTyp.Fields.CMDTYP,
+    CmdXfrTyp.Fields.CMDINX);
+
+  LOG_INFO (
+    " - PROT_CTRL\t:0x%08x DTW:%d D3CD:%d CDSS:%d EMODE:%d DMASEL:%d SABGREQ:%d BURST_LEN_EN:%d",
+    ProtCtrl.AsUint32,
+    ProtCtrl.Fields.DTW,
+    ProtCtrl.Fields.D3CD,
+    ProtCtrl.Fields.CDSS,
+    ProtCtrl.Fields.EMODE,
+    ProtCtrl.Fields.DMASEL,
+    ProtCtrl.Fields.SABGREQ,
+    ProtCtrl.Fields.BURST_LEN_EN);
+
+  LOG_INFO (
+    " - WTMK_LVL\t:0x%08x RD_WML:%d RD_BRST_LEN:%d WR_WML:%d WR_BRST_LEN:%d",
+    WtmkLvl.AsUint32,
+    WtmkLvl.Fields.RD_WML,
+    WtmkLvl.Fields.RD_BRST_LEN,
+    WtmkLvl.Fields.WR_WML,
+    WtmkLvl.Fields.WR_BRST_LEN);
+
+  LOG_INFO (
+    " - MIX_CTRL\t:0x%08x DMAEN:%d BCEN:%d AC12EN:%d DTDSEL:%d MSBSEL:%d AC23EN:%d FBCLK_SEL:%d",
+    MixCtrl.AsUint32,
+    MixCtrl.Fields.DMAEN,
+    MixCtrl.Fields.BCEN,
+    MixCtrl.Fields.AC12EN,
+    MixCtrl.Fields.DTDSEL,
+    MixCtrl.Fields.MSBSEL,
+    MixCtrl.Fields.AC23EN,
+    MixCtrl.Fields.FBCLK_SEL);
+
+  LOG_INFO (" - INT_STATUS_EN\t:0x%08x", IntStatusEn);
+  LOG_INFO (" - INT_SIGNAL_EN\t:0x%08x", IntSignalEn);
+  LOG_INFO (" - VEND_SPEC\t:0x%08x", VendSpec);
+  LOG_INFO (" - MMC_BOOT\t:0x%08x", MmcBoot);
+  LOG_INFO (" - VEND_SPEC2\t:0x%08x", VendSpec2);
+
+  LOG_INFO (
+    " - INT_STATUS\t:0x%08x CC:%d TC:%d BWR:%d BRR:%d CTOE:%d CCE:%d CEBE:%d CIE:%d DTOE:%d DCE:%d DEBE:%d",
+    IntStatus.AsUint32,
+    IntStatus.Fields.CC,
+    IntStatus.Fields.TC,
+    IntStatus.Fields.BWR,
+    IntStatus.Fields.BRR,
+    IntStatus.Fields.CTOE,
+    IntStatus.Fields.CCE,
+    IntStatus.Fields.CEBE,
+    IntStatus.Fields.CIE,
+    IntStatus.Fields.DTOE,
+    IntStatus.Fields.DCE,
+    IntStatus.Fields.DEBE);
+
+  LOG_INFO (
+    " - PRES_STATE\t:0x%08x CIHB:%d CDIHB:%d DLA:%d WTA:%d RTA:%d BWEN:%d BREN:%d CINST:%d DLSL:0x%x",
+    PresState.AsUint32,
+    PresState.Fields.CIHB,
+    PresState.Fields.CDIHB,
+    PresState.Fields.DLA,
+    PresState.Fields.WTA,
+    PresState.Fields.RTA,
+    PresState.Fields.BWEN,
+    PresState.Fields.BREN,
+    PresState.Fields.CINST,
+    PresState.Fields.DLSL);
+
+  DEBUG_CODE_END ();
+}
+
+EFI_STATUS
+WaitForReadFifo (
+  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
+  )
+{
+  USDHC_REGISTERS       *Reg;
+  USDHC_INT_STATUS_REG  IntStatus;
+  UINT32                Retry;
+
+  Reg = SdhcCtx->RegistersBase;
+  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+  Retry = USDHC_POLL_RETRY_COUNT;
+
+  while (!IntStatus.Fields.BRR &&
+         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
+         Retry) {
+    --Retry;
+    gBS->Stall (USDHC_POLL_WAIT_US);
+    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+  }
+
+  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
+    LOG_ERROR ("Error detected");
+    DumpState (SdhcCtx);
+    return EFI_DEVICE_ERROR;
+  } else if (IntStatus.Fields.BRR) {
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32);
+    return EFI_SUCCESS;
+  } else {
+    ASSERT (!Retry);
+    LOG_ERROR ("Time-out waiting on read FIFO");
+    DumpState (SdhcCtx);
+    return EFI_TIMEOUT;
+  }
+}
+
+EFI_STATUS
+WaitForWriteFifo (
+  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
+  )
+{
+  USDHC_REGISTERS       *Reg;
+  USDHC_INT_STATUS_REG  IntStatus;
+  UINT32                Retry;
+
+  Reg = SdhcCtx->RegistersBase;
+  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS) ;
+  Retry = USDHC_POLL_RETRY_COUNT;
+
+  while (!IntStatus.Fields.BWR &&
+         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
+         Retry) {
+    --Retry;
+    gBS->Stall (USDHC_POLL_WAIT_US);
+    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+  }
+
+  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
+    LOG_ERROR ("Error detected");
+    DumpState (SdhcCtx);
+    return EFI_DEVICE_ERROR;
+  } else if (IntStatus.Fields.BWR) {
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32);
+    return EFI_SUCCESS;
+  } else {
+    ASSERT (!Retry);
+    LOG_ERROR ("Time-out waiting on write FIFO");
+    DumpState (SdhcCtx);
+    return EFI_TIMEOUT;
+  }
+}
+
+EFI_STATUS
+WaitForCmdAndOrDataLine (
+  IN USDHC_PRIVATE_CONTEXT *SdhcCtx,
+  IN CONST SD_COMMAND *Cmd
+  )
+{
+  USDHC_REGISTERS       *Reg;
+  USDHC_INT_STATUS_REG  IntStatus;
+  USDHC_PRES_STATE_REG  PresState;
+  UINT32                Retry;
+  BOOLEAN               WaitForDataLine;
+
+  // Waiting on the DATA lines is the default behavior if no CMD is specified
+  if (Cmd == NULL) {
+    WaitForDataLine = TRUE;
+  } else {
+    // Per datasheet, the SDHC can isssue CMD0, CMD12, CMD13 and CMD52
+    // when the DATA lines are busy during a data transfer. Other commands
+    // should wait on the DATA lines before issuing
+    switch (Cmd->Index) {
+    case 0:
+    case 12:
+    case 13:
+    case 52:
+      WaitForDataLine = FALSE;
+      break;
+    default:
+      WaitForDataLine = TRUE;
+    }
+  }
+
+  Reg = SdhcCtx->RegistersBase;
+  PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS) ;
+  Retry = USDHC_POLL_RETRY_COUNT;
+
+  while (PresState.Fields.CIHB &&
+         (!WaitForDataLine || PresState.Fields.CDIHB) &&
+         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
+         Retry) {
+    gBS->Stall (USDHC_POLL_WAIT_US);
+    --Retry;
+    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+  }
+
+  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
+    LOG_ERROR ("Error detected");
+    DumpState (SdhcCtx);
+    return EFI_DEVICE_ERROR;
+  } else if (!(PresState.Fields.CIHB &&
+             (!WaitForDataLine || PresState.Fields.CDIHB))) {
+    return EFI_SUCCESS;
+  } else {
+    ASSERT (!Retry);
+    LOG_ERROR ("Time-out waiting on CMD and/or DATA lines");
+    DumpState (SdhcCtx);
+    return EFI_TIMEOUT;
+  }
+}
+
+EFI_STATUS
+WaitForCmdResponse (
+  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
+  )
+{
+  USDHC_REGISTERS       *Reg;
+  USDHC_INT_STATUS_REG  IntStatus;
+  UINT32                Retry;
+
+  Reg = SdhcCtx->RegistersBase;
+  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS) ;
+  Retry = USDHC_POLL_RETRY_COUNT;
+
+  // Wait for command to finish execution either with success or failure
+  while (!IntStatus.Fields.CC &&
+         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
+         Retry) {
+    gBS->Stall (USDHC_POLL_WAIT_US);
+    --Retry;
+    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+  }
+
+  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
+    LOG_ERROR ("Error detected");
+    DumpState (SdhcCtx);
+    return EFI_DEVICE_ERROR;
+  } else if (IntStatus.Fields.CC) {
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32);
+    return EFI_SUCCESS;
+  } else {
+    ASSERT (!Retry);
+    LOG_ERROR ("Time-out waiting on command completion");
+    DumpState (SdhcCtx);
+    return EFI_TIMEOUT;
+  }
+}
+
+EFI_STATUS
+SdhcSetBusWidth (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN SD_BUS_WIDTH BusWidth
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  USDHC_PROT_CTRL_REG     ProtCtrl;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+  Reg = SdhcCtx->RegistersBase;
+  ProtCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->PROT_CTRL);
+
+  LOG_TRACE ("SdhcSetBusWidth(%d)", BusWidth);
+
+  switch (BusWidth) {
+  case SdBusWidth1Bit:
+    ProtCtrl.Fields.DTW = USDHC_PROT_CTRL_DTW_1BIT;
+    break;
+  case SdBusWidth4Bit:
+    ProtCtrl.Fields.DTW = USDHC_PROT_CTRL_DTW_4BIT;
+    break;
+  case SdBusWidth8Bit:
+    ProtCtrl.Fields.DTW = USDHC_PROT_CTRL_DTW_8BIT;
+    break;
+  default:
+    LOG_ASSERT ("Invalid bus width");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MmioWrite32 ((UINTN)&Reg->PROT_CTRL, ProtCtrl.AsUint32);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSetClock (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN UINT32 TargetFreqHz
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  UINT32                  BestDivisor;
+  UINT32                  BestPrescaler;
+  UINT32                  Divisor;
+  UINT32                  FreqDistance;
+  UINT32                  MinFreqDistance;
+  USDHC_MIX_CTRL_REG      MixCtrl;
+  UINT32                  Prescaler;
+  USDHC_PRES_STATE_REG    PresState;
+  UINT32                  Retry;
+  UINT32                  SdClk;
+  USDHC_SYS_CTRL_REG      SysCtrl;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+  LOG_TRACE ("SdhcSetClock(%dHz)", TargetFreqHz);
+
+  Reg = SdhcCtx->RegistersBase;
+  SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+
+  // SdClk = (Base Clock) / (prescaler x divisor)
+  MixCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->MIX_CTRL);
+
+  // Bruteforce to find the best prescaler and divisor that result
+  // in SdClk less than or equal to the requested frequency
+  //
+  // Allowed |Base clock divided By
+  // SDCLKFS |DDR_EN=0   |DDR_EN=1
+  // 80h      256         512
+  // 40h      128         256
+  // 20h      64          128
+  // 10h      32          64
+  // 08h      16          32
+  // 04h      8           16
+  // 02h      4           8
+  // 01h      2           4
+  // 00h      1           2
+  CONST UINT32 PRESCALER_MIN = (MixCtrl.Fields.DDR_EN ? 2 : 1);
+  CONST UINT32 PRESCALER_MAX = (MixCtrl.Fields.DDR_EN ? 512 : 256);;
+  CONST UINT32 DIVISOR_MIN = 1;
+  CONST UINT32 DIVISOR_MAX = 16;
+  MinFreqDistance = MAX_UINT32;
+  BestPrescaler = 0;
+  BestDivisor = 0;
+
+  //
+  // Bruteforce to find the best prescaler and divisor that result
+  // in SdClk less than or equal to the requested frequency
+  //
+  for (Prescaler = PRESCALER_MAX; Prescaler >= PRESCALER_MIN; Prescaler /= 2) {
+    for (Divisor = DIVISOR_MIN; Divisor <= DIVISOR_MAX; ++Divisor) {
+      SdClk = USDHC_BASE_CLOCK_FREQ_HZ / (Prescaler * Divisor);
+
+      //
+      // We are not willing to choose clocks higher than the target one
+      // to avoid exceeding device limits
+      //
+      if (SdClk > TargetFreqHz) {
+        continue;
+      } else if (SdClk == TargetFreqHz) {
+        BestPrescaler = Prescaler;
+        BestDivisor = Divisor;
+        break;
+      } else {
+        FreqDistance = TargetFreqHz - SdClk;
+        if (FreqDistance < MinFreqDistance) {
+          MinFreqDistance = FreqDistance;
+          BestPrescaler = Prescaler;
+          BestDivisor = Divisor;
+        }
+      }
+    }
+  }
+
+  // Wait for clock to become stable before any modifications
+  PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+  Retry = USDHC_POLL_RETRY_COUNT;
+
+  while (!PresState.Fields.SDSTB &&
+         Retry) {
+    gBS->Stall (USDHC_POLL_WAIT_US);
+    --Retry;
+    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+  }
+
+  if (!PresState.Fields.SDSTB) {
+    ASSERT (!Retry);
+    LOG_ERROR ("Time-out waiting on SD clock to stabilize");
+    DumpState (SdhcCtx);
+    return EFI_TIMEOUT;
+  }
+
+  SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+  SysCtrl.Fields.SDCLKFS = BestPrescaler / (MixCtrl.Fields.DDR_EN ? 4 : 2);
+  SysCtrl.Fields.DVS = BestDivisor - 1;
+
+  MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
+
+  SdClk = USDHC_BASE_CLOCK_FREQ_HZ / (BestPrescaler * BestDivisor);
+
+  LOG_TRACE (
+    "Current SdClk:%dHz SDCLKFS:0x%x DVS:0x%x",
+    SdClk,
+    (UINT32)SysCtrl.Fields.SDCLKFS,
+    (UINT32)SysCtrl.Fields.DVS);
+
+  return EFI_SUCCESS;
+}
+
+BOOLEAN
+SdhcIsCardPresent (
+  IN EFI_SDHC_PROTOCOL *This
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  IMX_GPIO_VALUE          CardDetectLevel;
+  BOOLEAN                 IsCardPresent;
+  USDHC_PRES_STATE_REG    PresState;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+  if (SdhcCtx->CardDetectSignal == USDHC_SIGNAL_INTERNAL_PIN) {
+    Reg = SdhcCtx->RegistersBase;
+    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+    IsCardPresent = (PresState.Fields.CINST == 1);
+  } else {
+    if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal)) {
+      //Read the state of  CD_B pin for the card socket
+      CardDetectLevel = ImxGpioRead (
+                         SdhcCtx->CardDetectGpioPin.Bank,
+                         SdhcCtx->CardDetectGpioPin.IoNumber
+                         );
+    } else if (SdhcCtx->CardDetectSignal == USDHC_SIGNAL_OVERRIDE_PIN_LOW) {
+      CardDetectLevel = IMX_GPIO_LOW;
+    } else if (SdhcCtx->CardDetectSignal == USDHC_SIGNAL_OVERRIDE_PIN_HIGH) {
+      CardDetectLevel = IMX_GPIO_HIGH;
+    } else {
+      ASSERT (!"Invalid CardDetect signal source");
+      CardDetectLevel = IMX_GPIO_LOW;
+    }
+
+    // When no card is present,  CD_B is pulled-high, and the SDCard when
+    // inserted will pull CD_B low
+    // CD_B=0 means card present, while CD_B=1 means card not present
+    IsCardPresent = (CardDetectLevel == IMX_GPIO_LOW);
+  }
+
+  LOG_TRACE ("SdhcIsCardPresent(): %d", IsCardPresent);
+
+  return IsCardPresent;
+}
+
+BOOLEAN
+SdhcIsReadOnly (
+  IN EFI_SDHC_PROTOCOL *This
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  BOOLEAN                 IsReadOnly;
+  USDHC_PRES_STATE_REG    PresState;
+  IMX_GPIO_VALUE          WriteProtectLevel;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+
+  if (SdhcCtx->WriteProtectSignal == USDHC_SIGNAL_INTERNAL_PIN) {
+    Reg = SdhcCtx->RegistersBase;
+    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+    IsReadOnly = (PresState.Fields.WPSPL == 0);
+  } else {
+    if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal)) {
+      //Read the state of  WP pin for the card socket
+      WriteProtectLevel = ImxGpioRead (
+                           SdhcCtx->WriteProtectGpioPin.Bank,
+                           SdhcCtx->WriteProtectGpioPin.IoNumber
+                           );
+    } else if (SdhcCtx->WriteProtectSignal == USDHC_SIGNAL_OVERRIDE_PIN_LOW) {
+      WriteProtectLevel = IMX_GPIO_LOW;
+    } else if (SdhcCtx->WriteProtectSignal == USDHC_SIGNAL_OVERRIDE_PIN_HIGH) {
+      WriteProtectLevel = IMX_GPIO_HIGH;
+    } else {
+      ASSERT (!"Invalid WriteProtect signal source");
+      WriteProtectLevel = IMX_GPIO_LOW;
+    }
+
+    // When no card is present,  WP is pulled-high, and the SDCard when
+    // inserted will pull WP low if WP switch is configured to write enable
+    // the SDCard, otherwise it WP will stay pulled-high
+    // WP=0 means write enabled, while WP=1 means write protected
+    IsReadOnly = (WriteProtectLevel != IMX_GPIO_LOW);
+  }
+
+  LOG_TRACE ("SdhcIsReadOnly(): %d", IsReadOnly);
+  return IsReadOnly;
+}
+
+EFI_STATUS
+SdhcSendCommand (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN CONST SD_COMMAND *Cmd,
+  IN UINT32 Argument,
+  IN OPTIONAL CONST SD_COMMAND_XFR_INFO *XfrInfo
+  )
+{
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  USDHC_REGISTERS         *Reg;
+  USDHC_BLK_ATT_REG       BlkAtt;
+  USDHC_CMD_XFR_TYP_REG   CmdXfrTyp;
+  USDHC_MIX_CTRL_REG      MixCtrl;
+  EFI_STATUS              Status;
+  USDHC_WTMK_LVL_REG      WtmkLvl;
+  UINT32                  WtmkThreshold;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+  Reg = SdhcCtx->RegistersBase;
+
+  LOG_TRACE (
+    "SdhcSendCommand(%cCMD%d, %08x)",
+    ((Cmd->Class == SdCommandClassApp) ? 'A' : ' '),
+    (UINT32)Cmd->Index,
+    Argument);
+
+  Status = WaitForCmdAndOrDataLine (SdhcCtx, Cmd);
+  if (Status != EFI_SUCCESS) {
+    LOG_ERROR ("SdhcWaitForCmdAndDataLine failed");
+    return Status;
+  }
+
+  // Clear Interrupt status
+  MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
+
+  // Setup data transfer command
+  if (XfrInfo) {
+    if (XfrInfo->BlockCount > USDHC_MAX_BLOCK_COUNT) {
+      LOG_ERROR (
+        "Provided %d block count while SDHC max block count is %d",
+        XfrInfo->BlockCount,
+        USDHC_MAX_BLOCK_COUNT);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // Set block size and count
+    BlkAtt.AsUint32 = 0;
+    BlkAtt.Fields.BLKSIZE = XfrInfo->BlockSize;
+    ASSERT (XfrInfo->BlockCount > 0);
+    BlkAtt.Fields.BLKCNT = XfrInfo->BlockCount;
+    MmioWrite32 ((UINTN)&Reg->BLK_ATT, BlkAtt.AsUint32);
+
+    // Set transfer parameters
+    MixCtrl.AsUint32 = 0;
+    if (Cmd->TransferDirection == SdTransferDirectionRead) {
+      MixCtrl.Fields.DTDSEL = 1;
+    }
+
+    if (XfrInfo->BlockCount > 1) {
+      ASSERT ((Cmd->TransferType == SdTransferTypeMultiBlock) ||
+              (Cmd->TransferType == SdTransferTypeMultiBlockNoStop));
+      MixCtrl.Fields.MSBSEL = 1;
+      MixCtrl.Fields.BCEN = 1;
+    }
+
+    MmioWrite32 ((UINTN)&Reg->MIX_CTRL, MixCtrl.AsUint32);
+
+    WtmkLvl.AsUint32 = 0;
+
+    WtmkThreshold = USDHC_BLOCK_LENGTH_BYTES / 4;
+    if (Cmd->TransferDirection == SdTransferDirectionRead) {
+      if (WtmkThreshold > USDHC_WTMK_RD_WML_MAX_VAL) {
+        WtmkThreshold = USDHC_WTMK_RD_WML_MAX_VAL;
+      }
+      WtmkLvl.Fields.RD_WML = WtmkThreshold;
+    } else {
+      if (WtmkThreshold > USDHC_WTMK_WR_WML_MAX_VAL) {
+        WtmkThreshold = USDHC_WTMK_WR_WML_MAX_VAL;
+      }
+      WtmkLvl.Fields.WR_WML = WtmkThreshold;
+    }
+
+    MmioWrite32 ((UINTN)&Reg->WTMK_LVL, WtmkLvl.AsUint32);
+  }
+
+  // Set CMD parameters
+  CmdXfrTyp.AsUint32 = 0;
+  CmdXfrTyp.Fields.CMDINX = Cmd->Index;
+
+  switch (Cmd->ResponseType) {
+  case SdResponseTypeNone:
+    break;
+
+  case SdResponseTypeR1:
+  case SdResponseTypeR5:
+  case SdResponseTypeR6:
+    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_48;
+    CmdXfrTyp.Fields.CICEN = 1;
+    CmdXfrTyp.Fields.CCCEN = 1;
+    break;
+
+  case SdResponseTypeR1B:
+  case SdResponseTypeR5B:
+    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_48_CHK_BSY;
+    CmdXfrTyp.Fields.CICEN = 1;
+    CmdXfrTyp.Fields.CCCEN = 1;
+    break;
+
+  case SdResponseTypeR2:
+    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_136;
+    CmdXfrTyp.Fields.CCCEN = 1;
+    break;
+
+  case SdResponseTypeR3:
+  case SdResponseTypeR4:
+    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_48;
+    break;
+
+  default:
+    LOG_ASSERT ("SdhcSendCommand(): Invalid response type");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Cmd->Type == SdCommandTypeAbort) {
+    CmdXfrTyp.Fields.CMDTYP = USDHC_CMD_XFR_TYP_CMDTYP_ABORT;
+  }
+
+  if (XfrInfo) {
+    CmdXfrTyp.Fields.DPSEL = 1;
+  }
+
+  // Send command and wait for response
+  MmioWrite32 ((UINTN)&Reg->CMD_ARG, Argument);
+  MmioWrite32 ((UINTN)&Reg->CMD_XFR_TYP, CmdXfrTyp.AsUint32);
+
+  Status = WaitForCmdResponse (SdhcCtx);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("WaitForCmdResponse() failed. %r", Status);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcReceiveResponse (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN CONST SD_COMMAND *Cmd,
+  OUT UINT32 *Buffer
+  )
+{
+
+  USDHC_REGISTERS *Reg;
+  USDHC_PRIVATE_CONTEXT *SdhcCtx;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+
+  if (Buffer == NULL) {
+    LOG_ERROR ("Input Buffer is NULL");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Reg = SdhcCtx->RegistersBase;
+
+  switch (Cmd->ResponseType) {
+  case SdResponseTypeNone:
+    break;
+  case SdResponseTypeR1:
+  case SdResponseTypeR1B:
+  case SdResponseTypeR3:
+  case SdResponseTypeR4:
+  case SdResponseTypeR5:
+  case SdResponseTypeR5B:
+  case SdResponseTypeR6:
+    Buffer[0] = MmioRead32 ((UINTN)&Reg->CMD_RSP0);
+    LOG_TRACE (
+      "SdhcReceiveResponse(Type: %x), Buffer[0]: %08x",
+      Cmd->ResponseType,
+      Buffer[0]);
+    break;
+  case SdResponseTypeR2:
+    Buffer[0] = MmioRead32 ((UINTN)&Reg->CMD_RSP0);
+    Buffer[1] = MmioRead32 ((UINTN)&Reg->CMD_RSP1);
+    Buffer[2] = MmioRead32 ((UINTN)&Reg->CMD_RSP2);
+    Buffer[3] = MmioRead32 ((UINTN)&Reg->CMD_RSP3);
+
+    LOG_TRACE (
+      "SdhcReceiveResponse(Type: %x), Buffer[0-3]: %08x, %08x, %08x, %08x",
+      Cmd->ResponseType,
+      Buffer[0],
+      Buffer[1],
+      Buffer[2],
+      Buffer[3]);
+    break;
+  default:
+    LOG_ASSERT ("SdhcReceiveResponse(): Invalid response type");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcReadBlockData (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN UINTN LengthInBytes,
+  OUT UINT32 *Buffer
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  UINT32                  FifoWords;
+  UINTN                   NumWords;
+  EFI_STATUS              Status;
+  UINTN                   WordIdx;
+  USDHC_WTMK_LVL_REG      WtmkLvl;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+
+  LOG_TRACE (
+    "SdhcReadBlockData(LengthInBytes: 0x%x, Buffer: 0x%x)",
+    LengthInBytes,
+    Buffer);
+
+  ASSERT (Buffer != NULL);
+  ASSERT (LengthInBytes % sizeof (UINT32) == 0);
+
+  WordIdx = 0;
+  NumWords = LengthInBytes / sizeof (UINT32);
+  Reg = SdhcCtx->RegistersBase;
+  WtmkLvl.AsUint32 = MmioRead32 ((UINTN)&Reg->WTMK_LVL);
+
+  ASSERT (WtmkLvl.Fields.RD_WML > 0);
+
+  while (WordIdx < NumWords) {
+    Status = WaitForReadFifo (SdhcCtx);
+    if (EFI_ERROR (Status)) {
+      LOG_ERROR (
+        "WaitForReadFifo() failed at Word%d. %r",
+        (UINT32)WordIdx,
+        Status);
+      return Status;
+    }
+
+    FifoWords = WtmkLvl.Fields.RD_WML;
+    while (WordIdx < NumWords && FifoWords--) {
+      Buffer[WordIdx] = MmioRead32 ((UINTN)&Reg->DATA_BUFF_ACC_PORT);
+      ++WordIdx;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcWriteBlockData (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN UINTN LengthInBytes,
+  IN CONST UINT32 *Buffer
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  USDHC_INT_STATUS_REG    IntStatus;
+  UINTN                   NumBlocks;
+  USDHC_PRES_STATE_REG    PresState;
+  UINTN                   RemainingWords;
+  INT32                   Retry;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+
+  LOG_TRACE (
+    "SdhcWriteBlockData(LengthInBytes: 0x%x, Buffer: 0x%x)",
+    LengthInBytes,
+    Buffer);
+
+  ASSERT (Buffer != NULL);
+  ASSERT (LengthInBytes % USDHC_BLOCK_LENGTH_BYTES == 0);
+
+  CONST UINTN BlockWordCount = USDHC_BLOCK_LENGTH_BYTES / sizeof (UINT32);
+  NumBlocks = LengthInBytes / USDHC_BLOCK_LENGTH_BYTES;
+  Reg = SdhcCtx->RegistersBase;
+  Retry = 100000;
+
+  while (NumBlocks > 0) {
+    RemainingWords = BlockWordCount;
+    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
+    while (!PresState.Fields.BWEN && --Retry);
+    if (Retry <= 0) {
+      LOG_ERROR ("Timeout waiting for FIFO PRES_STATE.BWEN flag");
+      return EFI_TIMEOUT;
+    }
+
+    while (RemainingWords > 0 && !IntStatus.Fields.TC) {
+      MicroSecondDelay (100);
+      IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
+      MmioWrite32 ((UINTN)&Reg->DATA_BUFF_ACC_PORT, *Buffer);
+      Buffer++;
+      RemainingWords--;
+    }
+    NumBlocks--;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SdhcSoftwareReset (
+  IN EFI_SDHC_PROTOCOL *This,
+  IN SDHC_RESET_TYPE ResetType
+  )
+{
+  USDHC_REGISTERS         *Reg;
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  USDHC_PROT_CTRL_REG     ProtCtrl;
+  UINT32                  Retry;
+  EFI_STATUS              Status;
+  USDHC_SYS_CTRL_REG      SysCtrl;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+  Reg = SdhcCtx->RegistersBase;
+
+  if (ResetType == SdhcResetTypeAll) {
+    LOG_TRACE ("SdhcSoftwareReset(ALL)");
+    // Software reset for ALL
+    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    SysCtrl.Fields.RSTA = 1;
+    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
+    Retry = USDHC_POLL_RETRY_COUNT;
+
+    // Wait for reset to complete
+    while (SysCtrl.Fields.RSTA && Retry) {
+      --Retry;
+      gBS->Stall (USDHC_POLL_WAIT_US);
+      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    }
+
+    if (SysCtrl.Fields.RSTA) {
+      ASSERT (!Retry);
+      LOG_ERROR ("Time-out waiting on RSTA for self-clear");
+      return EFI_TIMEOUT;
+    }
+
+    // Disconnect interrupt signals between SDHC and GIC
+    MmioWrite32 ((UINTN)&Reg->INT_SIGNAL_EN, 0);
+
+    // Clear and Enable all interrupts
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS_EN, (UINT32)~0);
+
+    LOG_TRACE ("Waiting for CMD and DATA lines");
+
+    // Wait for CMD and DATA lines to become available
+    Status = WaitForCmdAndOrDataLine (SdhcCtx, NULL);
+    if (Status != EFI_SUCCESS) {
+      LOG_ERROR ("SdhcWaitForCmdAndDataLine() failed. %r", Status);
+      return Status;
+    }
+
+    // Send 80 clock ticks to power-up the card
+    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    SysCtrl.Fields.INITA = 1;
+    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
+    Retry = USDHC_POLL_RETRY_COUNT;
+
+    // Wait for the 80 clock ticks to complete
+    while (SysCtrl.Fields.INITA && Retry) {
+      --Retry;
+      gBS->Stall (USDHC_POLL_WAIT_US);
+      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    }
+
+    if (SysCtrl.Fields.INITA) {
+      ASSERT (!Retry);
+      LOG_ERROR ("Time-out waiting on INITA for self-clear");
+      return EFI_TIMEOUT;
+    }
+
+    LOG_TRACE ("Card power-up complete");
+
+    // Set max data-timout counter value
+    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    SysCtrl.Fields.DTOCV = 0xF;
+    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
+
+    // Reset Mixer Control
+    MmioWrite32 ((UINTN)&Reg->MIX_CTRL, 0);
+
+    ProtCtrl.AsUint32 = 0;
+    ProtCtrl.Fields.EMODE = USDHC_PROT_CTRL_EMODE_LITTLE_ENDIAN;
+    ProtCtrl.Fields.LCTL = 1;
+    MmioWrite32 ((UINTN)&Reg->PROT_CTRL, ProtCtrl.AsUint32);
+
+    LOG_TRACE ("Reset ALL complete");
+
+  } else if (ResetType == SdhcResetTypeCmd) {
+    LOG_TRACE ("SdhcSoftwareReset(CMD)");
+    //
+    // Software reset for CMD
+    //
+    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    SysCtrl.Fields.RSTC = 1;
+    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
+    Retry = USDHC_POLL_RETRY_COUNT;
+
+    //
+    // Wait for reset to complete
+    //
+    while (SysCtrl.Fields.RSTC && Retry) {
+      --Retry;
+      gBS->Stall (USDHC_POLL_WAIT_US);
+      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    }
+
+    if (SysCtrl.Fields.RSTC) {
+      ASSERT (!Retry);
+      LOG_ERROR ("Time-out waiting on RSTC for self-clear");
+      return EFI_TIMEOUT;
+    }
+
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
+
+    LOG_TRACE ("Reset CMD complete");
+
+  } else if (ResetType == SdhcResetTypeData) {
+    LOG_TRACE ("SdhcSoftwareReset(DAT)");
+    // Software reset for DAT
+    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    SysCtrl.Fields.RSTD = 1;
+    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
+    Retry = USDHC_POLL_RETRY_COUNT;
+
+    // Wait for reset to complete
+    while (SysCtrl.Fields.RSTD && Retry) {
+      --Retry;
+      gBS->Stall (USDHC_POLL_WAIT_US);
+      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
+    }
+
+    if (SysCtrl.Fields.RSTD) {
+      ASSERT (!Retry);
+      LOG_ERROR ("Time-out waiting on RSTD for self-clear");
+      return EFI_TIMEOUT;
+    }
+
+    MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
+
+    LOG_TRACE ("Reset DAT complete");
+
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+VOID
+SdhcCleanup (
+  IN EFI_SDHC_PROTOCOL *This
+  )
+{
+  if (This->PrivateContext != NULL) {
+    FreePool (This->PrivateContext);
+    This->PrivateContext = NULL;
+  }
+
+  FreePool (This);
+}
+
+VOID
+SdhcGetCapabilities (
+  IN EFI_SDHC_PROTOCOL *This,
+  OUT SDHC_CAPABILITIES *Capabilities
+  )
+{
+  USDHC_REGISTERS           *Reg;
+  USDHC_PRIVATE_CONTEXT     *SdhcCtx;
+  USDHC_HOST_CTRL_CAP_REG   Caps;
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
+  Reg = SdhcCtx->RegistersBase;
+  Caps.AsUint32 = MmioRead32 ((UINTN)&Reg->HOST_CTRL_CAP);
+  Capabilities->MaximumBlockSize = (UINT32) (512 << Caps.Fields.MBL);
+  Capabilities->MaximumBlockCount = 0xFFFF;
+}
+
+static EFI_SDHC_PROTOCOL mSdhcProtocolTemplate = {
+  SDHC_PROTOCOL_INTERFACE_REVISION,   // Revision
+  0,                                  // DeviceId
+  NULL,                               // PrivateContext
+  SdhcGetCapabilities,
+  SdhcSoftwareReset,
+  SdhcSetClock,
+  SdhcSetBusWidth,
+  SdhcIsCardPresent,
+  SdhcIsReadOnly,
+  SdhcSendCommand,
+  SdhcReceiveResponse,
+  SdhcReadBlockData,
+  SdhcWriteBlockData,
+  SdhcCleanup
+};
+
+EFI_STATUS
+SdhcDeviceRegister (
+  IN EFI_HANDLE ImageHandle,
+  IN UINT32 SdhcId,
+  IN VOID *RegistersBase,
+  IN USDHC_SIGNAL_SOURCE CardDetectSignal,
+  IN USDHC_SIGNAL_SOURCE WriteProtectSignal
+  )
+{
+  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
+  EFI_SDHC_PROTOCOL       *SdhcProtocol;
+  EFI_STATUS              Status;
+
+  SdhcProtocol = NULL;
+  SdhcCtx = NULL;
+
+  if (ImageHandle == NULL ||
+      RegistersBase == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  // Allocate per-device SDHC protocol and private context storage
+  SdhcProtocol = AllocateCopyPool (sizeof (EFI_SDHC_PROTOCOL),
+                                   &mSdhcProtocolTemplate);
+  if (SdhcProtocol == NULL) {
+    Status =  EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  SdhcProtocol->SdhcId = SdhcId;
+  SdhcProtocol->PrivateContext = AllocateZeroPool (sizeof (
+                                   USDHC_PRIVATE_CONTEXT));
+  if (SdhcProtocol->PrivateContext == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)SdhcProtocol->PrivateContext;
+  SdhcCtx->SdhcId = SdhcId;
+  SdhcCtx->RegistersBase = (USDHC_REGISTERS *)RegistersBase;
+  SdhcCtx->CardDetectSignal = CardDetectSignal;
+  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal)) {
+    SdhcCtx->CardDetectGpioPin.IoNumber = PCD_GPIO_PIN_IO_NUMBER ((
+                                            UINT16)CardDetectSignal);
+    SdhcCtx->CardDetectGpioPin.Bank = PCD_GPIO_PIN_BANK (CardDetectSignal);
+  }
+
+  SdhcCtx->WriteProtectSignal = WriteProtectSignal;
+  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal)) {
+    SdhcCtx->WriteProtectGpioPin.IoNumber = PCD_GPIO_PIN_IO_NUMBER ((
+        UINT16)WriteProtectSignal);
+    SdhcCtx->WriteProtectGpioPin.Bank = PCD_GPIO_PIN_BANK (WriteProtectSignal);
+  }
+
+  LOG_INFO (
+    "Initializing uSDHC%d @%p GPIO CD?:%d WP?:%d",
+    SdhcId,
+    RegistersBase,
+    (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal) ? 1 : 0),
+    (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal) ? 1 : 0));
+
+  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal)) {
+    LOG_INFO (
+      "Using GPIO%d_IO%d for CardDetect",
+      SdhcCtx->CardDetectGpioPin.Bank,
+      SdhcCtx->CardDetectGpioPin.IoNumber);
+  }
+
+  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal)) {
+    LOG_INFO (
+      "Using GPIO%d_IO%d for WriteProtect",
+      SdhcCtx->WriteProtectGpioPin.Bank,
+      SdhcCtx->WriteProtectGpioPin.IoNumber);
+  }
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+             &SdhcCtx->SdhcProtocolHandle,
+             &gEfiSdhcProtocolGuid,
+             SdhcProtocol,
+             NULL);
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("InstallMultipleProtocolInterfaces failed. %r", Status);
+    goto Exit;
+  }
+
+Exit:
+  if (EFI_ERROR (Status)) {
+    LOG_ERROR ("Failed to register and initialize uSDHC%d", SdhcId);
+
+    if (SdhcProtocol != NULL && SdhcProtocol->PrivateContext != NULL) {
+      FreePool (SdhcProtocol->PrivateContext);
+      SdhcProtocol->PrivateContext = NULL;
+    }
+
+    if (SdhcProtocol != NULL) {
+      FreePool (SdhcProtocol);
+      SdhcProtocol = NULL;
+    }
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+SdhcInitialize (
+  IN EFI_HANDLE ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  UINT32      SdhcRegisteredCount;
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+  SdhcRegisteredCount = 0;
+
+  // Register uSDHC1 through uSDHC4 if their base address is non-zero
+
+  // uSDHC1
+  if (FixedPcdGet32 (PcdSdhc1Enable)) {
+    Status = SdhcDeviceRegister (
+               ImageHandle,
+               1,
+               (VOID *)FixedPcdGet32 (PcdSdhc1Base),
+               FixedPcdGet32 (PcdSdhc1CardDetectSignal),
+               FixedPcdGet32 (PcdSdhc1WriteProtectSignal));
+    if (!EFI_ERROR (Status)) {
+      ++SdhcRegisteredCount;
+    }
+  }
+
+  // uSDHC2
+  if (FixedPcdGet32 (PcdSdhc2Enable)) {
+    Status = SdhcDeviceRegister (
+               ImageHandle,
+               2,
+               (VOID *)FixedPcdGet32 (PcdSdhc2Base),
+               FixedPcdGet32 (PcdSdhc2CardDetectSignal),
+               FixedPcdGet32 (PcdSdhc2WriteProtectSignal));
+    if (!EFI_ERROR (Status)) {
+      ++SdhcRegisteredCount;
+    }
+  }
+
+  // uSDHC3
+  if (FixedPcdGet32 (PcdSdhc3Enable)) {
+    Status = SdhcDeviceRegister (
+               ImageHandle,
+               3,
+               (VOID *)FixedPcdGet32 (PcdSdhc3Base),
+               FixedPcdGet32 (PcdSdhc3CardDetectSignal),
+               FixedPcdGet32 (PcdSdhc3WriteProtectSignal));
+    if (!EFI_ERROR (Status)) {
+      ++SdhcRegisteredCount;
+    }
+  }
+
+  // uSDHC4
+  if (FixedPcdGet32 (PcdSdhc4Enable)) {
+    Status = SdhcDeviceRegister (
+               ImageHandle,
+               4,
+               (VOID *)FixedPcdGet32 (PcdSdhc4Base),
+               FixedPcdGet32 (PcdSdhc4CardDetectSignal),
+               FixedPcdGet32 (PcdSdhc4WriteProtectSignal));
+    if (!EFI_ERROR (Status)) {
+      ++SdhcRegisteredCount;
+    }
+  }
+
+  // Succeed driver loading if at least one enabled uSDHC got registered successfully
+  if ((Status != EFI_SUCCESS) && (SdhcRegisteredCount > 0)) {
+    Status = EFI_SUCCESS;
+  }
+
+  return Status;
+}
diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h
new file mode 100644
index 000000000000..e3f7fe62b0b6
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h
@@ -0,0 +1,81 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _SDHC_DXE_H_
+#define _SDHC_DXE_H_
+
+typedef struct {
+  UINT32 IoNumber;
+  IMX_GPIO_BANK Bank;
+} IMX_GPIO_PIN;
+
+#define PCD_GPIO_PIN_IO_NUMBER(X)   ((X) & 0xFF)
+#define PCD_GPIO_PIN_BANK(X)        (((X) >> 8) & 0xFF)
+
+// A special value to indicate that GPIO is not the signal source for either
+// CardDetect or WriteProtect
+typedef enum {
+  USDHC_SIGNAL_GPIO_START = 0x000,
+  USDHC_SIGNAL_GPIO_END = 0xFF00,
+  USDHC_SIGNAL_OVERRIDE_PIN_LOW = 0xFF00,
+  USDHC_SIGNAL_OVERRIDE_PIN_HIGH = 0xFF01,
+  USDHC_SIGNAL_INTERNAL_PIN = 0xFFFF
+} USDHC_SIGNAL_SOURCE;
+
+#define USDHC_IS_GPIO_SIGNAL_SOURCE(X)  \
+    (((X) >= USDHC_SIGNAL_GPIO_START) && ((X) < USDHC_SIGNAL_GPIO_END))
+
+typedef struct {
+  UINT32 SdhcId;
+  EFI_HANDLE SdhcProtocolHandle;
+  USDHC_REGISTERS *RegistersBase;
+  USDHC_SIGNAL_SOURCE CardDetectSignal;
+  USDHC_SIGNAL_SOURCE WriteProtectSignal;
+  IMX_GPIO_PIN CardDetectGpioPin;
+  IMX_GPIO_PIN WriteProtectGpioPin;
+} USDHC_PRIVATE_CONTEXT;
+
+#define LOG_FMT_HELPER(FMT, ...) \
+    "SDHC%d:" FMT "%a\n", ((SdhcCtx != NULL) ? SdhcCtx->SdhcId : -1), __VA_ARGS__
+
+#define LOG_INFO(...) \
+    DEBUG((DEBUG_INFO | DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
+
+#define LOG_TRACE(...) \
+    DEBUG((DEBUG_VERBOSE | DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
+
+#define LOG_ERROR(...) \
+    DEBUG((DEBUG_ERROR | DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
+
+#define LOG_ASSERT(TXT) \
+    ASSERT(!"Sdhc: " TXT "\n")
+
+// uSDHC read/write FIFO is 128x32-bit
+#define USDHC_FIFO_MAX_WORD_COUNT       128
+
+// Max block count allowed in a single transfer
+#define USDHC_MAX_BLOCK_COUNT           0xFFFF
+
+// Number of register maximum polls
+#define USDHC_POLL_RETRY_COUNT          100000
+
+// Waits between each registry poll
+#define USDHC_POLL_WAIT_US              20
+
+// uSDHC input clock. Ideally, should query it from clock manager
+#define USDHC_BASE_CLOCK_FREQ_HZ        198000000
+
+#define USDHC_BLOCK_LENGTH_BYTES               512
+
+#endif // _SDHC_DXE_H_
diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
new file mode 100644
index 000000000000..5f29b7a7b7c8
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
@@ -0,0 +1,70 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = SdhcDxe
+  FILE_GUID                      = A9945BAB-78C9-43C9-9175-F576CA189870
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SdhcInitialize
+
+[Sources.common]
+  SdhcDxe.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/Microsoft/MsPkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  iMXIoMuxLib
+  IoLib
+  MemoryAllocationLib
+  PcdLib
+  UefiLib
+  UefiDriverEntryPoint
+
+[Guids]
+
+[Protocols]
+  gEfiSdhcProtocolGuid
+
+[Pcd]
+  giMXPlatformTokenSpaceGuid.PcdSdhc1Base
+  giMXPlatformTokenSpaceGuid.PcdSdhc1CardDetectSignal
+  giMXPlatformTokenSpaceGuid.PcdSdhc1Enable
+  giMXPlatformTokenSpaceGuid.PcdSdhc1WriteProtectSignal
+
+  giMXPlatformTokenSpaceGuid.PcdSdhc2Base
+  giMXPlatformTokenSpaceGuid.PcdSdhc2CardDetectSignal
+  giMXPlatformTokenSpaceGuid.PcdSdhc2Enable
+  giMXPlatformTokenSpaceGuid.PcdSdhc2WriteProtectSignal
+
+  giMXPlatformTokenSpaceGuid.PcdSdhc3Base
+  giMXPlatformTokenSpaceGuid.PcdSdhc3CardDetectSignal
+  giMXPlatformTokenSpaceGuid.PcdSdhc3Enable
+  giMXPlatformTokenSpaceGuid.PcdSdhc3WriteProtectSignal
+
+  giMXPlatformTokenSpaceGuid.PcdSdhc4Base
+  giMXPlatformTokenSpaceGuid.PcdSdhc4CardDetectSignal
+  giMXPlatformTokenSpaceGuid.PcdSdhc4Enable
+  giMXPlatformTokenSpaceGuid.PcdSdhc4WriteProtectSignal
+
+[FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
+
+[depex]
+  TRUE
diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
new file mode 100644
index 000000000000..df57159d9d41
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
@@ -0,0 +1,277 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __IMX_USDHC_H__
+#define __IMX_USDHC_H__
+
+//
+// uSDHCx Registers Layout
+//
+typedef struct {
+  UINT32 DS_ADDR;
+  UINT32 BLK_ATT;
+  UINT32 CMD_ARG;
+  UINT32 CMD_XFR_TYP;
+  UINT32 CMD_RSP0;
+  UINT32 CMD_RSP1;
+  UINT32 CMD_RSP2;
+  UINT32 CMD_RSP3;
+  UINT32 DATA_BUFF_ACC_PORT;
+  UINT32 PRES_STATE;
+  UINT32 PROT_CTRL;
+  UINT32 SYS_CTRL;
+  UINT32 INT_STATUS;
+  UINT32 INT_STATUS_EN;
+  UINT32 INT_SIGNAL_EN;
+  UINT32 AUTOCMD12_ERR_STATUS;
+  UINT32 HOST_CTRL_CAP;
+  UINT32 WTMK_LVL;
+  UINT32 MIX_CTRL;
+  UINT32 _pad0;
+  UINT32 FORCE_EVENT;
+  UINT32 ADMA_ERR_STATUS;
+  UINT32 ADMA_SYS_ADDR;
+  UINT32 _pad1;
+  UINT32 DLL_CTRL;
+  UINT32 DLL_STATUS;
+  UINT32 CLK_TUNE_CTRL_STATUS;
+  UINT32 _pad2[21];
+  UINT32 VEND_SPEC;
+  UINT32 MMC_BOOT;
+  UINT32 VEND_SPEC2;
+} USDHC_REGISTERS;
+
+//
+// Block Attributes uSDHCx_BLK_ATT fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 BLKSIZE    : 13; // 0:12
+    UINT32 _reserved0 : 3;  // 13:15
+    UINT32 BLKCNT     : 16; // 16:31
+  } Fields;
+} USDHC_BLK_ATT_REG;
+
+//
+// Command Transfer Type uSDHCx_CMD_XFR_TYP fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 _reserved0   : 16; // 0:15
+    UINT32 RSPTYP       : 2; // 16:17
+    UINT32 _reserved1   : 1; // 18
+    UINT32 CCCEN        : 1; // 19
+    UINT32 CICEN        : 1; // 20
+    UINT32 DPSEL        : 1; // 21
+    UINT32 CMDTYP       : 2; // 22:23
+    UINT32 CMDINX       : 6; // 24:29
+    UINT32 _reserved2   : 2; // 30:31
+  } Fields;
+} USDHC_CMD_XFR_TYP_REG;
+
+#define USDHC_CMD_XFR_TYP_RSPTYP_NO_RSP          0
+#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_136         1
+#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_48          2
+#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_48_CHK_BSY  3
+#define USDHC_CMD_XFR_TYP_CMDTYP_ABORT           3
+
+//
+// System Control uSDHCx_SYS_CTRL fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 _reserved0   : 4; // 0:3
+    UINT32 DVS          : 4; // 4:7
+    UINT32 SDCLKFS      : 8; // 8:15
+    UINT32 DTOCV        : 4; // 16:19
+    UINT32 _reserved1   : 3; // 20:22
+    UINT32 IPP_RST_N    : 1; // 23
+    UINT32 RSTA         : 1; // 24
+    UINT32 RSTC         : 1; // 25
+    UINT32 RSTD         : 1; // 26
+    UINT32 INITA        : 1; // 27
+    UINT32 _reserved2   : 4; // 28-31
+  } Fields;
+} USDHC_SYS_CTRL_REG;
+
+//
+// Host Controller Capabilities Register uSDHCx_HOST_CTRL_CAP fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 _reserved0       : 16; // 0:15
+    UINT32 MBL              : 3; // 16:18
+    UINT32 _reserved1       : 1; // 19
+    UINT32 ADMAS            : 1; // 20
+    UINT32 HSS              : 1; // 21
+    UINT32 DMAS             : 1; // 22
+    UINT32 SRS              : 1; // 23
+    UINT32 VS33             : 1; // 24
+    UINT32 VS30             : 1; // 25
+    UINT32 VS18             : 1; // 26
+    UINT32 _reserved2       : 5; // 27:31
+  } Fields;
+} USDHC_HOST_CTRL_CAP_REG;
+
+//
+// Watermark Level uSDHCx_WTMK_LVL
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 RD_WML           : 8; // 0:7
+    UINT32 RD_BRST_LEN      : 5; // 8:12
+    UINT32 _reserved0       : 3; // 13:15
+    UINT32 WR_WML           : 8; // 16:23
+    UINT32 WR_BRST_LEN      : 5; // 24:28
+    UINT32 _reserved1       : 3; // 29:31
+  } Fields;
+} USDHC_WTMK_LVL_REG;
+
+#define USDHC_WTMK_RD_WML_MAX_VAL   0x10
+#define USDHC_WTMK_WR_WML_MAX_VAL   0x80
+
+//
+// Mixer Control uSDHCx_MIX_CTRL fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 DMAEN          : 1; // 0
+    UINT32 BCEN           : 1; // 1
+    UINT32 AC12EN         : 1; // 2
+    UINT32 DDR_EN         : 1; // 3
+    UINT32 DTDSEL         : 1; // 4
+    UINT32 MSBSEL         : 1; // 5
+    UINT32 NIBBLE_POS     : 1; // 6
+    UINT32 AC23EN         : 1; // 7
+    UINT32 _reserved0     : 14; // 8:21
+    UINT32 EXE_TUNE       : 1; // 22
+    UINT32 SMP_CLK_SEL    : 1; // 23
+    UINT32 AUTO_TUNE_EN   : 1; //24
+    UINT32 FBCLK_SEL      : 1; // 25
+    UINT32 _reserved1     : 6; // 26-31
+  } Fields;
+} USDHC_MIX_CTRL_REG;
+
+//
+// Present State uSDHCx_PRES_STATE fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CIHB         : 1; // 0
+    UINT32 CDIHB        : 1; // 1
+    UINT32 DLA          : 1; // 2
+    UINT32 SDSTB        : 1; // 3
+    UINT32 IPGOFF       : 1; // 4
+    UINT32 HCKOFF       : 1; // 5
+    UINT32 PEROFF       : 1; // 6
+    UINT32 SDOFF        : 1; // 7
+    UINT32 WTA          : 1; // 8
+    UINT32 RTA          : 1; // 9
+    UINT32 BWEN         : 1; // 10
+    UINT32 BREN         : 1; // 11
+    UINT32 PTR          : 1; // 12
+    UINT32 _reserved0   : 3; // 13:15
+    UINT32 CINST        : 1; // 16
+    UINT32 _reserved1   : 1; // 17
+    UINT32 CDPL         : 1; // 18
+    UINT32 WPSPL        : 1; // 19
+    UINT32 _reserved2   : 3; // 20:22
+    UINT32 CLSL         : 1; // 23
+    UINT32 DLSL         : 8; // 24:31
+  } Fields;
+} USDHC_PRES_STATE_REG;
+
+//
+// Present State uSDHCx_PROT_CTRL fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 LCTL             : 1; // 0
+    UINT32 DTW              : 2; // 1:2
+    UINT32 D3CD             : 1; // 3
+    UINT32 EMODE            : 2; // 4:5
+    UINT32 CDTL             : 1; // 6
+    UINT32 CDSS             : 1; // 7
+    UINT32 DMASEL           : 2; // 8:9
+    UINT32 _reserved0       : 6; // 10:15
+    UINT32 SABGREQ          : 1; // 16
+    UINT32 CREQ             : 1; // 17
+    UINT32 RWCTL            : 1; // 18
+    UINT32 IABG             : 1; // 19
+    UINT32 RD_DONE_NO_8CLK  : 1; // 20
+    UINT32 _reserved1       : 3; // 21:23
+    UINT32 WECINT           : 1; // 24
+    UINT32 WECINS           : 1; // 25
+    UINT32 WECRM            : 1; // 26
+    UINT32 BURST_LEN_EN     : 3; // 27:29
+    UINT32 NON_EXACT_BLK_RD : 1; // 30
+    UINT32 _reserved2       : 1; // 31
+  } Fields;
+} USDHC_PROT_CTRL_REG;
+
+#define USDHC_PROT_CTRL_DTW_1BIT             0x0
+#define USDHC_PROT_CTRL_DTW_4BIT             0x1
+#define USDHC_PROT_CTRL_DTW_8BIT             0x2
+#define USDHC_PROT_CTRL_EMODE_LITTLE_ENDIAN  0x2
+
+//
+// Interrupt Status uSDHCx_INT_STATUS fields
+//
+typedef union {
+  UINT32 AsUint32;
+  struct {
+    UINT32 CC           : 1; // 0
+    UINT32 TC           : 1; // 1
+    UINT32 BGE          : 1; // 2
+    UINT32 DINT         : 1; // 3
+    UINT32 BWR          : 1; // 4
+    UINT32 BRR          : 1; // 5
+    UINT32 CINS         : 1; // 6
+    UINT32 CRM          : 1; // 7
+    UINT32 CINT         : 1; // 8
+    UINT32 _reserved0   : 3; // 9:11
+    UINT32 RTE          : 1; // 12
+    UINT32 _reserved1   : 1; // 13
+    UINT32 TP           : 1; // 14
+    UINT32 _reserved2   : 1; // 15
+    UINT32 CTOE         : 1; // 16
+    UINT32 CCE          : 1; // 17
+    UINT32 CEBE         : 1; // 18
+    UINT32 CIE          : 1; // 19
+    UINT32 DTOE         : 1; // 20
+    UINT32 DCE          : 1; // 21
+    UINT32 DEBE         : 1; // 22
+    UINT32 _reserved3   : 1; // 23
+    UINT32 AC12E        : 1; // 24
+    UINT32 _reserved4   : 1; // 25
+    UINT32 TNE          : 1; // 26
+    UINT32 _reserved5   : 1; // 27
+    UINT32 DMAE         : 1; // 28
+    UINT32 _reserved6   : 3; // 29:31
+  } Fields;
+} USDHC_INT_STATUS_REG;
+
+#define USDHC_INT_STATUS_CMD_ERROR   (BIT16 | BIT17 | BIT18 | BIT19)
+#define USDHC_INT_STATUS_DATA_ERROR  (BIT20 | BIT21 | BIT22)
+#define USDHC_INT_STATUS_ERROR       (USDHC_INT_STATUS_CMD_ERROR | USDHC_INT_STATUS_DATA_ERROR)
+
+#endif // __IMX_USDHC_H__
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (12 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 13/27] Silicon/NXP: Add support for iMX SDHC Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-11-08 18:14   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 15/27] Silicon/NXP: Add i.MX6 GPT Timer library Chris Co
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds the definitions for the NXP i.MX6 General Purpose Timer
and the Enhanced Periodic Interrupt Timer modules.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Include/common_epit.h | 118 +++++++++
 Silicon/NXP/iMX6Pkg/Include/common_gpt.h  | 271 ++++++++++++++++++++
 2 files changed, 389 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Include/common_epit.h b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
new file mode 100644
index 000000000000..485d6ccbc51e
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
@@ -0,0 +1,118 @@
+/** @file
+*
+*  Provides definitions for the EPIT (Enhanced Periodic Interrupt Timer)
+*  module that are common to Freescale SoCs.
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2004-2010, Freescale Semiconductor, Inc. All Rights Reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __COMMON_EPIT_H
+#define __COMMON_EPIT_H
+
+typedef struct {
+  UINT32 CR;
+  UINT32 SR;
+  UINT32 LR;
+  UINT32 CMPR;
+  UINT32 CNT;
+} CSP_EPIT_REG, *PCSP_EPIT_REG;
+
+#define EPIT_CR_OFFSET          0x0000
+#define EPIT_SR_OFFSET          0x0004
+#define EPIT_LR_OFFSET          0x0008
+#define EPIT_CMPR_OFFSET        0x000C
+#define EPIT_CNR_OFFSET         0x0010
+
+#define EPIT_CR_EN_LSH          0
+#define EPIT_CR_ENMOD_LSH       1
+#define EPIT_CR_OCIEN_LSH       2
+#define EPIT_CR_RLD_LSH         3
+#define EPIT_CR_PRESCALAR_LSH   4
+#define EPIT_CR_SWR_LSH         16
+#define EPIT_CR_IOVW_LSH        17
+#define EPIT_CR_DBGEN_LSH       18
+#define EPIT_CR_WAITEN_LSH      19
+#define EPIT_CR_DOZEN_LSH       20
+#define EPIT_CR_STOPEN_LSH      21
+#define EPIT_CR_OM_LSH          22
+#define EPIT_CR_CLKSRC_LSH      24
+
+#define EPIT_SR_OCIF_LSH        0
+#define EPIT_LR_LOAD_LSH        0
+#define EPIT_CMPR_COMPARE_LSH   0
+#define EPIT_CNT_COUNT_LSH      0
+
+#define EPIT_CR_EN_WID          1
+#define EPIT_CR_ENMOD_WID       1
+#define EPIT_CR_OCIEN_WID       2
+#define EPIT_CR_RLD_WID         1
+#define EPIT_CR_PRESCALAR_WID   12
+#define EPIT_CR_SWR_WID         1
+#define EPIT_CR_IOVW_WID        1
+#define EPIT_CR_DBGEN_WID       1
+#define EPIT_CR_WAITEN_WID      1
+#define EPIT_CR_DOZEN_WID       1
+#define EPIT_CR_STOPEN_WID      1
+#define EPIT_CR_OM_WID          2
+#define EPIT_CR_CLKSRC_WID      2
+
+#define EPIT_SR_OCIF_WID        1
+#define EPIT_LR_LOAD_WID        32
+#define EPIT_CMPR_COMPARE_WID   32
+#define EPIT_CNT_COUNT_WID      32
+
+// CR
+#define EPIT_CR_EN_DISABLE          0
+#define EPIT_CR_EN_ENABLE           1
+
+#define EPIT_CR_ENMOD_RESUME        0
+#define EPIT_CR_ENMOD_LOAD          1
+
+#define EPIT_CR_OCIEN_DISABLE       0
+#define EPIT_CR_OCIEN_ENABLE        1
+
+#define EPIT_CR_RLD_ROLLOVER        0
+#define EPIT_CR_RLD_RELOAD          1
+
+#define EPIT_CR_SWR_NORESET         0
+#define EPIT_CR_SWR_RESET           1
+
+#define EPIT_CR_IOVW_NOOVR          0
+#define EPIT_CR_IOVW_OVR            1
+
+#define EPIT_CR_DBGEN_INACTIVE      0
+#define EPIT_CR_DBGEN_ACTIVE        1
+
+#define EPIT_CR_WAITEN_DISABLE      0
+#define EPIT_CR_WAITEN_ENABLE       1
+
+#define EPIT_CR_DOZEN_DISABLE       0
+#define EPIT_CR_DOZEN_ENABLE        1
+
+#define EPIT_CR_STOPEN_DISABLE      0
+#define EPIT_CR_STOPEN_ENABLE       1
+
+#define EPIT_CR_OM_DICONNECT        0
+#define EPIT_CR_OM_TOGGLE           1
+#define EPIT_CR_OM_CLEAR            2
+#define EPIT_CR_OM_SET              3
+
+#define EPIT_CR_CLKSRC_OFF          0
+#define EPIT_CR_CLKSRC_IPGCLK       1
+#define EPIT_CR_CLKSRC_HIGHFREQ     2   // High freq is sourcing from PERCLK
+#define EPIT_CR_CLKSRC_CKIL         3
+
+// CNT
+#define EPIT_CNT_COUNT_MAX          0xFFFFFFFF
+
+#endif // __COMMON_EPIT_H
diff --git a/Silicon/NXP/iMX6Pkg/Include/common_gpt.h b/Silicon/NXP/iMX6Pkg/Include/common_gpt.h
new file mode 100644
index 000000000000..7fdfc25d819f
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/common_gpt.h
@@ -0,0 +1,271 @@
+/** @file
+*
+*  Provides definitions for the GPT (General Purpose Timer) module
+*  that are common to Freescale SoCs.
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright (c) 2004-2010, Freescale Semiconductor, Inc. All Rights Reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __COMMON_GPT_H
+#define __COMMON_GPT_H
+
+typedef struct {
+  UINT32 CR;
+  UINT32 PR;
+  UINT32 SR;
+  UINT32 IR;
+  UINT32 OCR1;
+  UINT32 OCR2;
+  UINT32 OCR3;
+  UINT32 ICR1;
+  UINT32 ICR2;
+  UINT32 CNT;
+} CSP_GPT_REGS, *PCSP_GPT_REGS;
+
+#define GPT_CR_OFFSET          0x0000
+#define GPT_PR_OFFSET          0x0004
+#define GPT_SR_OFFSET          0x0008
+#define GPT_IR_OFFSET          0x000C
+#define GPT_OCR1_OFFSET        0x0010
+#define GPT_OCR2_OFFSET        0x0014
+#define GPT_OCR3_OFFSET        0x0018
+#define GPT_ICR1_OFFSET        0x001C
+#define GPT_ICR2_OFFSET        0x0020
+#define GPT_CNT_OFFSET         0x0024
+
+
+#define GPT_CR_EN_LSH          0
+#define GPT_CR_ENMOD_LSH       1
+#define GPT_CR_DBGEN_LSH       2
+#define GPT_CR_WAITEN_LSH      3
+#define GPT_CR_STOPEN_LSH      5
+#define GPT_CR_CLKSRC_LSH      6
+#define GPT_CR_FRR_LSH         9
+#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
+#define GPT_CR_EN_24M_LSH      10
+#endif
+#define GPT_CR_SWR_LSH         15
+#define GPT_CR_IM1_LSH         16
+#define GPT_CR_IM2_LSH         18
+#define GPT_CR_OM1_LSH         20
+#define GPT_CR_OM2_LSH         23
+#define GPT_CR_OM3_LSH         26
+#define GPT_CR_FO1_LSH         29
+#define GPT_CR_FO2_LSH         30
+#define GPT_CR_FO3_LSH         31
+
+#define GPT_PR_PRESCALER_LSH   0
+
+#define GPT_SR_OF1_LSH         0
+#define GPT_SR_OF2_LSH         1
+#define GPT_SR_OF3_LSH         2
+#define GPT_SR_IF1_LSH         3
+#define GPT_SR_IF2_LSH         4
+#define GPT_SR_ROV_LSH         5
+
+#define GPT_IR_OF1IE_LSH       0
+#define GPT_IR_OF2IE_LSH       1
+#define GPT_IR_OF3IE_LSH       2
+#define GPT_IR_IF1IE_LSH       3
+#define GPT_IR_IF2IE_LSH       4
+#define GPT_IR_ROVIE_LSH       5
+
+#define GPT_OCR1_COMP_LSH      0
+#define GPT_OCR2_COMP_LSH      0
+#define GPT_OCR3_COMP_LSH      0
+#define GPT_ICR1_CAPT_LSH      0
+#define GPT_ICR2_CAPT_LSH      0
+#define GPT_CNT_COUNT_LSH      0
+
+#define GPT_CR_EN_WID          1
+#define GPT_CR_ENMOD_WID       1
+#define GPT_CR_DBGEN_WID       1
+#define GPT_CR_WAITEN_WID      1
+#define GPT_CR_STOPEN_WID      1
+#define GPT_CR_CLKSRC_WID      3
+#define GPT_CR_FRR_WID         1
+#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
+#define GPT_CR_EN_24M_WID      1
+#endif
+#define GPT_CR_SWR_WID         1
+#define GPT_CR_IM1_WID         2
+#define GPT_CR_IM2_WID         2
+#define GPT_CR_OM1_WID         3
+#define GPT_CR_OM2_WID         3
+#define GPT_CR_OM3_WID         3
+#define GPT_CR_FO1_WID         1
+#define GPT_CR_FO2_WID         1
+#define GPT_CR_FO3_WID         1
+
+#define GPT_PR_PRESCALER_WID   12
+
+#define GPT_SR_OF1_WID         1
+#define GPT_SR_OF2_WID         1
+#define GPT_SR_OF3_WID         1
+#define GPT_SR_IF1_WID         1
+#define GPT_SR_IF2_WID         1
+#define GPT_SR_ROV_WID         1
+
+#define GPT_IR_OF1IE_WID       1
+#define GPT_IR_OF2IE_WID       1
+#define GPT_IR_OF3IE_WID       1
+#define GPT_IR_IF1IE_WID       1
+#define GPT_IR_IF2IE_WID       1
+#define GPT_IR_ROVIE_WID       1
+
+#define GPT_OCR1_COMP_WID      32
+#define GPT_OCR2_COMP_WID      32
+#define GPT_OCR3_COMP_WID      32
+#define GPT_ICR1_CAPT_WID      32
+#define GPT_ICR2_CAPT_WID      32
+#define GPT_CNT_COUNT_WID      32
+
+
+//------------------------------------------------------------------------------
+// REGISTER BIT WRITE VALUES
+//------------------------------------------------------------------------------
+
+// GPTCR
+#define GPT_CR_EN_ENABLE                1 // GPT enabled
+#define GPT_CR_EN_DISABLE               0 // GPT disabled
+
+#define GPT_CR_ENMOD_RESET              1 // GPT counter reset to
+                                          //   0 when disabled
+#define GPT_CR_ENMOD_RETAIN             0 // GPT counter retains
+                                          //   value when disabled
+
+#define GPT_CR_DBGEN_ENABLE             1 // GPT enabled in debug mode
+#define GPT_CR_DBGEN_DISABLE            0 // GPT disabled in debug mode
+
+#define GPT_CR_WAITEN_ENABLE            1 // GPT enabled in wait mode
+#define GPT_CR_WAITEN_DISABLE           0 // GPT disabled in wait mode
+
+#define GPT_CR_STOPEN_ENABLE            1 // GPT enabled in stopdoze mode
+#define GPT_CR_STOPEN_DISABLE           0 // GPT disabled in stopoze mode
+
+#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
+#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
+#define GPT_CR_CLKSRC_IPGCLK            1 // ipg_clk is the clock source
+#define GPT_CR_CLKSRC_HIGHFREQ          2 // ipg_clk_highfreq
+#define GPT_CR_CLKSRC_EXTCLK            3 // ipp_gpt_clkin (external clock
+// from pad) is the clock source
+#define GPT_CR_CLKSRC_CLK32K            4 // ipg_clk_32k is clock source
+#define GPT_CR_CLKSRC_CLK8M             5 // crystal oscillator divided by 8 is clock source
+#define GPT_CR_CLKSRC_CLK24M            7 // crystal oscillator (24 Mhz) is clock source
+#elif defined(CPU_IMX6SDL)
+#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
+#define GPT_CR_CLKSRC_IPGCLK            1 // Peripheral Clock
+#define GPT_CR_CLKSRC_HIGHFREQ          2 // High Frequency Reference Clock
+#define GPT_CR_CLKSRC_EXTCLK            3 // External Clock (CLKIN)
+#define GPT_CR_CLKSRC_LOWFREQ           4 // Low Frequency Reference Clock
+#define GPT_CR_CLKSRC_CLK24M            5 // Crystal oscillator as Reference Clock
+#elif defined(CPU_IMX6SX)
+#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
+#define GPT_CR_CLKSRC_PERIPHCLK         1 // Peripheral Clock
+#define GPT_CR_CLKSRC_HIGHFREQ          2 // High Frequency Reference Clock
+#define GPT_CR_CLKSRC_EXTCLK            3 // External Clock (CLKIN)
+#define GPT_CR_CLKSRC_LOWFREQ           4 // Low Frequency Reference Clock
+#define GPT_CR_CLKSRC_CLK24M            5 // Crystal oscillator as Reference Clock
+#else
+#error CPU Preprocessor Flag Not Defined
+#endif
+
+#define GPT_CR_FRR_FREERUN              1 // Freerun mode (counter
+                                          //   continues after compare)
+#define GPT_CR_FRR_RESTART              0 // Restart mode (counter set
+                                          //   to zero after compare)
+#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
+#define GPT_CR_EN_24M_DISABLE           0  // 24M clock disabled
+#define GPT_CR_EN_24M_ENABLE            1  // 24M clock enabled
+#endif
+
+#define GPT_CR_SWR_RESET                1 // Self-clearing software reset
+#define GPT_CR_SWR_NORESET              0 // Do not activate software reset
+
+#define GPT_CR_IM1_DISABLE              0 // Capture Disabled
+#define GPT_CR_IM1_EDGE_RISE            1 // Capture on rising edge
+#define GPT_CR_IM1_EDGE_FALL            2 // Capture on falling edge
+#define GPT_CR_IM1_EDGE_BOTH            3 // Capture on both edges
+
+#define GPT_CR_IM2_DISABLE              0 // Capture Disabled
+#define GPT_CR_IM2_EDGE_RISE            1 // Capture on rising edge
+#define GPT_CR_IM2_EDGE_FALL            2 // Capture on falling edge
+#define GPT_CR_IM2_EDGE_BOTH            3 // Capture on both edges
+
+#define GPT_CR_OM1_DISABLE              0 // Compare generates no response
+#define GPT_CR_OM1_TOGGLE               1 // Compare toggles output pin
+#define GPT_CR_OM1_CLEAR                2 // Compare clears output pin
+#define GPT_CR_OM1_SET                  3 // Compare sets output pin
+#define GPT_CR_OM1_PULSE                4 // Compare event generates a
+                                          //   single count duration pulse
+                                          //   on output pin
+
+#define GPT_CR_OM2_DISABLE              0 // Compare generates no response
+#define GPT_CR_OM2_TOGGLE               1 // Compare toggles output pin
+#define GPT_CR_OM2_CLEAR                2 // Compare clears output pin
+#define GPT_CR_OM2_SET                  3 // Compare sets output pin
+#define GPT_CR_OM2_PULSE                4 // Compare event generates a
+                                          //   single count duration pulse
+                                          //   on output pin
+
+#define GPT_CR_OM3_DISABLE              0 // Compare generates no response
+#define GPT_CR_OM3_TOGGLE               1 // Compare toggles output pin
+#define GPT_CR_OM3_CLEAR                2 // Compare clears output pin
+#define GPT_CR_OM3_SET                  3 // Compare sets output pin
+#define GPT_CR_OM3_PULSE                4 // Compare event generates a
+                                          //   single count duration pulse
+                                          //   on output pin
+
+#define GPT_CR_FO1_FORCE                1 // Force pin action programmed
+                                          //   for output compare 1 pin.
+                                          //   Pin is self-negating.
+#define GPT_CR_FO1_NOFORCE              0 // Do not force pin
+
+#define GPT_CR_FO2_FORCE                1 // Force pin action programmed
+                                          //   for output compare 1 pin
+                                          //   Pin is self-negating.
+#define GPT_CR_FO2_NOFORCE              0 // Do not force pin
+
+#define GPT_CR_FO3_FORCE                1 // Force pin action programmed
+                                          //   for output compare 1 pin
+                                          //   Pin is self-negating.
+#define GPT_CR_FO3_NOFORCE              0 // Do not force pin
+
+// GPTSR
+#define GPT_SR_OF1_STATUS_CLEAR         1 // Output compare 1 status clear
+#define GPT_SR_OF2_STATUS_CLEAR         1 // Output compare 2 status clear
+#define GPT_SR_OF3_STATUS_CLEAR         1 // Output compare 3 status clear
+#define GPT_SR_IF1_STATUS_CLEAR         1 // Input capture 1 status clear
+#define GPT_SR_IF2_STATUS_CLEAR         1 // Input capture 2 status clear
+#define GPT_SR_ROV_STATUS_CLEAR         1 // Rollover status clear
+
+// GPTIR
+#define GPT_IR_OF1IE_INT_ENABLE         1 // Output compare 1 int enabled
+#define GPT_IR_OF1IE_INT_DISABLE        0 // Output compare 1 int disabled
+
+#define GPT_IR_OF2IE_INT_ENABLE         1 // Output compare 2 int enabled
+#define GPT_IR_OF2IE_INT_DISABLE        0 // Output compare 2 int disabled
+
+#define GPT_IR_OF3IE_INT_ENABLE         1 // Output compare 3 int enabled
+#define GPT_IR_OF3IE_INT_DISABLE        0 // Output compare 3 int disabled
+
+#define GPT_IR_IF1IE_INT_ENABLE         1 // Input capture 1 int enabled
+#define GPT_IR_IF1IE_INT_DISABLE        0 // Input capture 1 int disabled
+
+#define GPT_IR_IF2IE_INT_ENABLE         1 // Input capture 2 int enabled
+#define GPT_IR_IF2IE_INT_DISABLE        0 // Input capture 2 int disabled
+
+#define GPT_IR_ROVIE_INT_ENABLE         1 // Rollover int enabled
+#define GPT_IR_ROVIE_INT_DISABLE        0 // Rollover int disabled
+
+#endif // __COMMON_GPT_H
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 15/27] Silicon/NXP: Add i.MX6 GPT Timer library
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (13 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-13 17:26   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 16/27] Silicon/NXP: Add i.MX6 Timer DXE driver Chris Co
                   ` (12 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for GPT Timer on NXP i.MX6 SoCs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h           |  24 ++
 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c   | 246 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf |  45 ++++
 3 files changed, 315 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h b/Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
new file mode 100644
index 000000000000..fbac9d2a61c0
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
@@ -0,0 +1,24 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_TIMER_H_
+#define _IMX6_TIMER_H_
+
+RETURN_STATUS
+EFIAPI
+TimerConstructor (
+  VOID
+  );
+
+#endif  /* _IMX6_TIMER_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c b/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
new file mode 100644
index 000000000000..fa55cee242ef
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
@@ -0,0 +1,246 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+
+#include <common_gpt.h>
+#include <iMX6.h>
+#include <iMX6Timer.h>
+
+RETURN_STATUS
+EFIAPI
+TimerConstructor (
+  VOID
+  )
+{
+  PCSP_GPT_REGS pGpt;
+  UINT32 FreqPreScale;
+
+  pGpt = (PCSP_GPT_REGS)CSP_BASE_REG_PA_GPT;
+
+  ASSERT (SOC_OSC_FREQUENCY_REF_HZ >= PcdGet32 (PcdArmArchTimerFreqInHz));
+
+  // Calculate the scale factor since we are using the 24Mhz oscillator
+  // as reference.
+  FreqPreScale = SOC_OSC_FREQUENCY_REF_HZ / PcdGet32 (PcdArmArchTimerFreqInHz);
+  ASSERT (FreqPreScale <= (1 << GPT_PR_PRESCALER_WID));
+
+  // Set the frequency scale
+  MmioWrite32 ((UINTN)&pGpt->PR, FreqPreScale - 1);
+
+#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
+  // Set GPT configuration:
+  // - GPT Enabled
+  // - Use the 24Mhz oscillator source
+  MmioWrite32 ((UINTN)&pGpt->CR,
+            (GPT_CR_EN_ENABLE << GPT_CR_EN_LSH) |
+            (GPT_CR_CLKSRC_CLK24M << GPT_CR_CLKSRC_LSH));
+#elif defined(CPU_IMX6SDL) || defined(CPU_IMX6SX)
+  // Set GPT configuration:
+  // - GPT Enabled
+  // - Enable 24 Mhz Oscillator
+  // - Use the 24Mhz oscillator source
+  MmioWrite32 ((UINTN)&pGpt->CR,
+            (GPT_CR_EN_ENABLE << GPT_CR_EN_LSH) |
+            (GPT_CR_EN_24M_ENABLE << GPT_CR_EN_24M_LSH) |
+            (GPT_CR_CLKSRC_CLK24M << GPT_CR_CLKSRC_LSH));
+#else
+#error CPU Preprocessor Flag Not Defined
+#endif
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return The value of MicroSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN  UINTN   MicroSeconds
+  )
+{
+  UINT64 TimerTicks64;
+  UINT32 CurCounterRead;
+  UINT32 PrevCounterRead;
+  UINT64 CountOffset;
+
+  // Convert uSec delay to counter ticks:
+  TimerTicks64      = ((UINT64)MicroSeconds * PcdGet32 (
+                         PcdArmArchTimerFreqInHz)) / 1000000U;
+  CurCounterRead    = (UINT32)GetPerformanceCounter();
+  PrevCounterRead   = CurCounterRead;
+  TimerTicks64      += (UINT64)CurCounterRead;
+  CountOffset       = 0;
+
+  // GPT is a 32bit counter, thus we need to handle rollover cases.
+  while (((UINT64)CurCounterRead + CountOffset) < TimerTicks64) {
+    CurCounterRead = (UINT32)GetPerformanceCounter();
+    if (CurCounterRead < PrevCounterRead) {
+      CountOffset += 0x100000000;
+    }
+    PrevCounterRead = CurCounterRead;
+  }
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return The value of NanoSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN  UINTN   NanoSeconds
+  )
+{
+  if (NanoSeconds < (0xffffffff - 999)) {
+    NanoSeconds += 999;
+  }
+  MicroSecondDelay (NanoSeconds / 1000);
+
+  return 0;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  The counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+  VOID
+  )
+{
+  PCSP_GPT_REGS pGpt;
+
+  pGpt = (PCSP_GPT_REGS)CSP_BASE_REG_PA_GPT;
+  return MmioRead32 ((UINTN)(&pGpt->CNT));
+}
+
+/**
+  Retrieves the 64-bit frequency in Hz and the range of performance counter
+  values.
+
+  If StartValue is not NULL, then the value that the performance counter starts
+  with immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+  OUT UINT64  *StartValue,  OPTIONAL
+  OUT UINT64  *EndValue     OPTIONAL
+  )
+{
+  if (StartValue != NULL) {
+    *StartValue = 0x0;
+  }
+
+  if (EndValue != NULL) {
+    *EndValue = MAX_UINT64;
+  }
+
+  return PcdGet32 (PcdArmArchTimerFreqInHz);
+}
+
+/**
+  Converts elapsed ticks of performance counter to time in nanoseconds.
+
+  This function converts the elapsed ticks of running performance counter to
+  time value in unit of nanoseconds.
+
+  @param  Ticks     The number of elapsed ticks of running performance counter.
+
+  @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+  IN  UINT64    Ticks
+  )
+{
+  UINT64  NanoSeconds;
+  UINT32  Remainder;
+  UINT32  TimerFreq;
+
+  TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz);
+
+  //          Ticks
+  // Time = --------- x 1,000,000,000
+  //        Frequency
+  NanoSeconds = MultU64x32 (
+                  DivU64x32Remainder (
+                    Ticks,
+                    TimerFreq,
+                    &Remainder),
+                  1000000000U
+                );
+
+  // Frequency < 0x100000000, so Remainder < 0x100000000,
+  // then (Remainder * 1,000,000,000) will not overflow 64-bit.
+  NanoSeconds += DivU64x32 (
+                   MultU64x32 (
+                     (UINT64) Remainder,
+                     1000000000U),
+                   TimerFreq
+                 );
+
+  return NanoSeconds;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf b/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
new file mode 100644
index 000000000000..4716dee65a5d
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
@@ -0,0 +1,45 @@
+## @file
+#
+#  NULL instance of Timer Library as a template.
+#
+#  A non-functional instance of the Timer Library that can be used as a template
+#  for the implementation of a functional timer library instance. This library
+#  instance can also be used to test build DXE, Runtime, DXE SAL, and DXE SMM
+#  modules that require timer services as well as EBC modules that require
+#  timer services.
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#  Copyright (c) 2007 - 2008, Intel Corporation.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMX6TimerLib
+  FILE_GUID                      = 2956C1A6-6FF8-4763-9FD8-D45892E025E3
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+
+[Sources.common]
+  TimerLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+
+[LibraryClasses]
+  DebugLib
+  IoLib
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 16/27] Silicon/NXP: Add i.MX6 Timer DXE driver
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (14 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 15/27] Silicon/NXP: Add i.MX6 GPT Timer library Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-13 17:33   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 17/27] Silicon/NXP: Add i.MX6 USB Phy Library Chris Co
                   ` (11 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds DXE support for EPIT timer on NXP i.MX6 SoCs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c      | 278 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf |  55 ++++
 2 files changed, 333 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
new file mode 100644
index 000000000000..6b4db6185b48
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
@@ -0,0 +1,278 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/HardwareInterrupt.h>
+#include <Protocol/Timer.h>
+
+#include <common_epit.h>
+#include <iMX6.h>
+
+// The notification function to call on every timer interrupt.
+volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY) NULL;
+EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT) NULL;
+
+// Cached copy of the Hardware Interrupt protocol instance
+EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
+
+// Cached interrupt vector
+volatile UINTN  mVector;
+UINT64 mCurrentTimerPeriod;
+
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+  IN EFI_TIMER_ARCH_PROTOCOL  *This,
+  IN EFI_TIMER_NOTIFY         NotifyFunction
+  )
+{
+  DEBUG ((DEBUG_VERBOSE, "++TimerDriverRegisterHandler()\n"));
+  if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  mTimerNotifyFunction = NotifyFunction;
+  DEBUG ((DEBUG_VERBOSE, "--TimerDriverRegisterHandler()=ok\n"));
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+  IN EFI_TIMER_ARCH_PROTOCOL  *This,
+  IN UINT64                   TimerPeriod
+  )
+{
+  PCSP_EPIT_REG   pEpit;
+  UINT16          EpitPreScalar;
+  EFI_STATUS      Status;
+  UINT32          TimerCount;
+  UINT32          Value;
+
+  DEBUG ((DEBUG_VERBOSE, "++TimerDriverSetTimerPeriod(%d)\n", TimerPeriod));
+
+  pEpit = (PCSP_EPIT_REG) CSP_BASE_REG_PA_EPIT1;
+  DEBUG ((DEBUG_VERBOSE,
+          "TimerDriverSetTimerPeriod() disable timer. EPIT_REG adr=%p\n", pEpit));
+
+  // First stop the timer.
+  Value = MmioRead32 ((UINTN)&pEpit->CR);
+  Value &= ~(((1 << EPIT_CR_EN_WID) - 1) << EPIT_CR_EN_LSH);
+  Value |= (EPIT_CR_EN_DISABLE << EPIT_CR_EN_LSH);
+  MmioWrite32 ((UINTN)&pEpit->CR, Value);
+
+  if (TimerPeriod == 0) {
+    Status = gInterrupt->DisableInterruptSource (gInterrupt, mVector);
+    mCurrentTimerPeriod = 0;
+    DEBUG ((DEBUG_VERBOSE, "--TimerDriverSetTimerPeriod() Timer Disabled\n"));
+    return Status;
+  }
+
+  // Configure EPIT to be sourced from iMX6 24 MHz crystal oscialltor
+  // Aim to have UEFI tick counting at 1 MHz clock or another frequency as set in pcd
+  EpitPreScalar = 68;
+  DEBUG ((DEBUG_VERBOSE,
+          "TimerDriverSetTimerPeriod() using corrected EPIT prescalar=%d\n",
+          EpitPreScalar));
+
+  MmioWrite32 ((UINTN)&pEpit->CR,
+            (EPIT_CR_ENMOD_LOAD << EPIT_CR_ENMOD_LSH) |
+            (EPIT_CR_OCIEN_ENABLE << EPIT_CR_OCIEN_LSH) |
+            (EPIT_CR_RLD_RELOAD << EPIT_CR_RLD_LSH) |
+            ((EpitPreScalar - 1) << EPIT_CR_PRESCALAR_LSH) |
+            (EPIT_CR_SWR_NORESET << EPIT_CR_SWR_LSH) |
+            (EPIT_CR_IOVW_OVR << EPIT_CR_IOVW_LSH) |
+            (EPIT_CR_DBGEN_ACTIVE << EPIT_CR_DBGEN_LSH) |
+            (EPIT_CR_WAITEN_ENABLE << EPIT_CR_WAITEN_LSH) |
+            (EPIT_CR_DOZEN_ENABLE << EPIT_CR_DOZEN_LSH) |
+            (EPIT_CR_STOPEN_ENABLE << EPIT_CR_STOPEN_LSH) |
+            (EPIT_CR_OM_DICONNECT << EPIT_CR_OM_LSH) |
+            (EPIT_CR_CLKSRC_IPGCLK << EPIT_CR_CLKSRC_LSH));
+
+  // Clear timer compare interrupt flag (write-1-clear)
+  MmioWrite32 ((UINTN)&pEpit->SR, ((1 << EPIT_SR_OCIF_WID) - 1) << EPIT_SR_OCIF_LSH);
+  TimerCount = (UINT32) (TimerPeriod / 10);
+  if ((UINT64)TimerCount > (UINT64)0xffffffff) {
+    TimerCount = 0xffffffff;
+  }
+
+  mCurrentTimerPeriod = TimerPeriod;
+  MmioWrite32 ((UINTN)&pEpit->CMPR, TimerCount);
+  MmioWrite32 ((UINTN)&pEpit->LR, TimerCount);
+  Status = gInterrupt->EnableInterruptSource (gInterrupt, mVector);
+
+  // Turn the timer on
+  Value = MmioRead32 ((UINTN)&pEpit->CR);
+  Value &= ~(((1 << EPIT_CR_EN_WID) - 1) << EPIT_CR_EN_LSH);
+  Value |= EPIT_CR_EN_ENABLE << EPIT_CR_EN_LSH;
+  MmioWrite32 ((UINTN)&pEpit->CR, Value);
+
+  DEBUG ((DEBUG_VERBOSE, "--TimerDriverSetTimerPeriod(%d)=%Xh\n", TimerPeriod,
+          Status));
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+  IN EFI_TIMER_ARCH_PROTOCOL   *This,
+  OUT UINT64                   *TimerPeriod
+  )
+{
+  *TimerPeriod = mCurrentTimerPeriod;
+  DEBUG ((DEBUG_VERBOSE, "+-TimerDriverGetTimerPeriod(%d)=ok\n",
+          mCurrentTimerPeriod));
+  return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+TimerInterruptHandler (
+  IN  HARDWARE_INTERRUPT_SOURCE   Source,
+  IN  EFI_SYSTEM_CONTEXT          SystemContext
+  )
+{
+  EFI_TPL OriginalTPL;
+  PCSP_EPIT_REG pEpit;
+
+  pEpit = (PCSP_EPIT_REG) CSP_BASE_REG_PA_EPIT1;
+
+  // DXE core uses this callback for the EFI timer tick. The DXE core uses locks
+  // that raise to TPL_HIGH and then restore back to current level. Thus we need
+  // to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
+  OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  // Check if the timer interrupt is active
+  if (MmioRead32 ((UINTN)&pEpit->SR) != 0) {
+    // Acknowledge the EPIT interrupt
+    MmioWrite32 ((UINTN)&pEpit->SR, 0x1);
+
+    // Signal EOI to avoid losing subsequent ticks from long duration handlers
+    gInterrupt->EndOfInterrupt (gInterrupt, Source);
+
+    if (mTimerNotifyFunction) {
+      mTimerNotifyFunction (mCurrentTimerPeriod);
+    }
+  }
+
+  gBS->RestoreTPL (OriginalTPL);
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+  IN EFI_TIMER_ARCH_PROTOCOL  *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_TIMER_ARCH_PROTOCOL gTimer = {
+  TimerDriverRegisterHandler,
+  TimerDriverSetTimerPeriod,
+  TimerDriverGetTimerPeriod,
+  TimerDriverGenerateSoftInterrupt
+};
+
+VOID
+EFIAPI
+ExitBootServicesEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "Disabling EPIT timer on ExitBootServicesEvent"));
+
+  // Disable the timer
+  Status = TimerDriverSetTimerPeriod (&gTimer, 0);
+  ASSERT_EFI_ERROR (Status);
+}
+
+EFI_STATUS
+EFIAPI
+TimerInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+)
+{
+  EFI_HANDLE  Handle;
+  EFI_STATUS  Status;
+  DEBUG ((DEBUG_VERBOSE, "++TimerInitialize()\n"));
+
+  Handle = NULL;
+  mVector = IRQ_EPIT1;
+
+  // Find the interrupt controller protocol.
+  Status = gBS->LocateProtocol (
+             &gHardwareInterruptProtocolGuid,
+             NULL,
+             (VOID **) &gInterrupt);
+  ASSERT_EFI_ERROR (Status);
+
+  // Disable the timer
+  Status = TimerDriverSetTimerPeriod (&gTimer, 0);
+  ASSERT_EFI_ERROR (Status);
+
+  // Install interrupt handler
+  Status = gInterrupt->RegisterInterruptSource (gInterrupt, mVector,
+           TimerInterruptHandler);
+  ASSERT_EFI_ERROR (Status);
+
+  // Set up default timer
+  Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32 (PcdTimerPeriod));
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((
+           DEBUG_VERBOSE,
+           "EPIT Timer initialized to default period %d x 100ns ~ %dms\n",
+           FixedPcdGet32 (PcdTimerPeriod),
+           FixedPcdGet32 (PcdTimerPeriod) / 10000));
+
+  // Install the Timer Architectural Protocol onto a new handle
+  Status = gBS->InstallMultipleProtocolInterfaces (
+             &Handle,
+             &gEfiTimerArchProtocolGuid,
+             &gTimer,
+             NULL);
+
+  ASSERT_EFI_ERROR (Status);
+
+  // Register for ExitBootServicesEvent
+  Status = gBS->CreateEvent (
+             EVT_SIGNAL_EXIT_BOOT_SERVICES,
+             TPL_NOTIFY,
+             ExitBootServicesEvent,
+             NULL,
+             &EfiExitBootServicesEvent);
+
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_VERBOSE, "--TimerInitialize()\n"));
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
new file mode 100644
index 000000000000..adcc158e29ab
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
@@ -0,0 +1,55 @@
+#/** @file
+#
+#  Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMX6TimerDxe
+  FILE_GUID                      = 7CAF576F-F1D9-4104-A922-CB64537FD7AE
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = TimerInitialize
+
+[Sources.common]
+  Timer.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  PerformanceLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+  UefiRuntimeServicesTableLib
+
+[Guids]
+
+[Protocols]
+  gEfiTimerArchProtocolGuid
+  gHardwareInterruptProtocolGuid
+
+[Pcd.common]
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds
+  gEmbeddedTokenSpaceGuid.PcdTimerPeriod
+
+[Depex]
+  gHardwareInterruptProtocolGuid
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 17/27] Silicon/NXP: Add i.MX6 USB Phy Library
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (15 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 16/27] Silicon/NXP: Add i.MX6 Timer DXE driver Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 17:10   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library Chris Co
                   ` (10 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for configuring the USB EHCI PHY on NXP i.MX6 SoCs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h                    |  20 ++
 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c      | 328 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf |  43 +++
 3 files changed, 391 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h b/Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
new file mode 100644
index 000000000000..153c5461a6ad
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
@@ -0,0 +1,20 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_USB_PHY_H_
+#define _IMX6_USB_PHY_H_
+
+EFI_STATUS ImxUsbPhyInit (IMX_USBPHY_ID ImxUsbPhyId);
+
+#endif // _IMX6_USB_PHY_H_
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
new file mode 100644
index 000000000000..317d17d14844
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
@@ -0,0 +1,328 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+
+#include <iMX6.h>
+#include <iMX6IoMux.h>
+#include <iMX6UsbPhy.h>
+
+#define USB_PHY_PLL_LOCK_TIMEOUT_USEC (UINT32)(1000*1000)
+#define USB_EHCI_STOP_RESET_TIMEOUT_USEC (UINT32)(1000*1000)
+
+#define IMX_CCM_ANALOG_PLL_USB1_REG_LOCK 0x80000000
+#define IMX_USB_CMD_REG_RUN 0x00000001
+#define IMX_USB_CMD_REG_RESET 0x00000002
+
+/**
+  Wait for a register bit to be on/off
+**/
+EFI_STATUS
+RegisterWaitBit (
+  IN  volatile VOID   *RegisterAddr,
+  IN  UINT32          Mask,
+  IN  BOOLEAN         IsWaitOn,
+  IN  UINT32          TimeOutUsec
+  )
+{
+  UINT32 RegisterValue;
+  UINT32 TimeUsec;
+
+  TimeUsec = 0;
+  do {
+    RegisterValue = MmioRead32 ((UINTN)RegisterAddr) & Mask;
+    if (((RegisterValue == Mask) && IsWaitOn) || ((RegisterValue == 0)
+        && !IsWaitOn)) {
+      return EFI_SUCCESS;
+    }
+
+    MicroSecondDelay (10);
+    TimeUsec += 10;
+  } while (TimeUsec < TimeOutUsec);
+
+  return EFI_TIMEOUT;
+}
+
+/**
+  Turn on the 480Mhz PLL
+**/
+EFI_STATUS
+ImxUsbPhyEnablePll (
+  IN  IMX_USBPHY_ID   ImxUsbPhyId
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS     *CcmAnaRegsPtr;
+  volatile IMX_CCM_ANALOG_PLL_USB1_REG  *PllUsbClrRegPtr;
+  volatile IMX_CCM_ANALOG_PLL_USB1_REG  *PllUsbSetRegPtr;
+  IMX_CCM_ANALOG_PLL_USB1_REG           PllUsbClrReg;
+  IMX_CCM_ANALOG_PLL_USB1_REG           PllUsbSetReg;
+  EFI_STATUS                            Status;
+
+  CcmAnaRegsPtr = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
+
+  switch (ImxUsbPhyId) {
+  case IMX_USBPHY0:
+    PllUsbClrRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB1_CLR;
+    PllUsbSetRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB1_SET;
+    break;
+  case IMX_USBPHY1:
+    PllUsbClrRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB2_CLR;
+    PllUsbSetRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB2_SET;
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PllUsbClrReg.AsUint32 = 0;
+  PllUsbClrReg.BYPASS = 1;
+  MmioWrite32 ((UINTN)PllUsbClrRegPtr, PllUsbClrReg.AsUint32);
+
+  PllUsbSetReg.AsUint32 = 0;
+  PllUsbSetReg.EN_USB_CLKS = 1;
+  PllUsbSetReg.POWER = 1;
+  PllUsbSetReg.ENABLE = 1;
+  MmioWrite32 ((UINTN)PllUsbSetRegPtr, PllUsbSetReg.AsUint32);
+
+  // Wait for PLL to lock
+  Status = RegisterWaitBit (
+             PllUsbSetRegPtr,
+             IMX_CCM_ANALOG_PLL_USB1_REG_LOCK,
+             TRUE,
+             USB_PHY_PLL_LOCK_TIMEOUT_USEC);
+
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "PLL 480Mhz failed to lock for PHY %d\n",
+            (UINT32)ImxUsbPhyId));
+    // On failure disable the PHY
+    PllUsbClrReg.AsUint32 = 0;
+    PllUsbSetReg.EN_USB_CLKS = 1;
+    PllUsbSetReg.POWER = 1;
+    PllUsbSetReg.ENABLE = 1;
+    MmioWrite32 ((UINTN)PllUsbClrRegPtr, PllUsbSetReg.AsUint32);
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Reset the EHCI controller associated with the given PHY.
+**/
+EFI_STATUS
+ImxUsbEhciResetController (
+  IN  IMX_USBPHY_ID   ImxUsbPhyId
+  )
+{
+  volatile USB_USBCMD_REG   *UsbCmdRegPtr;
+  volatile USB_USBMODE_REG  *UsbModeRegPtr;
+  EFI_STATUS                Status;
+  USB_USBCMD_REG            UsbCmdReg;
+  USB_USBMODE_REG           UsbModeReg;
+
+  switch (ImxUsbPhyId) {
+  case IMX_USBPHY0:
+    UsbCmdRegPtr = (USB_USBCMD_REG *) (IMX_USBCORE_BASE + IMX_USBCORE_LENGTH * 0 +
+                                       IMX_USBCMD_OFFSET);
+    break;
+  case IMX_USBPHY1:
+    UsbCmdRegPtr = (USB_USBCMD_REG *) (IMX_USBCORE_BASE + IMX_USBCORE_LENGTH * 1 +
+                                       IMX_USBCMD_OFFSET);
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // The host controller can only be reset when it is stopped.
+  UsbCmdReg.AsUint32 = MmioRead32 ((UINTN)UsbCmdRegPtr);
+  UsbCmdReg.RS = 0;
+  MmioWrite32 ((UINTN)UsbCmdRegPtr, UsbCmdReg.AsUint32);
+
+  // Wait for controller to stop
+  Status = RegisterWaitBit (
+             UsbCmdRegPtr,
+             IMX_USB_CMD_REG_RUN,
+             FALSE,
+             USB_EHCI_STOP_RESET_TIMEOUT_USEC);
+  if (Status != EFI_SUCCESS) {
+    ASSERT_EFI_ERROR (Status);
+    DEBUG ((DEBUG_ERROR, "Failed to stop EHCI controller (PHY %d)\n",
+            (UINT32)ImxUsbPhyId));
+    return Status;
+  }
+
+  // Reset the controller
+  UsbCmdReg.AsUint32 = MmioRead32 ((UINTN)UsbCmdRegPtr);
+  UsbCmdReg.RST = 1;
+  MmioWrite32 ((UINTN)UsbCmdRegPtr, UsbCmdReg.AsUint32);
+
+  // Wait for controller reset to complete
+  Status = RegisterWaitBit (
+             UsbCmdRegPtr,
+             IMX_USB_CMD_REG_RESET,
+             FALSE,
+             USB_EHCI_STOP_RESET_TIMEOUT_USEC);
+
+  if (Status != EFI_SUCCESS) {
+    ASSERT_EFI_ERROR (Status);
+    DEBUG ((DEBUG_ERROR, "Failed to reset EHCI controller (PHY %d)\n",
+            (UINT32)ImxUsbPhyId));
+    return Status;
+  }
+
+  // Force OTG port into Host mode. We have seen that ID_PIN can be
+  // unreliable in some board designs (e.g. SABRESED).
+  // If the OTG port is not forced into Host mode, the USB stack fails to
+  // start.
+  if (ImxUsbPhyId == IMX_USBPHY0) {
+    DEBUG ((DEBUG_INFO, "Switching USB OTG Port to Host\n"));
+
+    UsbModeRegPtr = (USB_USBMODE_REG *) (IMX_USBCORE_BASE + IMX_USBMODE_OFFSET);
+    UsbModeReg.AsUint32 = MmioRead32 ((UINTN)UsbModeRegPtr);
+    UsbModeReg.CM = IMX_USBMODE_HOST;
+    MmioWrite32 ((UINTN)UsbModeRegPtr, UsbModeReg.AsUint32);
+
+    UsbModeReg.AsUint32 = MmioRead32 ((UINTN)UsbModeRegPtr);
+    ASSERT (UsbModeReg.CM == IMX_USBMODE_HOST);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize a USB PHY
+**/
+EFI_STATUS
+ImxUsbPhyInit (
+  IN  IMX_USBPHY_ID   ImxUsbPhyId
+  )
+{
+  volatile IMX_USBANA_REGISTERS       *UsbAnaRegsPtr;
+  volatile IMX_USBANA_USB_REGISTERS   *UsbAnaUsbRegsPtr;
+  volatile USBNC_USB_UH_CTRL_REG      *UsbNcUhCtrlRegPtr;
+  volatile IMX_USBNONCORE_REGISTERS   *UsbNonCoreRegPtr;
+  volatile IMX_USBPHY_REGISTERS       *UsbPhyRegsPtr;
+  EFI_STATUS                          Status;
+  USB_ANALOG_USB_CHRG_DETECT_REG      UsbAnaChrgDetReg;
+  USB_ANALOG_USB_MISC_REG             UsbAnaMicReg;
+  USBNC_USB_UH_CTRL_REG               UsbNcHcCtrlReg;
+  USBPHYx_CTRL_REG                    UsbPhyCtrlReg;
+
+  UsbAnaRegsPtr = (IMX_USBANA_REGISTERS *)IMX_USBANA_BASE;
+  UsbNonCoreRegPtr = (IMX_USBNONCORE_REGISTERS *)IMX_USBNONCORE_BASE;
+
+  switch (ImxUsbPhyId) {
+  case IMX_USBPHY0:
+    UsbPhyRegsPtr = (IMX_USBPHY_REGISTERS *)IMX_USBPHY1_BASE;
+    UsbAnaUsbRegsPtr = &UsbAnaRegsPtr->USBANA[0];
+    UsbNcUhCtrlRegPtr = (USBNC_USB_UH_CTRL_REG *)
+                        &UsbNonCoreRegPtr->USBNC_USB_OTG_CTRL;
+    break;
+  case IMX_USBPHY1:
+    UsbPhyRegsPtr = (IMX_USBPHY_REGISTERS *)IMX_USBPHY2_BASE;
+    UsbAnaUsbRegsPtr = &UsbAnaRegsPtr->USBANA[1];
+    UsbNcUhCtrlRegPtr = (USBNC_USB_UH_CTRL_REG *)
+                        &UsbNonCoreRegPtr->USBNC_USB_UH1_CTRL;
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // USB power configuration:
+  // Set power polarity
+  UsbNcHcCtrlReg.AsUint32 = MmioRead32 ((UINTN)UsbNcUhCtrlRegPtr);
+  UsbNcHcCtrlReg.PWR_POL = 1;
+  UsbNcHcCtrlReg.AsUint32 |= 0x2;     // Reserved bit
+  MmioWrite32 ((UINTN)UsbNcUhCtrlRegPtr, UsbNcHcCtrlReg.AsUint32);
+
+  // Disable external USB charger detector
+  UsbAnaChrgDetReg.AsUint32 = 0;
+  UsbAnaChrgDetReg.EN_B = 1;
+  UsbAnaChrgDetReg.CHK_CHRG_B = 1;
+  MmioWrite32 ((UINTN)&UsbAnaUsbRegsPtr->USB_ANALOG_USB_CHRG_DETECT_SET,
+                UsbAnaChrgDetReg.AsUint32);
+
+  // Enable the 480Mhz PLL
+  Status = ImxUsbPhyEnablePll (ImxUsbPhyId);
+  if (Status != EFI_SUCCESS) {
+    ASSERT_EFI_ERROR (Status);
+    DEBUG ((DEBUG_ERROR, "Failed to enable PLL 480Mhz failed for PHY %d\n",
+            (UINT32)ImxUsbPhyId));
+    return Status;
+  }
+
+  // Configure Over Current
+  UsbNcHcCtrlReg.AsUint32 = MmioRead32 ((UINTN)UsbNcUhCtrlRegPtr);
+  UsbNcHcCtrlReg.OVER_CUR_POL = 0;
+  UsbNcHcCtrlReg.OVER_CUR_DIS = 1;
+  MmioWrite32 ((UINTN)UsbNcUhCtrlRegPtr, UsbNcHcCtrlReg.AsUint32);
+
+  // Enable USBH PHY clock
+  UsbPhyCtrlReg.AsUint32 = 0;
+  UsbPhyCtrlReg.CLKGATE = 1;
+  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_CLR, UsbPhyCtrlReg.AsUint32);
+  MicroSecondDelay (10);
+
+  // Enable clock to UTMI block
+  UsbAnaMicReg.AsUint32 = 0;
+  UsbAnaMicReg.EN_CLK_UTMI = 1;
+  MmioWrite32 ((UINTN)&UsbAnaUsbRegsPtr->USB_ANALOG_USB_MISC_SET,
+                UsbAnaMicReg.AsUint32);
+  MicroSecondDelay (10);
+
+  // Enable USBH PHY
+  // Reset the associated EHCI controller
+  Status = ImxUsbEhciResetController (ImxUsbPhyId);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  // Reset the PHY
+  UsbPhyCtrlReg.AsUint32 = 0;
+  UsbPhyCtrlReg.SFTRST = 1;
+  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_SET, UsbPhyCtrlReg.AsUint32);
+  MicroSecondDelay (10);
+
+  UsbPhyCtrlReg.AsUint32 = 0;
+  UsbPhyCtrlReg.SFTRST = 1;
+  UsbPhyCtrlReg.CLKGATE = 1;
+  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_CLR, UsbPhyCtrlReg.AsUint32);
+  MicroSecondDelay (10);
+
+  // Power UP the PHY
+  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_PWD, 0);
+
+  // Apply PHY configuration:
+  // - Enable low/full speed devices.
+  UsbPhyCtrlReg.AsUint32 = 0;
+#if defined(CPU_IMX6DQ)
+  UsbPhyCtrlReg.ENAUTOSET_USBCLKS = 1;
+  UsbPhyCtrlReg.ENAUTOCLR_USBCLKGATE = 1;
+  UsbPhyCtrlReg.ENAUTO_PWRON_PLL = 1;
+#endif
+  UsbPhyCtrlReg.ENAUTOCLR_PHY_PWD = 1;
+  UsbPhyCtrlReg.ENAUTOCLR_CLKGATE = 1;
+  UsbPhyCtrlReg.ENUTMILEVEL2 = 1;
+  UsbPhyCtrlReg.ENUTMILEVEL3 = 1;
+  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_SET, UsbPhyCtrlReg.AsUint32);
+#if defined(CPU_IMX6DQ)
+  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_IP_SET, IMX_USBPHY_IP_FIX);
+#endif
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
new file mode 100644
index 000000000000..30f9f1862747
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
@@ -0,0 +1,43 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = iMX6UsbPhyLib
+  FILE_GUID                      = 463989D1-27DC-4AE7-92AE-C7E28C1C605D
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = iMX6UsbPhyLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  TimerLib
+  iMXIoMuxLib
+
+[Sources.common]
+  iMX6UsbPhy.c
+
+[FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (16 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 17/27] Silicon/NXP: Add i.MX6 USB Phy Library Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 18:12   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables Chris Co
                   ` (9 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for managing clocks on NXP i.MX6 SoC. It will
manipulate the Clock Gating registers (CCGR).

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c         | 1876 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf    |   46 +
 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h |  221 +++
 3 files changed, 2143 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
new file mode 100644
index 000000000000..07958b1e392d
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
@@ -0,0 +1,1876 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include "iMX6ClkPwr_private.h"
+
+static IMX_CLOCK_TREE_CACHE mImxpClockPwrCache;   // Cached clock value
+
+STATIC CONST IMX_CCGR_INDEX ImxpCcgrIndexMap[] = {
+  {0, 0},  // MX6_AIPS_TZ1_CLK_ENABLE
+  {0, 1},  // MX6_AIPS_TZ2_CLK_ENABLE
+  {0, 2},  // MX6_APBHDMA_HCLK_ENABLE
+  {0, 3},  // MX6_ASRC_CLK_ENABLE
+  {0, 4},  // MX6_CAAM_SECURE_MEM_CLK_ENABLE
+  {0, 5},  // MX6_CAAM_WRAPPER_ACLK_ENABLE
+  {0, 6},  // MX6_CAAM_WRAPPER_IPG_ENABLE
+  {0, 7},  // MX6_CAN1_CLK_ENABLE
+  {0, 8},  // MX6_CAN1_SERIAL_CLK_ENABLE
+  {0, 9},  // MX6_CAN2_CLK_ENABLE
+  {0, 10}, // MX6_CAN2_SERIAL_CLK_ENABLE
+  {0, 11}, // MX6_ARM_DBG_CLK_ENABLE
+  {0, 12}, // MX6_DCIC1_CLK_ENABLE
+  {0, 13}, // MX6_DCIC2_CLK_ENABLE
+  {0, 14}, // MX6_DTCP_CLK_ENABLE
+  {1, 0},  // MX6_ECSPI1_CLK_ENABLE
+  {1, 1},  // MX6_ECSPI2_CLK_ENABLE
+  {1, 2},  // MX6_ECSPI3_CLK_ENABLE
+  {1, 3},  // MX6_ECSPI4_CLK_ENABLE
+  {1, 4},  // MX6_ECSPI5_CLK_ENABLE
+  {1, 5},  // MX6_ENET_CLK_ENABLE
+  {1, 6},  // MX6_EPIT1_CLK_ENABLE
+  {1, 7},  // MX6_EPIT2_CLK_ENABLE
+  {1, 8},  // MX6_ESAI_CLK_ENABLE
+  {1, 10}, // MX6_GPT_CLK_ENABLE
+  {1, 11}, // MX6_GPT_SERIAL_CLK_ENABLE
+  {1, 12}, // MX6_GPU2D_CLK_ENABLE
+  {1, 13}, // MX6_GPU3D_CLK_ENABLE
+  {2, 0},  // MX6_HDMI_TX_ENABLE
+  {2, 2},  // MX6_HDMI_TX_ISFRCLK_ENABLE
+  {2, 3},  // MX6_I2C1_SERIAL_CLK_ENABLE
+  {2, 4},  // MX6_I2C2_SERIAL_CLK_ENABLE
+  {2, 5},  // MX6_I2C3_SERIAL_CLK_ENABLE
+  {2, 6},  // MX6_IIM_CLK_ENABLE
+  {2, 7},  // MX6_IOMUX_IPT_CLK_IO_ENABLE
+  {2, 8},  // MX6_IPMUX1_CLK_ENABLE
+  {2, 9},  // MX6_IPMUX2_CLK_ENABLE
+  {2, 10}, // MX6_IPMUX3_CLK_ENABLE
+  {2, 11}, // MX6_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE
+  {2, 12}, // MX6_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE
+  {2, 13}, // MX6_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE
+  {3, 0},  // MX6_IPU1_IPU_CLK_ENABLE
+  {3, 1},  // MX6_IPU1_IPU_DI0_CLK_ENABLE
+  {3, 2},  // MX6_IPU1_IPU_DI1_CLK_ENABLE
+  {3, 3},  // MX6_IPU2_IPU_CLK_ENABLE
+  {3, 4},  // MX6_IPU2_IPU_DI0_CLK_ENABLE
+  {3, 5},  // MX6_IPU2_IPU_DI1_CLK_ENABLE
+  {3, 6},  // MX6_LDB_DI0_CLK_ENABLE
+  {3, 7},  // MX6_LDB_DI1_CLK_ENABLE
+  {3, 8},  // MX6_MIPI_CORE_CFG_CLK_ENABLE
+  {3, 9},  // MX6_MLB_CLK_ENABLE
+  {3, 10}, // MX6_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE
+  {3, 12}, // MX6_MMDC_CORE_IPG_CLK_P0_ENABLE
+  {3, 14}, // MX6_OCRAM_CLK_ENABLE
+  {3, 15}, // MX6_OPENVGAXICLK_CLK_ROOT_ENABLE
+  {4, 0},  // MX6_PCIE_ROOT_ENABLE
+  {4, 4},  // MX6_PL301_MX6QFAST1_S133CLK_ENABLE
+  {4, 6},  // MX6_PL301_MX6QPER1_BCHCLK_ENABLE
+  {4, 7},  // MX6_PL301_MX6QPER2_MAINCLK_ENABLE
+  {4, 8},  // MX6_PWM1_CLK_ENABLE
+  {4, 9},  // MX6_PWM2_CLK_ENABLE
+  {4, 10}, // MX6_PWM3_CLK_ENABLE
+  {4, 11}, // MX6_PWM4_CLK_ENABLE
+  {4, 12}, // MX6_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE
+  {4, 13}, // MX6_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE
+  {4, 14}, // MX6_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE
+  {4, 15}, // MX6_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE
+  {5, 0},  // MX6_ROM_CLK_ENABLE
+  {5, 2},  // MX6_SATA_CLK_ENABLE
+  {5, 3},  // MX6_SDMA_CLK_ENABLE
+  {5, 6},  // MX6_SPBA_CLK_ENABLE
+  {5, 7},  // MX6_SPDIF_CLK_ENABLE
+  {5, 9},  // MX6_SSI1_CLK_ENABLE
+  {5, 10}, // MX6_SSI2_CLK_ENABLE
+  {5, 11}, // MX6_SSI3_CLK_ENABLE
+  {5, 12}, // MX6_UART_CLK_ENABLE
+  {5, 13}, // MX6_UART_SERIAL_CLK_ENABLE
+  {6, 0},  // MX6_USBOH3_CLK_ENABLE
+  {6, 1},  // MX6_USDHC1_CLK_ENABLE
+  {6, 2},  // MX6_USDHC2_CLK_ENABLE
+  {6, 3},  // MX6_USDHC3_CLK_ENABLE
+  {6, 4},  // MX6_USDHC4_CLK_ENABLE
+  {6, 5},  // MX6_EIM_SLOW_CLK_ENABLE
+  {6, 6},  // MX6_VDOAXICLK_CLK_ENABLE
+  {6, 7},  // MX6_VPU_CLK_ENABLE
+};
+
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+STATIC IMX_CLOCK_CONTEXT ExpectedClocks[] = {
+  {IMX_OSC_CLK, {24000000, IMX_CLK_NONE}},
+  {IMX_PLL1_MAIN_CLK, {792000000, IMX_OSC_CLK}},
+  {IMX_PLL2_MAIN_CLK, {528000000, IMX_OSC_CLK}},
+  {IMX_PLL2_PFD0, {352000000, IMX_PLL2_MAIN_CLK}},
+  {IMX_PLL2_PFD1, {594000000, IMX_PLL2_MAIN_CLK}},
+  {IMX_PLL2_PFD2, {396000000, IMX_PLL2_MAIN_CLK}},
+  {IMX_PLL3_MAIN_CLK, {480000000, IMX_OSC_CLK}},
+  {IMX_PLL3_PFD0, {720000000, IMX_PLL3_MAIN_CLK}},
+  {IMX_PLL3_PFD1, {540000000, IMX_PLL3_MAIN_CLK}},
+  {IMX_PLL3_PFD2, {508235294, IMX_PLL3_MAIN_CLK}},
+  {IMX_PLL3_PFD3, {454736842, IMX_PLL3_MAIN_CLK}},
+  {IMX_AXI_CLK_ROOT, {264000000, IMX_PERIPH_CLK}},
+  {IMX_MMDC_CH0_CLK_ROOT, {528000000, IMX_PERIPH_CLK}},
+};
+#elif defined(CPU_IMX6SDL)
+STATIC IMX_CLOCK_CONTEXT ExpectedClocks[] = {
+  {IMX_OSC_CLK, {24000000, IMX_CLK_NONE}},
+  {IMX_PLL1_MAIN_CLK, {792000000, IMX_OSC_CLK}},
+  {IMX_PLL2_MAIN_CLK, {528000000, IMX_OSC_CLK}},
+  {IMX_PLL2_PFD0, {306580645, IMX_PLL2_MAIN_CLK}},
+  {IMX_PLL2_PFD1, {528000000, IMX_PLL2_MAIN_CLK}},
+  {IMX_PLL2_PFD2, {396000000, IMX_PLL2_MAIN_CLK}},
+  {IMX_PLL3_MAIN_CLK, {480000000, IMX_OSC_CLK}},
+  {IMX_PLL3_PFD0, {720000000, IMX_PLL3_MAIN_CLK}},
+  {IMX_PLL3_PFD1, {540000000, IMX_PLL3_MAIN_CLK}},
+  {IMX_PLL3_PFD2, {508235294, IMX_PLL3_MAIN_CLK}},
+  {IMX_PLL3_PFD3, {454736842, IMX_PLL3_MAIN_CLK}},
+  {IMX_AXI_CLK_ROOT, {198000000, IMX_PERIPH_CLK}},
+  {IMX_MMDC_CH0_CLK_ROOT, {396000000, IMX_PERIPH_CLK}},
+};
+#endif
+
+/**
+  Get the CCGR register index and gate number for a clock gate.
+
+  @param[in]  ClockGate   Specific clock gate to get CCGR index
+**/
+IMX_CCGR_INDEX
+ImxpCcgrIndexFromClkGate (
+  IN  IMX_CLK_GATE    ClockGate
+  )
+{
+  return ImxpCcgrIndexMap[ClockGate];
+}
+
+CONST CHAR16*
+StringFromImxClk (
+  IN  IMX_CLK   Value
+  )
+{
+  switch (Value) {
+  case IMX_CLK_NONE:
+    return L"(none)";
+  case IMX_OSC_CLK:
+    return L"OSC_CLK";
+  case IMX_PLL1_MAIN_CLK:
+    return L"PLL1_MAIN_CLK";
+  case IMX_PLL2_MAIN_CLK:
+    return L"PLL2_MAIN_CLK";
+  case IMX_PLL2_PFD0:
+    return L"PLL2_PFD0";
+  case IMX_PLL2_PFD1:
+    return L"PLL2_PFD1";
+  case IMX_PLL2_PFD2:
+    return L"PLL2_PFD2";
+  case IMX_PLL3_MAIN_CLK:
+    return L"PLL3_MAIN_CLK";
+  case IMX_PLL3_PFD0:
+    return L"PLL3_PFD0";
+  case IMX_PLL3_PFD1:
+    return L"PLL3_PFD1";
+  case IMX_PLL3_PFD2:
+    return L"PLL3_PFD2";
+  case IMX_PLL3_PFD3:
+    return L"PLL3_PFD3";
+  case IMX_PLL4_MAIN_CLK:
+    return L"PLL4_MAIN_CLK";
+  case IMX_PLL5_MAIN_CLK:
+    return L"PLL5_MAIN_CLK";
+  case IMX_CLK1:
+    return L"CLK1";
+  case IMX_CLK2:
+    return L"CLK2";
+  case IMX_PLL1_SW_CLK:
+    return L"PLL1_SW_CLK";
+  case IMX_STEP_CLK:
+    return L"STEP_CLK";
+  case IMX_PLL3_SW_CLK:
+    return L"PLL3_SW_CLK";
+  case IMX_AXI_ALT:
+    return L"AXI_ALT";
+  case IMX_AXI_CLK_ROOT:
+    return L"AXI_CLK_ROOT";
+  case IMX_PERIPH_CLK2:
+    return L"PERIPH_CLK2";
+  case IMX_PERIPH_CLK:
+    return L"PERIPH_CLK";
+  case IMX_PRE_PERIPH_CLK:
+    return L"PRE_PERIPH_CLK";
+  case IMX_PRE_PERIPH2_CLK:
+    return L"PRE_PERIPH2_CLK";
+  case IMX_PERIPH2_CLK:
+    return L"PERIPH2_CLK";
+  case IMX_ARM_CLK_ROOT:
+    return L"ARM_CLK_ROOT";
+  case IMX_MMDC_CH0_CLK_ROOT:
+    return L"MMDC_CH0_CLK_ROOT";
+  case IMX_MMDC_CH1_CLK_ROOT:
+    return L"MMDC_CH1_CLK_ROOT";
+  case IMX_AHB_CLK_ROOT:
+    return L"AHB_CLK_ROOT";
+  case IMX_IPG_CLK_ROOT:
+    return L"IPG_CLK_ROOT";
+  case IMX_PERCLK_CLK_ROOT:
+    return L"PERCLK_CLK_ROOT";
+  case IMX_USDHC1_CLK_ROOT:
+    return L"USDHC1_CLK_ROOT";
+  case IMX_USDHC2_CLK_ROOT:
+    return L"USDHC2_CLK_ROOT";
+  case IMX_USDHC3_CLK_ROOT:
+    return L"USDHC3_CLK_ROOT";
+  case IMX_USDHC4_CLK_ROOT:
+    return L"USDHC4_CLK_ROOT";
+  case IMX_SSI1_CLK_ROOT:
+    return L"SSI1_CLK_ROOT";
+  case IMX_SSI2_CLK_ROOT:
+    return L"SSI2_CLK_ROOT";
+  case IMX_SSI3_CLK_ROOT:
+    return L"SSI3_CLK_ROOT";
+  case IMX_GPU2D_AXI_CLK_ROOT:
+    return L"GPU2D_AXI_CLK_ROOT";
+  case IMX_GPU3D_AXI_CLK_ROOT:
+    return L"GPU3D_AXI_CLK_ROOT";
+  case IMX_PCIE_AXI_CLK_ROOT:
+    return L"PCIE_AXI_CLK_ROOT";
+  case IMX_VDO_AXI_CLK_ROOT:
+    return L"VDO_AXI_CLK_ROOT";
+  case IMX_IPU1_HSP_CLK_ROOT:
+    return L"IPU1_HSP_CLK_ROOT";
+  case IMX_GPU2D_CORE_CLK_ROOT:
+    return L"GPU2D_CORE_CLK_ROOT";
+  case IMX_ACLK_EIM_SLOW_CLK_ROOT:
+    return L"ACLK_EIM_SLOW_CLK_ROOT";
+  case IMX_ACLK_CLK_ROOT:
+    return L"ACLK_CLK_ROOT";
+  case IMX_ENFC_CLK_ROOT:
+    return L"ENFC_CLK_ROOT";
+  case IMX_GPU3D_CORE_CLK_ROOT:
+    return L"GPU3D_CORE_CLK_ROOT";
+  case IMX_GPU3D_SHADER_CLK_ROOT:
+    return L"GPU3D_SHADER_CLK_ROOT";
+  case IMX_VPU_AXI_CLK_ROOT:
+    return L"VPU_AXI_CLK_ROOT";
+  case IMX_IPU1_DI0_CLK_ROOT:
+    return L"IPU1_DI0_CLK_ROOT";
+  case IMX_IPU1_DI1_CLK_ROOT:
+    return L"IPU1_DI1_CLK_ROOT";
+  case IMX_LDB_DI0_SERIAL_CLK_ROOT:
+    return L"LDB_DI0_SERIAL_CLK_ROOT";
+  case IMX_LDB_DI0_IPU:
+    return L"LDB_DI0_IPU";
+  case IMX_LDB_DI1_SERIAL_CLK_ROOT:
+    return L"LDB_DI1_SERIAL_CLK_ROOT";
+  case IMX_LDB_DI1_IPU:
+    return L"LDB_DI1_IPU";
+  case IMX_SPDIF0_CLK_ROOT:
+    return L"SPDIF0_CLK_ROOT";
+  case IMX_SPDIF1_CLK_ROOT:
+    return L"SPDIF1_CLK_ROOT";
+  case IMX_ESAI_CLK_ROOT:
+    return L"ESAI_CLK_ROOT";
+  case IMX_HSI_TX_CLK_ROOT:
+    return L"HSI_TX_CLK_ROOT";
+  case IMX_CAN_CLK_ROOT:
+    return L"CAN_CLK_ROOT";
+  case IMX_ECSPI_CLK_ROOT:
+    return L"ECSPI_CLK_ROOT";
+  case IMX_UART_CLK_ROOT:
+    return L"UART_CLK_ROOT";
+  case IMX_VIDEO_27M_CLK_ROOT:
+    return L"VIDEO_27M_CLK_ROOT";
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  case IMX_IPU2_HSP_CLK_ROOT:
+    return L"IPU2_HSP_CLK_ROOT";
+  case IMX_IPU2_DI0_CLK_ROOT:
+    return L"IPU2_DI0_CLK_ROOT";
+  case IMX_IPU2_DI1_CLK_ROOT:
+    return L"IPU2_DI1_CLK_ROOT";
+#endif
+  default:
+    ASSERT (FALSE);
+    return L"[Invalid IMX_CLK value]";
+  }
+}
+
+IMX_CLK
+ImxpClkFromBypassClkSource (
+  IN  IMX_PLL_BYPASS_CLK_SRC    BypassClockSource
+  )
+{
+  switch (BypassClockSource) {
+  case IMX_PLL_BYPASS_CLK_SRC_REF_CLK_24M:
+    return IMX_OSC_CLK;
+  case IMX_PLL_BYPASS_CLK_SRC_CLK1:
+    return IMX_CLK1;
+  case IMX_PLL_BYPASS_CLK_SRC_CLK2:
+    return IMX_CLK2;
+  case IMX_PLL_BYPASS_CLK_SRC_XOR:
+  default:
+    ASSERT (FALSE);
+    return IMX_CLK_NONE;
+  }
+}
+
+/**
+  Configure the GPU clock tree so that GPU2D and GPU3D are clocked from
+  the AXI clock root and are within the allowed frequency range.
+
+  The GPU must be powered down, and GPU clocks must be gated when this
+  function is called.
+**/
+VOID
+ImxCcmConfigureGpuClockTree (
+  VOID
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+
+  CbcmrReg.gpu2d_axi_clk_sel = IMX_CCM_GPU2D_AXI_CLK_SEL_AXI;
+  CbcmrReg.gpu3d_axi_clk_sel = IMX_CCM_GPU3D_AXI_CLK_SEL_AXI;
+  CbcmrReg.gpu2d_core_clk_sel = IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0;
+  CbcmrReg.gpu3d_core_clk_sel = IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI;
+  CbcmrReg.gpu3d_shader_clk_sel = IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI;
+  CbcmrReg.gpu2d_core_clk_podf = 0;
+  CbcmrReg.gpu3d_core_podf = 0;
+  CbcmrReg.gpu3d_shader_podf = 0;
+
+  ImxpClkPwrCacheReset ();
+  MmioWrite32 ((UINTN) &pCcmRegisters->CBCMR, CbcmrReg.AsUint32);
+}
+
+/**
+  Configure all of DIx clock tree for both IPU1 and IPU2. For flexibility
+  purpose use PLL5 (PLL Video) as main reference clock. PLL 5 has flexible
+  divider making it easily configurable. Muxing and clock programming needs
+  when to be updated when supporting multiple display.
+**/
+VOID
+ImxCcmConfigureIPUDIxClockTree (
+  VOID
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CHSCCDR_REG         ChscddrReg;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  ChscddrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CHSCCDR);
+
+  // Setup muxing to pre-mux
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    ChscddrReg.ipu1_di0_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK;
+    ChscddrReg.ipu1_di1_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK;
+  } else {
+    ChscddrReg.ipu1_di0_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_PREMUX;
+    ChscddrReg.ipu1_di1_clk_sel = IMX_CHSCCDR_IPU1_DI1_CLK_SEL_PREMUX;
+  }
+  ChscddrReg.ipu1_di0_podf = IMX_CHSCCDR_IPU1_DI0_PODF_DIV_1;
+  ChscddrReg.ipu1_di1_podf = IMX_CHSCCDR_IPU1_DI1_PODF_DIV_1;
+  ChscddrReg.ipu1_di0_pre_clk_sel = IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL5;
+  ChscddrReg.ipu1_di1_pre_clk_sel = IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL5;
+
+  MmioWrite32 ((UINTN)&pCcmRegisters->CHSCCDR, ChscddrReg.AsUint32);
+}
+
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+/**
+    Configure both LDB0/1 to use PLL5 clock
+**/
+VOID
+ImxCcmConfigureIPULDBxClockTree (
+  VOID
+  )
+{
+  volatile IMX_CCM_REGISTERS *pCcmRegisters;
+  IMX_CCM_CS2CDR_REG Cs2cdrReg;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Cs2cdrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CS2CDR);
+
+  Cs2cdrReg.ldb_di0_clk_sel = 0x0;
+  Cs2cdrReg.ldb_di1_clk_sel = 0x0;
+
+  MmioWrite32 ((UINTN)&pCcmRegisters->CS2CDR, Cs2cdrReg.AsUint32);
+}
+#endif
+
+/**
+    Configure PLL 5 clock rate to the desired clock rate
+**/
+VOID
+ImxSetClockRatePLL5 (
+  IN  UINT32                                  ClockRate,
+  IN  IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT  PostDivSelect
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
+  UINT32                              Counter;
+  UINT32                              Denom;
+  UINT32                              DivSelect;
+  UINT32                              Numerator;
+  IMX_CCM_PLL_VIDEO_CTRL_REG          PllVideoCtrlClearReg;
+  IMX_CCM_PLL_VIDEO_CTRL_REG          PllVideoCtrlReg;
+  IMX_CCM_PLL_VIDEO_CTRL_REG          PllVideoCtrlSetReg;
+
+  // Use clock rate as Denom for simple fractional calculation
+  Denom = IMX_REF_CLK_24M_FREQ;
+  DivSelect = ClockRate / IMX_REF_CLK_24M_FREQ;
+  Numerator = ClockRate % IMX_REF_CLK_24M_FREQ;
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
+  PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
+
+  ASSERT (Numerator < Denom);
+  ASSERT ((DivSelect >= 27) && (DivSelect <= 54));
+
+  // PLL output frequency = Fref * (DIV_SELECT + NUM / DENOM)
+  PllVideoCtrlReg.DIV_SELECT = DivSelect;
+  PllVideoCtrlReg.POST_DIV_SELECT = PostDivSelect;
+
+  MmioWrite32 (
+    (UINTN)&pCcmAnalogRegisters->PLL_VIDEO, PllVideoCtrlReg.AsUint32);
+  MmioWrite32 (
+    (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_NUM, Numerator);
+  MmioWrite32 (
+    (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_DENOM, Denom);
+
+  PllVideoCtrlReg.AsUint32 = MmioRead32 (
+                               (UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
+
+  // Check to see if pll is locked, if not attempt to enable it
+  if (PllVideoCtrlReg.LOCK == 0) {
+    PllVideoCtrlClearReg.AsUint32 = 0;
+    PllVideoCtrlClearReg.POWERDOWN = 1;
+    MmioWrite32 (
+      (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_CLR,
+      PllVideoCtrlClearReg.AsUint32);
+    PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
+
+    PllVideoCtrlSetReg.AsUint32 = 0;
+    PllVideoCtrlSetReg.ENABLE = 1;
+    MmioWrite32 (
+      (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_SET,
+      PllVideoCtrlSetReg.AsUint32);
+    PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
+
+    PllVideoCtrlClearReg.AsUint32 = 0;
+    PllVideoCtrlClearReg.BYPASS = 1;
+    MmioWrite32 (
+      (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_CLR,
+      PllVideoCtrlClearReg.AsUint32);
+    PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
+
+    for (Counter = 0; Counter < 10000; Counter++) {
+      PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
+      if (PllVideoCtrlReg.LOCK == 1) {
+        DEBUG ((DEBUG_VERBOSE, "%a: PLL5 Video locked.\n", __FUNCTION__));
+        break;
+      }
+    }
+    if (PllVideoCtrlReg.LOCK == 0) {
+      DEBUG ((DEBUG_ERROR, "%a: PLL5 Video not locked.\n", __FUNCTION__));
+    }
+  }
+}
+
+EFI_STATUS
+ImxpGetPll2PfdClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  IN      IMX_PLL_PFD           PfdIndex,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters;
+  IMX_CLOCK_INFO                    ParentInfo;
+  IMX_CCM_PFD_528_REG               Pfd528Reg;
+  UINT32                            PfdFrac;
+  EFI_STATUS                        Status;
+
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
+  Pfd528Reg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PFD_528);
+  switch (PfdIndex) {
+  case IMX_PLL_PFD0:
+    PfdFrac = Pfd528Reg.PFD0_FRAC;
+    break;
+  case IMX_PLL_PFD1:
+    PfdFrac = Pfd528Reg.PFD1_FRAC;
+    break;
+  case IMX_PLL_PFD2:
+    PfdFrac = Pfd528Reg.PFD2_FRAC;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = ImxpGetClockInfo (Cache, IMX_PLL2_MAIN_CLK, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // The resulting frequency shall be 528*18/PFDn_FRAC
+  // where PFD0_FRAC is in the range 12-35.
+  ASSERT ((PfdFrac >= 12) && (PfdFrac <= 35));
+  ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * 18 / PfdFrac);
+  ClockInfo->Parent = IMX_PLL2_MAIN_CLK;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetAxiClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCDR_REG           CbcdrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
+
+  if (CbcdrReg.axi_sel == IMX_CCM_AXI_SEL_PERIPH_CLK) {
+    Parent = IMX_PERIPH_CLK;
+  } else {
+    ASSERT (CbcdrReg.axi_sel == IMX_CCM_AXI_SEL_AXI_ALT);
+    Parent = IMX_AXI_ALT;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.axi_podf);
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetGpu2dCoreClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  switch (CbcmrReg.gpu2d_core_clk_sel) {
+  case IMX_CCM_GPU2D_CORE_CLK_SEL_AXI:
+    Parent = IMX_AXI_CLK_ROOT;
+    break;
+  case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL3_SW:
+    Parent = IMX_PLL3_SW_CLK;
+    break;
+  case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0:
+    Parent = IMX_PLL2_PFD0;
+    break;
+  case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD2:
+    Parent = IMX_PLL2_PFD2;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu2d_core_clk_podf);
+  ClockInfo->Parent = Parent;
+  if (ClockInfo->Frequency > IMX_GPU2D_CORE_CLK_MAX) {
+    DEBUG ((
+            DEBUG_WARN,
+            "%a: GPU2D_CORE_CLK exceeds maximum. (Value = %d, Max = %d)\n",
+            __FUNCTION__,
+            ClockInfo->Frequency,
+            IMX_GPU2D_CORE_CLK_MAX));
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetGpu3dCoreClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  switch (CbcmrReg.gpu3d_core_clk_sel) {
+  case IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI:
+    Parent = IMX_MMDC_CH0_CLK_ROOT;
+    break;
+  case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL3_SW:
+    Parent = IMX_PLL3_SW_CLK;
+    break;
+  case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD1:
+    Parent = IMX_PLL2_PFD1;
+    break;
+  case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD2:
+    Parent = IMX_PLL2_PFD2;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu3d_core_podf);
+  ClockInfo->Parent = Parent;
+  if (ClockInfo->Frequency > IMX_GPU3D_CORE_CLK_MAX) {
+    DEBUG ((
+            DEBUG_WARN,
+            "%a: GPU3D_CORE_CLK exceeds maximum. (Value = %d, Max = %d)\n",
+            __FUNCTION__,
+            ClockInfo->Frequency,
+            IMX_GPU3D_CORE_CLK_MAX));
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetGpu3dShaderClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  switch (CbcmrReg.gpu3d_shader_clk_sel) {
+  case IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI:
+    Parent = IMX_MMDC_CH0_CLK_ROOT;
+    break;
+  case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_SW:
+    Parent = IMX_PLL3_SW_CLK;
+    break;
+  case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL2_PFD1:
+    Parent = IMX_PLL2_PFD1;
+    break;
+  case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_PFD0:
+    Parent = IMX_PLL3_PFD0;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu3d_shader_podf);
+  ClockInfo->Parent = Parent;
+
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  if (ClockInfo->Frequency > IMX_GPU3D_SHADER_CLK_MAX) {
+    DEBUG ((
+            DEBUG_WARN,
+            "%a: GPU3D_SHADER_CLK exceeds maximum. (Value = %d, Max = %d)",
+            __FUNCTION__,
+            ClockInfo->Frequency,
+            IMX_GPU3D_SHADER_CLK_MAX));
+  }
+#endif
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPeriphClk2Info (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS *pCcmRegisters;
+  IMX_CCM_CBCDR_REG CbcdrReg;
+  IMX_CCM_CBCMR_REG CbcmrReg;
+  IMX_CLK Parent;
+  IMX_CLOCK_INFO ParentInfo;
+  EFI_STATUS Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  switch (CbcmrReg.periph_clk2_sel) {
+  case IMX_CCM_PERIPH_CLK2_SEL_PLL3_SW_CLK:
+    Parent = IMX_PLL3_SW_CLK;
+    break;
+  case IMX_CCM_PERIPH_CLK2_SEL_OSC_CLK:
+    Parent = IMX_OSC_CLK;
+    break;
+  case IMX_CCM_PERIPH_CLK2_SEL_PLL2:
+    Parent = IMX_PLL2_MAIN_CLK;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.periph_clk2_podf);
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPeriphClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCDR_REG           CbcdrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
+
+  // NOTE: periph_clk_sel is OR'd with PLL_bypass_en2 (from jtag) to
+  //       produce the input value to the MUX. We assume PLL_bypass_en2 is 0.
+  if (CbcdrReg.periph_clk_sel == 0) {
+    Parent = IMX_PRE_PERIPH_CLK;
+  } else {
+    ASSERT (CbcdrReg.periph_clk_sel == 1);
+    Parent = IMX_PERIPH_CLK2;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.mmdc_ch0_axi_podf);
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetMmdcCh0ClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCDR_REG           CbcdrReg;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Status = ImxpGetClockInfo (Cache, IMX_PERIPH_CLK, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.mmdc_ch0_axi_podf);
+  ClockInfo->Parent = IMX_PERIPH_CLK;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetGpu2dAxiClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  if (CbcmrReg.gpu2d_axi_clk_sel == IMX_CCM_GPU2D_AXI_CLK_SEL_AXI) {
+    Parent = IMX_AXI_CLK_ROOT;
+  } else {
+    ASSERT (CbcmrReg.gpu2d_axi_clk_sel == IMX_CCM_GPU2D_AXI_CLK_SEL_AHB);
+    Parent = IMX_AHB_CLK_ROOT;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency;
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetGpu3dAxiClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  if (CbcmrReg.gpu3d_axi_clk_sel == IMX_CCM_GPU3D_AXI_CLK_SEL_AXI) {
+    Parent = IMX_AXI_CLK_ROOT;
+  } else {
+    ASSERT (CbcmrReg.gpu3d_axi_clk_sel == IMX_CCM_GPU3D_AXI_CLK_SEL_AHB);
+    Parent = IMX_AHB_CLK_ROOT;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency;
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+VOID
+ImxEnableGpuVpuPowerDomain (
+  VOID
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pAnalogRegisters;
+  volatile IMX_GPC_REGISTERS          *pGpcRegisters;
+  volatile IMX_GPC_PGC_REGISTERS      *pGpuPgcRegisters;
+  IMX_GPC_CNTR_REG                    GpcCntrReg;
+  IMX_PMU_REG_CORE_REG                PmuCoreReg;
+  IMX_GPC_PGC_PUPSCR_REG              PupscrReg;
+
+  pAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
+  pGpcRegisters = (IMX_GPC_REGISTERS *) IMX_GPC_BASE;
+  pGpuPgcRegisters = &pGpcRegisters->PGC_GPU;
+
+  // Configure GPC/PGC PUPSCR Register SW2ISO bits
+  PupscrReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->PUPSCR);
+  PupscrReg.SW = IMX_GPC_PGC_PUPSCR_SW_DEFAULT;
+  PupscrReg.SW2ISO = IMX_GPC_PGC_PUPSCR_SW2ISO_DEFAULT;
+  MmioWrite32 ((UINTN) &pGpuPgcRegisters->PUPSCR, PupscrReg.AsUint32);
+
+  // Turn on LDO_PU to 1.250V
+  PmuCoreReg.AsUint32 = 0;
+  PmuCoreReg.REG1_TARG = 0x1f;
+  MmioWrite32 ((UINTN) &pAnalogRegisters->PMU_REG_CORE_CLR, PmuCoreReg.AsUint32);
+  PmuCoreReg.REG1_TARG = 22;
+  MmioWrite32 ((UINTN) &pAnalogRegisters->PMU_REG_CORE_SET, PmuCoreReg.AsUint32);
+  MicroSecondDelay (100);
+
+  // Assert power up request
+  GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
+  GpcCntrReg.gpu_vpu_pdn_req = 0;
+  GpcCntrReg.gpu_vpu_pup_req = 1;
+  MmioWrite32 ((UINTN) &pGpcRegisters->CNTR, GpcCntrReg.AsUint32);
+
+  // Wait for power up request to complete
+  do {
+    GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
+  } while (GpcCntrReg.gpu_vpu_pup_req != 0);
+}
+
+VOID
+ImxDisableGpuVpuPowerDomain (
+  VOID
+  )
+{
+  volatile IMX_GPC_REGISTERS      *pGpcRegisters;
+  volatile IMX_GPC_PGC_REGISTERS  *pGpuPgcRegisters;
+  IMX_GPC_PGC_PGCR_REG            CtrlReg;
+  IMX_GPC_CNTR_REG                GpcCntrReg;
+  IMX_GPC_PGC_PDNSCR_REG          PdnscrReg;
+
+  pGpcRegisters = (IMX_GPC_REGISTERS *) IMX_GPC_BASE;
+  pGpuPgcRegisters = &pGpcRegisters->PGC_GPU;
+
+  // Configure GPC/PGC PDNSCR Register ISO bits
+  PdnscrReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->PDNSCR);
+  PdnscrReg.ISO = IMX_GPC_PGC_PDNSCR_ISO_DEFAULT;
+  PdnscrReg.ISO2SW = IMX_GPC_PGC_PDNSCR_ISO2SW_DEFAULT;
+  MmioWrite32 ((UINTN) &pGpuPgcRegisters->PDNSCR, PdnscrReg.AsUint32);
+
+  // Configure GPC/PGC CTRL[PCR] bit to allow power down of the blocks
+  CtrlReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->CTRL);
+  CtrlReg.PCR = 1;    // Enable powering down of the blocks
+  MmioWrite32 ((UINTN) &pGpuPgcRegisters->CTRL, CtrlReg.AsUint32);
+
+  // Assert power down request
+  GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
+  GpcCntrReg.gpu_vpu_pdn_req = 1;
+  GpcCntrReg.gpu_vpu_pup_req = 0;
+  MmioWrite32 ((UINTN) &pGpcRegisters->CNTR, GpcCntrReg.AsUint32);
+
+  // Wait for power down request to complete
+  do {
+    GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
+  } while (GpcCntrReg.gpu_vpu_pdn_req != 0);
+}
+
+EFI_STATUS
+ImxpGetClockInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  IN      IMX_CLK               ClockId,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  UINTN       CacheValidBits;
+  EFI_STATUS  Status;
+
+  ASSERT (ClockId < ARRAYSIZE (Cache->Table));
+
+  // First try to satisfy from cache
+  CacheValidBits = Cache->Valid[ClockId / _BITS_PER_UINTN];
+  if (CacheValidBits & (1 << (ClockId % _BITS_PER_UINTN))) {
+    *ClockInfo = Cache->Table[ClockId];
+    return EFI_SUCCESS;
+  }
+
+  switch (ClockId) {
+  case IMX_OSC_CLK:
+    ImxpGetOsc24ClkInfo (ClockInfo);
+    Status = EFI_SUCCESS;
+    break;
+  case IMX_PLL1_MAIN_CLK:
+    Status = ImxpGetPll1MainClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_PLL2_MAIN_CLK:
+    Status = ImxpGetPll2MainClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_PLL2_PFD0:
+    Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD0, ClockInfo);
+    break;
+  case IMX_PLL2_PFD1:
+    Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD1, ClockInfo);
+    break;
+  case IMX_PLL2_PFD2:
+    Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD2, ClockInfo);
+    break;
+  case IMX_PLL3_MAIN_CLK:
+    Status = ImxpGetPll3MainClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_PLL3_PFD0:
+    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD0, ClockInfo);
+    break;
+  case IMX_PLL3_PFD1:
+    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD1, ClockInfo);
+    break;
+  case IMX_PLL3_PFD2:
+    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD2, ClockInfo);
+    break;
+  case IMX_PLL3_PFD3:
+    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD3, ClockInfo);
+    break;
+  case IMX_PLL3_SW_CLK:
+    Status = ImxpGetPll3SwClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_AXI_CLK_ROOT:
+    Status = ImxpGetAxiClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_PERIPH_CLK2:
+    Status = ImxpGetPeriphClk2Info (Cache, ClockInfo);
+    break;
+  case IMX_PERIPH_CLK:
+    Status = ImxpGetPeriphClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_PRE_PERIPH_CLK:
+    Status = ImxpGetPrePeriphClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_ARM_CLK_ROOT:
+    Status = ImxpGetArmClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_MMDC_CH0_CLK_ROOT:
+    Status = ImxpGetMmdcCh0ClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_AHB_CLK_ROOT:
+    Status = ImxpGetAhbClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_IPG_CLK_ROOT:
+    Status = ImxpGetIpgClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_GPU2D_AXI_CLK_ROOT:
+    Status = ImxpGetGpu2dAxiClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_GPU3D_AXI_CLK_ROOT:
+    Status = ImxpGetGpu3dAxiClkRootInfo (Cache, ClockInfo);
+    break;
+  case IMX_GPU2D_CORE_CLK_ROOT:
+    Status = ImxpGetGpu2dCoreClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_GPU3D_CORE_CLK_ROOT:
+    Status = ImxpGetGpu3dCoreClkInfo (Cache, ClockInfo);
+    break;
+  case IMX_GPU3D_SHADER_CLK_ROOT:
+    Status = ImxpGetGpu3dShaderClkInfo (Cache, ClockInfo);
+    break;
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Update the cache
+  Cache->Table[ClockId] = *ClockInfo;
+  Cache->Valid[ClockId / _BITS_PER_UINTN] |= (1 << (ClockId % _BITS_PER_UINTN));
+  return EFI_SUCCESS;
+}
+
+/**
+  Power on and clock the GPU2D/GPU3D blocks.
+
+  Follow the datasheet recommended sequence for clocking and powering:
+    Gate clocks -> unpower module ->
+    configure muxes/dividers -> power module -> Ungate clocks
+**/
+EFI_STATUS
+ImxClkPwrGpuEnable (
+  VOID
+  )
+{
+#if !defined(MDEPKG_NDEBUG)
+  // Precondition: clock and power should be disabled
+  ASSERT (ImxClkPwrGetClockGate (IMX_GPU3D_CLK_ENABLE) == IMX_CLOCK_GATE_STATE_OFF);
+  ASSERT (ImxClkPwrGetClockGate (IMX_GPU2D_CLK_ENABLE) == IMX_CLOCK_GATE_STATE_OFF);
+  ASSERT (ImxClkPwrGetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE) == IMX_CLOCK_GATE_STATE_OFF);
+#endif
+
+  // Ensure clocks are gated
+  ImxClkPwrSetClockGate (IMX_GPU3D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_OFF);
+  ImxClkPwrSetClockGate (IMX_GPU2D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_OFF);
+  ImxClkPwrSetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
+                         IMX_CLOCK_GATE_STATE_OFF);
+
+  // Ensure GPU powered down (GPU should be powered down anyway)
+  ImxDisableGpuVpuPowerDomain ();
+
+  // Configure clock muxes and dividers for GPU3D, GPU2D, and OpenVG
+  ImxCcmConfigureGpuClockTree ();
+
+  // Power on the GPU
+  ImxEnableGpuVpuPowerDomain ();
+
+  // Ungate the GPU clocks
+  ImxClkPwrSetClockGate (IMX_GPU3D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_ON);
+  ImxClkPwrSetClockGate (IMX_GPU2D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_ON);
+  ImxClkPwrSetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
+                         IMX_CLOCK_GATE_STATE_ON);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxClkPwrIpuDIxEnable (
+  VOID
+  )
+{
+  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+  ImxClkPwrSetClockGate (IMX_IPU1_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  ImxClkPwrSetClockGate (IMX_IPU2_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+  ImxClkPwrSetClockGate (IMX_IPU2_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+#endif
+  ImxCcmConfigureIPUDIxClockTree();
+  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON);
+
+  // Setup PLL to 65MHz as expected from UBOOT although transition
+  // might be so fast that UBOOT screen would not be displayed
+  ImxSetPll5ReferenceRate (65000000);
+  return EFI_SUCCESS;
+}
+
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+/**
+    Setup the clock tree for LDB0/1
+**/
+EFI_STATUS
+ImxClkPwrIpuLDBxEnable (
+  VOID
+  )
+{
+  ImxClkPwrSetClockGate (IMX_LDB_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+  ImxClkPwrSetClockGate (IMX_LDB_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+  ImxCcmConfigureIPULDBxClockTree();
+  ImxClkPwrSetClockGate (IMX_LDB_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON);
+  ImxClkPwrSetClockGate (IMX_LDB_DI1_CLK_ENABLE, IMX_CCM_CCGR_ON);
+
+  return EFI_SUCCESS;
+}
+#endif
+
+/**
+    Configure PLL5 to the desired clock rate for all Display Interface (DI).
+    Currently only support one display to IPU1 DI0.
+**/
+EFI_STATUS
+ImxSetPll5ReferenceRate (
+  IN  UINT32  ClockRate
+  )
+{
+  volatile IMX_CCM_REGISTERS              *pCcmRegisters;
+  IMX_CCM_CHSCCDR_REG                     ChscddrReg;
+  UINT32                                  DxPodfDivider;
+  BOOLEAN                                 FoundConfig;
+  IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT  postDivSelect[3];
+  UINT32                                  PostDivSelectCount;
+  UINT32                                  PostDivSelectValue[3];
+  UINT32                                  TargetFreq;
+
+  FoundConfig = FALSE;
+  PostDivSelectValue[0] = 1;
+  PostDivSelectValue[1] = 2;
+  PostDivSelectValue[2] = 4;
+  postDivSelect[0] = IMX_POST_DIV_SELECT_DIVIDE_1;
+  postDivSelect[1] = IMX_POST_DIV_SELECT_DIVIDE_2;
+  postDivSelect[2] = IMX_POST_DIV_SELECT_DIVIDE_4;
+
+  for (PostDivSelectCount = 0;
+       PostDivSelectCount < ARRAYSIZE (PostDivSelectValue);
+       ++PostDivSelectCount) {
+    for (DxPodfDivider = 1; DxPodfDivider < 9; ++DxPodfDivider) {
+      TargetFreq = DxPodfDivider * ClockRate * PostDivSelectValue[PostDivSelectCount];
+      // The valid range for PPL loop divider is 27-54 so target freq needs
+      //   to fit within the valid range.
+      if ((TargetFreq >= PLL5_MIN_FREQ) &&
+          (TargetFreq <= PLL5_MAX_FREQ)) {
+        FoundConfig = TRUE;
+        break;
+      }
+    }
+
+    if (FoundConfig == TRUE) {
+      break;
+    }
+  }
+
+  if (FoundConfig == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: ClockRate %d\n", __FUNCTION__, ClockRate));
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+  DEBUG ((
+          DEBUG_INFO,
+          "%a: PLL 5 setting (%d) Target Freq %d Divider %d PostDiv %d\n",
+          __FUNCTION__,
+          ClockRate,
+          TargetFreq,
+          DxPodfDivider,
+          PostDivSelectValue[PostDivSelectCount]
+        ));
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  ChscddrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CHSCCDR);
+  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+  ImxClkPwrSetClockGate (IMX_IPU1_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  ImxClkPwrSetClockGate (IMX_IPU2_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+  ImxClkPwrSetClockGate (IMX_IPU2_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
+#endif
+  ChscddrReg.ipu1_di0_podf = DxPodfDivider - 1;
+  ChscddrReg.ipu1_di1_podf = DxPodfDivider - 1;
+  MmioWrite32 ((UINTN)&pCcmRegisters->CHSCCDR, ChscddrReg.AsUint32);
+
+  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON);
+  ImxSetClockRatePLL5 (TargetFreq, postDivSelect[PostDivSelectCount]);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxClkPwrClkOut1Enable (
+  IN  IMX_CLK   Clock,
+  IN  UINT32    Divider
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CCOSR_REG           CcosrReg;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  if ((Divider < 1) || (Divider > 8)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CcosrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCOSR);
+  switch (Clock) {
+  case IMX_OSC_CLK:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_OSC_CLK;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  case IMX_PLL2_MAIN_CLK:
+    CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_PLL2_MAIN_CLK_2;
+    CcosrReg.CLKO1_DIV = Divider - 1;
+    CcosrReg.CLKO1_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1;
+    break;
+
+  case IMX_AXI_CLK_ROOT:
+    CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_AXI_CLK_ROOT;
+    CcosrReg.CLKO1_DIV = Divider - 1;
+    CcosrReg.CLKO1_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1;
+    break;
+
+  case IMX_IPG_CLK_ROOT:
+    CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_IPG_CLK_ROOT;
+    CcosrReg.CLKO1_DIV = Divider - 1;
+    CcosrReg.CLKO1_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1;
+    break;
+
+  case IMX_GPU2D_AXI_CLK_ROOT:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU2D_AXI_CLK_ROOT;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  case IMX_GPU3D_AXI_CLK_ROOT:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_AXI_CLK_ROOT;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  case IMX_GPU2D_CORE_CLK_ROOT:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU2D_CORE_CLK_ROOT;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  case IMX_GPU3D_CORE_CLK_ROOT:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_CORE_CLK_ROOT;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  case IMX_GPU3D_SHADER_CLK_ROOT:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_SHADER_CLK_ROOT;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  case IMX_UART_CLK_ROOT:
+    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_UART_CLK_ROOT;
+    CcosrReg.CLKO2_DIV = Divider - 1;
+    CcosrReg.CLKO2_EN = 1;
+    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  MmioWrite32 ((UINTN) &pCcmRegisters->CCOSR, CcosrReg.AsUint32);
+  return EFI_SUCCESS;
+}
+
+VOID
+ImxClkPwrClkOut1Disable (
+  VOID
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CCOSR_REG           CcosrReg;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CcosrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCOSR);
+  CcosrReg.CLKO1_EN = 0;
+  CcosrReg.CLKO2_EN = 0;
+  MmioWrite32 ((UINTN) &pCcmRegisters->CCOSR, CcosrReg.AsUint32);
+}
+
+EFI_STATUS
+ImxClkPwrValidateClocks (
+  VOID
+  )
+{
+  IMX_CLOCK_INFO  ActualInfo;
+  UINT32          i;
+  BOOLEAN         Invalid;
+  EFI_STATUS      Status;
+
+  Invalid = FALSE;
+  for (i = 0; i < ARRAYSIZE (ExpectedClocks); ++i) {
+    DEBUG ((
+            DEBUG_INFO,
+            "%a: Validating clock %s. Expecting: Frequency = %d (%d Mhz), Parent = %s\n",
+            __FUNCTION__,
+            StringFromImxClk (ExpectedClocks[i].Clock),
+            ExpectedClocks[i].Info.Frequency,
+            ExpectedClocks[i].Info.Frequency / 1000000,
+            StringFromImxClk (ExpectedClocks[i].Info.Parent)
+          ));
+    Status = ImxClkPwrGetClockInfo (ExpectedClocks[i].Clock, &ActualInfo);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+              DEBUG_ERROR,
+              "%a: Failed to get clock info. (Clock = %s, Status = 0x%x)\n",
+              __FUNCTION__,
+              StringFromImxClk (ExpectedClocks[i].Clock),
+              Status
+            ));
+      return Status;
+    }
+    if ((ActualInfo.Frequency != ExpectedClocks[i].Info.Frequency) ||
+        (ActualInfo.Parent != ExpectedClocks[i].Info.Parent)) {
+      DEBUG ((
+              DEBUG_ERROR,
+              "%a: Clock settings do not match expected! Clock = %s (Expected, Actual) "
+              "Frequency: %d, %d. Parent: %s, %s\n",
+              __FUNCTION__,
+              StringFromImxClk (ExpectedClocks[i].Clock),
+              ExpectedClocks[i].Info.Frequency,
+              ActualInfo.Frequency,
+              StringFromImxClk (ExpectedClocks[i].Info.Parent),
+              StringFromImxClk (ActualInfo.Parent)
+            ));
+      Invalid = TRUE;
+    }
+  }
+
+  return Invalid ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+}
+
+/**
+  Reset/invalidate the clock tree cache.
+
+  The clock tree cache must be invalidated whenever the clock tree is modified,
+  e.g. when changing PLL configuration, clock mux, or divider.
+
+**/
+VOID
+ImxpClkPwrCacheReset (
+  VOID
+  )
+{
+  SetMem (&mImxpClockPwrCache.Valid, sizeof (mImxpClockPwrCache.Valid), 0);
+}
+
+/**
+  Configure clock gating for the specified clock signal.
+
+  @param[in]  ClockGate   Specific clock signal to configure.
+  @param[in]  State       State to set the clock signal to.
+**/
+VOID
+ImxClkPwrSetClockGate (
+  IN  IMX_CLK_GATE          ClockGate,
+  IN  IMX_CLOCK_GATE_STATE  State
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  UINTN                       EndBit;
+  IMX_CCGR_INDEX              Index;
+  UINTN                       StartBit;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+
+  // Extract register index
+  Index = ImxpCcgrIndexFromClkGate (ClockGate);
+  StartBit = Index.GateNumber * 2;
+  EndBit = StartBit + 1;
+
+  MmioBitFieldWrite32 (
+    (UINTN) &pCcmRegisters->CCGR[Index.RegisterIndex],
+    StartBit,
+    EndBit,
+    State);
+}
+
+/**
+  Determine if gating TZASC1_IPG_MASTER_CLK should be skipped.
+ **/
+BOOLEAN
+ImxClkPwrShouldSkipTZASC1 (
+  VOID
+  )
+{
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  IMX_IOMUXC_GPR_REGISTERS  *IoMuxMmioBasePtr;
+  UINTN                     IomuxGPR9;
+#endif
+  BOOLEAN                   Skip;
+
+  Skip = FALSE;
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  IoMuxMmioBasePtr = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
+
+  IomuxGPR9 = MmioRead32 ((UINTN) &IoMuxMmioBasePtr->GPR9);
+  if (IomuxGPR9 & IMX_IOMUXC_TZASC1_BYP) {
+    // TZASC-1 is active.
+    Skip = TRUE;
+  }
+#endif
+
+  return Skip;
+}
+
+/**
+  Determine if a clock gate should be skipped
+
+  @param[in]  ClockGate   Specific clock signal to configure.
+ **/
+BOOLEAN
+ImxClkPwrShouldSkipGate (
+  IN  IMX_CLK_GATE  ClockGate
+  )
+{
+  switch (ClockGate) {
+  case IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE:
+    return ImxClkPwrShouldSkipTZASC1 ();
+
+  default:
+    return FALSE;
+  }
+}
+
+/**
+  Set multiple clock signals to a given state.
+
+  @param[in]  ClockGateList   Pointer to list of possible clock signals.
+  @param[in]  ClockGateCount  Number of clock signals to gate.
+  @param[in]  State           State to set the clock signal to.
+**/
+VOID
+ImxClkPwrSetClockGates (
+  CONST IMX_CLK_GATE *ClockGateList,
+  UINTN ClockGateCount,
+  IMX_CLOCK_GATE_STATE State
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  UINTN                       i;
+  IMX_CCGR_INDEX              Index;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+
+  // Read all CCGR registers to local copy
+  UINT32 ccgrRegisters[ARRAYSIZE (pCcmRegisters->CCGR)];
+  for (i = 0; i < ARRAYSIZE (ccgrRegisters); ++i) {
+    ccgrRegisters[i] = MmioRead32 ((UINTN) &pCcmRegisters->CCGR[i]);
+  }
+
+  // Compute new CCGR register values
+  for (i = 0; i < ClockGateCount; ++i) {
+    if (ImxClkPwrShouldSkipGate (ClockGateList[i])) {
+      continue;
+    }
+
+    Index = ImxpCcgrIndexFromClkGate (ClockGateList[i]);
+    ccgrRegisters[Index.RegisterIndex] =
+      (ccgrRegisters[Index.RegisterIndex] & ~(0x3 << (2 * Index.GateNumber))) |
+      (State << (2 * Index.GateNumber));
+  }
+
+  // Write back to registers
+  for (i = 0; i < ARRAYSIZE (ccgrRegisters); ++i) {
+    MmioWrite32 ((UINTN) &pCcmRegisters->CCGR[i], ccgrRegisters[i]);
+  }
+}
+
+/**
+  Get the current clock gating setting for the specified clock gate.
+
+  @param[in]  ClockGate     Specific clock signal to fetch clock gate info from.
+**/
+IMX_CLOCK_GATE_STATE
+ImxClkPwrGetClockGate (
+  IN  IMX_CLK_GATE  ClockGate
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  UINTN                       EndBit;
+  IMX_CCGR_INDEX              Index;
+  UINTN                       StartBit;
+  UINT32                      Value;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Index = ImxpCcgrIndexFromClkGate (ClockGate);
+  StartBit = Index.GateNumber * 2;
+  EndBit = StartBit + 1;
+
+  Value = MmioBitFieldRead32 (
+            (UINTN) &pCcmRegisters->CCGR[Index.RegisterIndex],
+            StartBit,
+            EndBit);
+
+  if ((Value != IMX_CCM_CCGR_OFF) &&
+      (Value != IMX_CCM_CCGR_ON_RUN) &&
+      (Value != IMX_CCM_CCGR_ON)) {
+    ASSERT (FALSE);
+  }
+
+  return (IMX_CLOCK_GATE_STATE) Value;
+}
+
+EFI_STATUS
+ImxpGetPll3MainClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
+  IMX_CLK                             Parent;
+  IMX_CLOCK_INFO                      ParentInfo;
+  IMX_CCM_ANALOG_PLL_USB1_REG         PllUsb1Reg;
+  EFI_STATUS                          Status;
+
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
+  PllUsb1Reg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_USB1);
+  Parent = ImxpClkFromBypassClkSource (PllUsb1Reg.BYPASS_CLK_SRC);
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (PllUsb1Reg.DIV_SELECT == 0) {
+    ClockInfo->Frequency = ParentInfo.Frequency * 20;
+  } else {
+    ClockInfo->Frequency = ParentInfo.Frequency * 22;
+  }
+
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPll3PfdClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  IN      IMX_PLL_PFD           PfdIndex,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
+  IMX_CLOCK_INFO                      ParentInfo;
+  IMX_CCM_PFD_480_REG                 Pfd480Reg;
+  UINT32                              PfdFrac;
+  EFI_STATUS                          Status;
+
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
+  Pfd480Reg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PFD_480);
+  switch (PfdIndex) {
+  case IMX_PLL_PFD0:
+    PfdFrac = Pfd480Reg.PFD0_FRAC;
+    break;
+  case IMX_PLL_PFD1:
+    PfdFrac = Pfd480Reg.PFD1_FRAC;
+    break;
+  case IMX_PLL_PFD2:
+    PfdFrac = Pfd480Reg.PFD2_FRAC;
+    break;
+  case IMX_PLL_PFD3:
+    PfdFrac = Pfd480Reg.PFD3_FRAC;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = ImxpGetClockInfo (Cache, IMX_PLL3_MAIN_CLK, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // The resulting frequency shall be 480*18/PFDn_FRAC
+  // where PFD0_FRAC is in the range 12-35.
+  ASSERT ((PfdFrac >= 12) && (PfdFrac <= 35));
+  ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * 18 / PfdFrac);
+  ClockInfo->Parent = IMX_PLL3_MAIN_CLK;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPll3SwClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CCSR_REG            CcsrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CcsrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCSR);
+  if (CcsrReg.pll3_sw_clk_sel == IMX_CCM_PLL3_SW_CLK_SEL_PLL3_MAIN_CLK) {
+    Parent = IMX_PLL3_MAIN_CLK;
+  } else {
+    ASSERT (CcsrReg.pll3_sw_clk_sel == IMX_CCM_PLL3_SW_CLK_SEL_PLL3_BYPASS_CLK);
+    ASSERT (!"Not implemented");
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ClockInfo->Frequency = ParentInfo.Frequency;
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPll1MainClkInfo  (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
+  IMX_CLK                             Parent;
+  IMX_CLOCK_INFO                      ParentInfo;
+  IMX_CCM_ANALOG_PLL_ARM_REG          PllArmReg;
+  EFI_STATUS                          Status;
+
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
+  PllArmReg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PLL_ARM);
+  Parent = ImxpClkFromBypassClkSource (PllArmReg.BYPASS_CLK_SRC);
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (PllArmReg.BYPASS != 0) {
+    ClockInfo->Frequency = ParentInfo.Frequency;
+    ClockInfo->Parent = Parent;
+    return EFI_SUCCESS;
+  }
+
+  ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * PllArmReg.DIV_SELECT / 2);
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPll2MainClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
+  IMX_CLK                             Parent;
+  IMX_CLOCK_INFO                      ParentInfo;
+  IMX_CCM_ANALOG_PLL_SYS_REG          PllSysReg;
+  EFI_STATUS                          Status;
+
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
+  PllSysReg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PLL_SYS);
+  // Determine the reference clock source
+  Parent = ImxpClkFromBypassClkSource (PllSysReg.BYPASS_CLK_SRC);
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (PllSysReg.BYPASS != 0) {
+    ClockInfo->Frequency = ParentInfo.Frequency;
+    ClockInfo->Parent = Parent;
+    return EFI_SUCCESS;
+  }
+
+  if (PllSysReg.DIV_SELECT == 0) {
+    ClockInfo->Frequency = ParentInfo.Frequency * 20;
+  } else {
+    ASSERT (PllSysReg.DIV_SELECT == 1);
+    ClockInfo->Frequency = ParentInfo.Frequency * 22;
+  }
+
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetArmClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CACRR_REG           CacrrReg;
+  IMX_CLOCK_INFO              Pll1Info;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Status = ImxpGetClockInfo (Cache, IMX_PLL1_MAIN_CLK, &Pll1Info);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CacrrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CACRR);
+  ClockInfo->Frequency = Pll1Info.Frequency / (1 + CacrrReg.arm_podf);
+  ClockInfo->Parent = IMX_PLL1_MAIN_CLK;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetPrePeriphClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCMR_REG           CbcmrReg;
+  IMX_CLK                     Parent;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
+  switch (CbcmrReg.pre_periph_clk_sel) {
+  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2:
+    Parent = IMX_PLL2_MAIN_CLK;
+    break;
+  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2:
+    Parent = IMX_PLL2_PFD2;
+    break;
+  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD0:
+    Parent = IMX_PLL2_PFD0;
+    break;
+  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2:
+    Parent = IMX_PLL2_PFD2;
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (CbcmrReg.pre_periph_clk_sel == IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2) {
+    ClockInfo->Frequency = ParentInfo.Frequency / 2;
+  } else {
+    ClockInfo->Frequency = ParentInfo.Frequency;
+  }
+
+  ClockInfo->Parent = Parent;
+  return EFI_SUCCESS;
+}
+
+VOID
+ImxpGetOsc24ClkInfo (
+  OUT IMX_CLOCK_INFO  *ClockInfo
+  )
+{
+  ClockInfo->Frequency = IMX_REF_CLK_24M_FREQ;
+  ClockInfo->Parent = IMX_CLK_NONE;
+}
+
+EFI_STATUS
+ImxpGetAhbClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCDR_REG           CbcdrReg;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Status = ImxpGetClockInfo (Cache, IMX_PERIPH_CLK, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.ahb_podf);
+  ClockInfo->Parent = IMX_PERIPH_CLK;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxpGetIpgClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
+  IMX_CCM_CBCDR_REG           CbcdrReg;
+  IMX_CLOCK_INFO              ParentInfo;
+  EFI_STATUS                  Status;
+
+  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Status = ImxpGetClockInfo (Cache, IMX_AHB_CLK_ROOT, &ParentInfo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
+  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.ipg_podf);
+  ClockInfo->Parent = IMX_AHB_CLK_ROOT;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ImxClkPwrGetClockInfo (
+  IN  IMX_CLK         ClockId,
+  OUT IMX_CLOCK_INFO  *ClockInfo
+  )
+{
+  return ImxpGetClockInfo (&mImxpClockPwrCache, ClockId, ClockInfo);
+}
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
new file mode 100644
index 000000000000..5e4603131471
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
@@ -0,0 +1,46 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMX6ClkPwrLib
+  FILE_GUID                      = 8DB4B460-9201-435A-B86A-24B58CED9A9E
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = iMX6ClkPwrLib
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  iMXIoMuxLib
+  IoLib
+  TimerLib
+
+[Sources.common]
+  iMX6ClkPwr.c
+
+[FeaturePcd]
+  giMX6TokenSpaceGuid.PcdLvdsEnable
+
+[FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
new file mode 100644
index 000000000000..2de1f62c7740
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
@@ -0,0 +1,221 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_CLK_PWR_PRIVATE_H_
+#define _IMX6_CLK_PWR_PRIVATE_H_
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif // ARRAYSIZE
+
+#define _BITS_PER_UINTN (8 * sizeof(UINTN))
+
+typedef enum {
+  IMX_PLL_PFD0,
+  IMX_PLL_PFD1,
+  IMX_PLL_PFD2,
+  IMX_PLL_PFD3,
+} IMX_PLL_PFD;
+
+typedef struct {
+  IMX_CLK Clock;
+  IMX_CLOCK_INFO Info;
+} IMX_CLOCK_CONTEXT;
+
+typedef struct {
+  UINT16 RegisterIndex;   // Register index (0-6)
+  UINT16 GateNumber;      // Gate number within register (0-15)
+} IMX_CCGR_INDEX;
+
+typedef struct {
+  UINTN Valid[(IMX_CLK_MAX + _BITS_PER_UINTN) / _BITS_PER_UINTN];
+  IMX_CLOCK_INFO Table[IMX_CLK_MAX];
+} IMX_CLOCK_TREE_CACHE;
+
+IMX_CCGR_INDEX
+ImxpCcgrIndexFromClkGate (
+  IN  IMX_CLK_GATE    ClockGate
+  );
+
+VOID
+ImxpClkPwrCacheReset (
+  VOID
+  );
+
+IMX_CLK
+ImxpClkFromBypassClkSource (
+  IN  IMX_PLL_BYPASS_CLK_SRC    BypassClockSource
+  );
+
+VOID
+ImxCcmConfigureGpuClockTree (
+  VOID
+  );
+
+VOID
+ImxCcmConfigureIPUDIxClockTree (
+  VOID
+  );
+
+VOID
+ImxCcmConfigureIPULDBxClockTree (
+  VOID
+  );
+
+VOID
+ImxSetClockRatePLL5 (
+  IN  UINT32                                  ClockRate,
+  IN  IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT  PostDivSelect
+  );
+
+EFI_STATUS
+ImxpGetClockInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  IN      IMX_CLK               ClockId,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+VOID
+ImxpGetOsc24ClkInfo (
+  OUT IMX_CLOCK_INFO  *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPll1MainClkInfo  (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPll2MainClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPll2PfdClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  IN      IMX_PLL_PFD           PfdIndex,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPll3MainClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPll3PfdClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  IN      IMX_PLL_PFD           PfdIndex,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPll3SwClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetAxiClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPeriphClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPrePeriphClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetPeriphClk2Info (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetArmClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetMmdcCh0ClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetAhbClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetIpgClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetGpu2dAxiClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetGpu3dAxiClkRootInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetGpu2dCoreClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetGpu3dCoreClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+EFI_STATUS
+ImxpGetGpu3dShaderClkInfo (
+  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
+  OUT     IMX_CLOCK_INFO        *ClockInfo
+  );
+
+VOID
+ImxEnableGpuVpuPowerDomain (
+  VOID
+  );
+
+VOID
+ImxDisableGpuVpuPowerDomain (
+  VOID
+  );
+
+#endif // _IMX6_CLK_PWR_PRIVATE_H_
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 20/27] Silicon/NXP: Add i.MX6 Board init library
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (18 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 20:12   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 21/27] Silicon/NXP: Add i.MX6 PCIe DXE driver Chris Co
                   ` (7 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support for board initialization which is common to
NXP i.MX6-based platforms.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S   |  89 ++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c      | 110 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c        |  88 ++++++++++++++++
 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c | 107 +++++++++++++++++++
 4 files changed, 394 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
new file mode 100644
index 000000000000..979e98888a6b
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
@@ -0,0 +1,89 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+#include <AsmMacroIoLib.h>
+#include <AutoGen.h>
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+
+.text
+.align 2
+
+// GIC Cpu interface
+#define ARM_GIC_ICCICR  0x00  // CPU Interface Control Register
+#define ARM_GIC_ICCPMR  0x04  // Interrupt Priority Mask Register
+#define ARM_GIC_ICCBPR  0x08  // Binary Point Register
+#define ARM_GIC_ICCIAR  0x0C  // Interrupt Acknowledge Register
+#define ARM_GIC_ICCEIOR 0x10  // End Of Interrupt Register
+#define ARM_GIC_ICCRPR  0x14  // Running Priority Register
+#define ARM_GIC_ICCPIR  0x18  // Highest Pending Interrupt Register
+#define ARM_GIC_ICCABPR 0x1C  // Aliased Binary Point Register
+#define ARM_GIC_ICCIDR  0xFC  // Identification Register
+
+// SRC (System Reset Controller) register offsets & masks
+#define IMX6_SRC_SCR     0x0
+#define IMX6_SRC_GPR1    0x20
+#define IMX6_SRC_GPR2    0x24
+#define IMX6_SRC_GPR3    0x28
+#define IMX6_SRC_GPR4    0x2C
+#define IMX6_SRC_GPR5    0x30
+#define IMX6_SRC_GPR6    0x34
+#define IMX6_SRC_GPR7    0x38
+#define IMX6_SRC_GPR8    0x3C
+#define IMX6_SRC_GPR9    0x40
+#define IMX6_SRC_GPR10   0x44
+
+GCC_ASM_EXPORT(ArmPlatformPeiBootAction)
+GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)
+GCC_ASM_EXPORT(ArmPlatformGetCorePosition)
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
+  MOV32 (r0, FixedPcdGet32 (PcdArmPrimaryCore))
+  ldr   r0, [r0]
+  bx    lr
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_PFX(ArmPlatformIsPrimaryCore):
+  mrc   p15,0,r0,c0,c0,5
+  ands  r0,r0,#3
+  moveq r0,#1
+  movne r0,#0
+  bx    lr
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+ASM_PFX(ArmPlatformGetCorePosition):
+  and   r0, r0, #ARM_CORE_MASK
+  bx    lr
+
+ASM_PFX(ArmPlatformPeiBootAction):
+  // enable unaligned access
+  mrc   p15, 0, r1, c1, c0, 0
+  bic   r1, r1, #0x2
+  mcr   p15, 0, r1, c1, c0, 0
+  isb
+  bx r14
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
new file mode 100644
index 000000000000..a2b601ec9c52
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
@@ -0,0 +1,110 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include "iMX6.h"
+
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS  8
+
+/**
+  Return the Virtual Memory Map of your platform
+
+  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
+  on your platform.
+
+  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR describing
+                                    a Physical-to-Virtual Memory mapping. This
+                                    array must be ended by a zero-filled entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+  IN ARM_MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap
+  )
+{
+  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
+  UINTN                         Index = 0;
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  DEBUG ((DEBUG_VERBOSE, "Enter: ArmPlatformGetVirtualMemoryMap\n"));
+
+  VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR *)AllocatePages (
+                         EFI_SIZE_TO_PAGES (sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
+                             MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
+  if (VirtualMemoryTable == NULL) {
+    return;
+  }
+
+  CacheAttributes = DDR_ATTRIBUTES_CACHED;
+  DEBUG ((DEBUG_VERBOSE, "CacheAttributes=0x%d\n", CacheAttributes));
+
+  // SOC registers region 1 (0x00100000 size 0x00C00000)
+  VirtualMemoryTable[Index].PhysicalBase   = SOC_REGISTERS_PHYSICAL_BASE1;
+  VirtualMemoryTable[Index].VirtualBase    = SOC_REGISTERS_PHYSICAL_BASE1;
+  VirtualMemoryTable[Index].Length         = SOC_REGISTERS_PHYSICAL_LENGTH1;
+  VirtualMemoryTable[Index].Attributes     = SOC_REGISTERS_ATTRIBUTES;
+
+  // PCIE Registers (0x01000000 size 0x01000000)
+  VirtualMemoryTable[++Index].PhysicalBase = PCIE_REGISTERS_PHYSICAL_BASE;
+  VirtualMemoryTable[Index].VirtualBase    = PCIE_REGISTERS_PHYSICAL_BASE;
+  VirtualMemoryTable[Index].Length         = PCIE_REGISTERS_PHYSICAL_LENGTH;
+  VirtualMemoryTable[Index].Attributes     = SOC_REGISTERS_ATTRIBUTES;
+
+  // SOC registers region 2 (excluding EIM) (0x02000000 size 0x00A00000)
+  VirtualMemoryTable[++Index].PhysicalBase = SOC_REGISTERS_PHYSICAL_BASE2;
+  VirtualMemoryTable[Index].VirtualBase    = SOC_REGISTERS_PHYSICAL_BASE2;
+  VirtualMemoryTable[Index].Length         = SOC_REGISTERS_PHYSICAL_LENGTH2;
+  VirtualMemoryTable[Index].Attributes     = SOC_REGISTERS_ATTRIBUTES;
+
+  // Framebuffer
+  VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet32 (PcdFrameBufferBase);
+  VirtualMemoryTable[Index].VirtualBase    = FixedPcdGet32 (PcdFrameBufferBase);
+  VirtualMemoryTable[Index].Length         = FixedPcdGet32 (PcdFrameBufferSize);
+  VirtualMemoryTable[Index].Attributes     = DDR_ATTRIBUTES_UNCACHED;
+
+  // Boot (UEFI) DRAM region (kernel.img & boot working DRAM) (0x10800000 size 0x001D0000)
+  VirtualMemoryTable[++Index].PhysicalBase   = BOOT_IMAGE_PHYSICAL_BASE;
+  VirtualMemoryTable[Index].VirtualBase      = BOOT_IMAGE_PHYSICAL_BASE;
+  VirtualMemoryTable[Index].Length           = BOOT_IMAGE_PHYSICAL_LENGTH;
+  VirtualMemoryTable[Index].Attributes       = BOOT_IMAGE_ATTRIBUTES;
+
+  // TrustZone Shared Memory
+  VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdTrustZoneSharedMemoryBase);
+  VirtualMemoryTable[Index].VirtualBase    = FixedPcdGet64 (PcdTrustZoneSharedMemoryBase);
+  VirtualMemoryTable[Index].Length         = FixedPcdGet64 (PcdTrustZoneSharedMemorySize);
+  VirtualMemoryTable[Index].Attributes     = CacheAttributes;
+
+  // Base SDRAM
+  VirtualMemoryTable[++Index].PhysicalBase = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[Index].VirtualBase    = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[Index].Length         = PcdGet64 (PcdSystemMemorySize);
+  VirtualMemoryTable[Index].Attributes     = CacheAttributes;
+
+  // End of Table
+  VirtualMemoryTable[++Index].PhysicalBase = 0;
+  VirtualMemoryTable[Index].VirtualBase    = 0;
+  VirtualMemoryTable[Index].Length         = 0;
+  VirtualMemoryTable[Index].Attributes     = (ARM_MEMORY_REGION_ATTRIBUTES)0;
+
+  ASSERT ((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
+
+  *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
new file mode 100644
index 000000000000..3f45527981a7
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
@@ -0,0 +1,88 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <IndustryStandard/Tpm20.h>
+#include <IndustryStandard/Tpm2Acpi.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/TimerLib.h>
+
+#include <iMX6.h>
+#include <iMX6BoardLib.h>
+#include <iMX6Timer.h>
+
+VOID __DoNothing() {}
+VOID SdhcInit () __attribute__ ((weak, alias ("__DoNothing")));
+VOID EhciInit () __attribute__ ((weak, alias ("__DoNothing")));
+VOID EnetInit () __attribute__ ((weak, alias ("__DoNothing")));
+VOID I2cInit () __attribute__ ((weak, alias ("__DoNothing")));
+VOID SpiInit () __attribute__ ((weak, alias ("__DoNothing")));
+VOID PcieInit () __attribute__ ((weak, alias ("__DoNothing")));
+VOID SetupAudio () __attribute__ ((weak, alias ("__DoNothing")));
+
+/**
+  Initialize controllers that must setup at the early stage
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+  IN  UINTN                     MpId
+  )
+{
+  if (!ArmPlatformIsPrimaryCore (MpId)) {
+    return RETURN_SUCCESS;
+  }
+
+  ImxClkPwrInit ();
+
+  // Initialize default UEFI debug port early so we can use its debug output
+  SerialPortInitialize ();
+  SerialPortWrite (
+    (UINT8 *)SERIAL_DEBUG_PORT_INIT_MSG,
+    (UINTN)sizeof (SERIAL_DEBUG_PORT_INIT_MSG));
+
+  // Initialize timer early on because the following init path will be calling
+  // delay functions. PrePi.c calls ArmPlatformInitialize before it calls
+  // TimerConstructor to initialize the timer.
+  TimerConstructor ();
+
+  SdhcInit ();
+  EhciInit ();
+  EnetInit ();
+  I2cInit ();
+  SpiInit ();
+  PcieInit ();
+  SetupAudio ();
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Return the current Boot Mode
+
+  This function returns the boot reason on the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+  VOID
+  )
+{
+  return BOOT_WITH_FULL_CONFIGURATION;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
new file mode 100644
index 000000000000..b59f9fe6f01f
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
@@ -0,0 +1,107 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+ARM_CORE_INFO iMX6Ppi[] = {
+  {
+    // Cluster 0, Core 0
+    0x0, 0x0,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value.
+    // Not used with i.MX6, set to 0
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (UINT64)0
+  },
+
+#if FixedPcdGet32(PcdCoreCount) > 1
+  {
+    // Cluster 0, Core 1
+    0x0, 0x1,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    // Not used with i.MX6, set to 0
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (UINT64)0
+  },
+#endif // FixedPcdGet32(PcdCoreCount) > 1
+
+#if FixedPcdGet32(PcdCoreCount) > 2
+  {
+    // Cluster 0, Core 2
+    0x0, 0x2,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    // Not used with i.MX6, set to 0
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (UINT64)0
+  },
+
+  {
+    // Cluster 0, Core 3
+    0x0, 0x3,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    // Not used with i.MX6, set to 0
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (EFI_PHYSICAL_ADDRESS)0x00000000,
+    (UINT64)0
+  }
+#endif // FixedPcdGet32(PcdCoreCount) > 2
+};
+
+EFI_STATUS
+PrePeiCoreGetMpCoreInfo (
+  OUT UINTN                   *CoreCount,
+  OUT ARM_CORE_INFO           **ArmCoreTable
+  )
+{
+  // Only support one cluster
+  *CoreCount    = sizeof (iMX6Ppi) / sizeof (ARM_CORE_INFO);
+  ASSERT (*CoreCount == FixedPcdGet32 (PcdCoreCount));
+  *ArmCoreTable = iMX6Ppi;
+  return EFI_SUCCESS;
+}
+
+EFI_GUID mArmMpCoreInfoPpiGuid = ARM_MP_CORE_INFO_PPI_GUID;
+ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo };
+EFI_PEI_PPI_DESCRIPTOR      gPlatformPpiTable[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &mArmMpCoreInfoPpiGuid,
+    &mMpCoreInfoPpi
+  }
+};
+
+VOID
+ArmPlatformGetPlatformPpiList (
+  OUT UINTN                   *PpiListSize,
+  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
+  )
+{
+  *PpiListSize = sizeof (gPlatformPpiTable);
+  *PpiList = gPlatformPpiTable;
+}
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (17 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 19:53   ` Leif Lindholm
  2018-12-17 11:14   ` Ard Biesheuvel
  2018-09-21  8:26 ` [PATCH edk2-platforms 20/27] Silicon/NXP: Add i.MX6 Board init library Chris Co
                   ` (8 subsequent siblings)
  27 siblings, 2 replies; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds baseline ACPI table support for booting Windows on
NXP i.MX6 SoCs.  Platforms may override these tables as necessary.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc         | 408 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc         | 142 +++++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h     | 106 +++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl     | 106 +++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl      |  74 ++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl     |  55 +++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl      |  67 ++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl     | 298 ++++++++++++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl | 106 +++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl      |  85 ++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl     | 133 +++++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl      | 103 +++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl     |  33 ++
 Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc         |  60 +++
 Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc         | 120 ++++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc         |  92 +++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc         |  95 +++++
 Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc         |  53 +++
 18 files changed, 2136 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
new file mode 100644
index 000000000000..82c2420a2b7e
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
@@ -0,0 +1,408 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "../Include/Platform.h"
+#include "../Include/iMX6.h"
+
+#pragma pack(push, iMX6Csrt, 1)
+
+// Timer Resource Group
+// Each timer consumes 4K of address space.
+#define TIMER_ADDRES_SIZE 0x1000
+#define TIMER_CAP_ALWAYS_ON     0x00000001 // Timer is always ON.
+#define TIMER_CAP_UP_COUNTER    0x00000002 // Up counter vs. down counter (0)
+#define TIMER_CAP_READABLE      0x00000004 // Counter has a software interface.
+#define TIMER_CAP_PERIODIC      0x00000008 // Can generate periodic interrupts.
+#define TIMER_CAP_DRIVES_IRQ    0x00000010 // Timer interrupt drives a physical IRQ.
+#define TIMER_CAP_ONE_SHOT      0x00000020 // Counter can generate one-shot interrupts
+
+// Timer source clock codes
+typedef enum {
+  GPT_CLOCK_NONE        = 0,
+  GPT_CLOCK_PERIPHERAL  = 1,
+  GPT_CLOCK_HI_FREQ     = 2,
+  GPT_CLOCK_EXT         = 3,
+  GPT_CLOCK_LOW_FREQ    = 4,
+#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
+  GPT_CLOCK_OSC_DIV_8   = 5,
+  GPT_CLOCK_OSC         = 7,
+#elif (defined(CPU_IMX6SDL) || defined(CPU_IMX6SX))
+  GPT_CLOCK_OSC         = 5,
+#else
+#error iMX6 CPU Type Not Defined (Preprocessor Flag)
+#endif
+} GPT_SOURCE_CLOCK;
+
+// EPIT timer source clock codes
+typedef enum {
+  EPIT_CLOCK_NONE        = 0,
+  EPIT_CLOCK_PERIPHERAL  = 1,
+  EPIT_CLOCK_HI_FREQ     = 2,
+  EPIT_CLOCK_LOW_FREQ    = 3,
+} EPIT_SOURCE_CLOCK;
+
+// Timer descriptor
+typedef struct {
+  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
+  UINT32 Capabilities;
+  UINT32 Width;
+  UINT32 Source;
+  UINT32 Frequency;
+  UINT32 FrequencyScale;
+  UINT32 BaseAddress;
+  UINT32 Size;
+  UINT32 Interrupt;
+  UINT32 ChipType;
+} RD_TIMER;
+
+// Resource Group Shared Info
+typedef struct {
+  UINT16 RevMajor;
+  UINT16 RevMinor;
+  UINT32 ChipType;
+} RG_PLATFORM_INFORMATION;
+
+// Timer group descriptor
+typedef struct {
+  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
+  RG_PLATFORM_INFORMATION PlatformInfo;
+#if defined(CPU_IMX6SDL)
+  RD_TIMER Timers[3];
+#else
+  RD_TIMER Timers[4];
+#endif
+} RG_TIMER;
+
+// PL310 L2 Cache Controller Resource Group
+#define CSRT_PL310_MINIMUM_VERSION   1
+#define CSRT_PL310_VERSION_2         2
+#define CSRT_PL310_RAW_PROTOCOL      0
+#define CSRT_PL310_SMC_PROTOCOL      1
+
+// We use PSCI_CPU_ON to turn on the L2 cache, with special value
+// 0x00100000 for the Core ID. PSCI sees this core ID and knows
+// this is an L2 cache operation, then looks at R2 for the
+// operation to perform.
+#define PSCI_FID_CPU_ON                        0x84000003
+#define L2CACHE_SMC_R1                         0x00100000
+#define L2CACHE_OP_ENABLE                      1
+#define L2CACHE_OP_DISABLE                     2
+#define L2CACHE_OP_ENABLE_WRITEBACK            3
+#define L2CACHE_OP_DISABLE_WRITEBACK           4
+#define L2CACHE_OP_ENABLE_WFLZ                 5
+
+typedef struct {
+  UINT32 Immediate;
+  UINT32 R0;
+  UINT32 R1;
+  UINT32 R2;
+  UINT32 R3;
+  UINT32 R12;
+} CSRT_SMC_INVOCATION_BLOCK;
+
+// L2 cache descriptor
+typedef struct {
+  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
+  UINT32 Version;
+  UINT32 ManagementProtocol;
+  UINT64 Address;
+  CSRT_SMC_INVOCATION_BLOCK InvokeEnable;
+  CSRT_SMC_INVOCATION_BLOCK InvokeDisable;
+  CSRT_SMC_INVOCATION_BLOCK InvokeEnableWriteback;
+  CSRT_SMC_INVOCATION_BLOCK InvokeDisableWriteback;
+  CSRT_SMC_INVOCATION_BLOCK InvokeEnableWFLZ;
+} RD_L2_CACHE;
+
+// PL310 L2 cache controller descriptor
+typedef struct {
+  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
+  RD_L2_CACHE L2Cache;
+} RG_L2_CACHE;
+
+// SmartDMA (SDMA) Controller Resource Group
+enum IMX_SDMA_CORE_CLOCK_RATIO {
+  IMX_SDMA_CORE_CLOCK_TWICE_CORE_FREQ = 0,
+  IMX_SDMA_CORE_CLOCK_EQUALS_CORE_FREQ = 1
+};
+
+// SDMA controller descriptor
+typedef struct {
+  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
+  UINT32 ChipType; // IMX_CHIP_TYPE
+  UINT64 RegistersBaseAddress;
+  UINT64 IoMuxGPR0Address;
+  UINT32 Interrupt;
+  UINT32 SdmaCoreClockRatio; // IMX_SDMA_CORE_CLOCK_RATIO
+} RD_SDMA;
+
+// SDMA controller group descriptor
+typedef struct {
+  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
+  RD_SDMA Sdma;
+} RG_SDMA;
+
+
+// CSRT structure for this platform
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER CsrtHeader; // Standard ACPI Header
+  RG_TIMER TimerResourceGroup;            // Timer Resource Group
+#ifndef CONFIG_L2CACHE_OFF
+  RG_L2_CACHE L2CacheResourceGroup;       // PL310 L2 Cache Resource Group
+#endif
+  RG_SDMA SdmaResourceGroup;              // SDMA Resource Group
+} EFI_ACPI_CSRT_TABLE;
+
+#pragma pack (pop, iMX6Csrt)
+
+EFI_ACPI_CSRT_TABLE Csrt = {
+  // CSRT Header
+  {
+    EFI_ACPI_5_0_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE,  // Signature "CSRT"
+    sizeof (EFI_ACPI_DESCRIPTION_HEADER) +              // Length
+    sizeof (RG_TIMER)
+#ifndef CONFIG_L2CACHE_OFF
+    + sizeof (RG_L2_CACHE)
+#endif
+    + sizeof (RG_SDMA),
+    EFI_ACPI_5_0_CSRT_REVISION,                         // Revision
+    0x00,                                               // Checksum calculated at runtime.
+    EFI_ACPI_OEM_ID,                                    // OEMID is a 6 bytes long field.
+    EFI_ACPI_OEM_TABLE_ID,                              // OEM table identification(8 bytes long).
+    EFI_ACPI_OEM_REVISION,                              // OEM revision number.
+    EFI_ACPI_CREATOR_ID,                                // ASL compiler vendor ID.
+    EFI_ACPI_CREATOR_REVISION,                          // ASL compiler revision number.
+  },
+
+  // TimerResourceGroup
+  {
+    // Timer group header
+    {
+      sizeof (RG_TIMER),              // Resource Group Length
+      EFI_ACPI_VENDOR_ID,             // VendorId
+      0,                              // SubvendorId
+      0x0101,                         // DeviceId
+      0,                              // SubdeviceId
+      0,                              // Revision
+      0,                              // Reserved
+      sizeof (RG_PLATFORM_INFORMATION) // Platform Information shared info
+    },
+
+    // Platform Information
+    {
+      0x0001,                        // RevMajor
+      0x0000,                        // RevMinor
+      0,                             // IMX_CHIP_TYPE (not used)
+    },
+
+    // Timers
+    {
+      // Counter (GPT)
+      {
+        {
+          sizeof (RD_TIMER),              // Resource Descriptor Length
+          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
+          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
+          3,                              // ResourceId
+        },
+        TIMER_CAP_READABLE | TIMER_CAP_UP_COUNTER, // Capabilities
+        32,                                 // Timer width (bits)
+        GPT_CLOCK_OSC,                      // Source is 111b for QD, 101b for SDL
+        SOC_OSC_FREQUENCY_REF_HZ,           // Frequency 24 MHz
+        24,                                 // divider to make 1 MHz
+        CSP_BASE_REG_PA_GPT,                // 32 bit Physical address
+        TIMER_ADDRES_SIZE,                  // Size of timer address space
+        0,                                  // N.B. No interrupt on this counter
+      },
+
+      // Timer0 (EPIT1)
+      {
+        {
+          sizeof (RD_TIMER),              // Resource Descriptor Length
+          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
+          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
+          4,                              // ResourceId
+        },
+        TIMER_CAP_ONE_SHOT | TIMER_CAP_PERIODIC | // Capabilities
+        TIMER_CAP_ALWAYS_ON | TIMER_CAP_DRIVES_IRQ,
+        32,                                 // Timer width (bits)
+        EPIT_CLOCK_LOW_FREQ,                // Source
+        SOC_LOW_FREQ_REF_HZ,                // Frequency
+        1,                                  // Frequency scale
+        CSP_BASE_REG_PA_EPIT1,              // 32 bit Physical address
+        TIMER_ADDRES_SIZE,                  // Size of timer address space
+        IRQ_EPIT1,                          // Interrupt
+      },
+
+      // Timer1 (EPIT2)
+      {
+        {
+          sizeof (RD_TIMER),              // Resource Descriptor Length
+          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
+          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
+          5,                              // ResourceId
+        },
+        TIMER_CAP_ONE_SHOT | TIMER_CAP_PERIODIC | // Capabilities
+        TIMER_CAP_ALWAYS_ON | TIMER_CAP_DRIVES_IRQ,
+        32,                                 // Timer width (bits)
+        EPIT_CLOCK_LOW_FREQ,                // Source
+        SOC_LOW_FREQ_REF_HZ,                // Frequency
+        1,                                  // Frequency scale
+        CSP_BASE_REG_PA_EPIT2,              // 32 bit Physical address
+        TIMER_ADDRES_SIZE,                  // Size of timer address space
+        IRQ_EPIT2,                          // Interrupt
+      },
+
+#if defined(CPU_IMX6DQ)
+      // SNVS LP Real Time Counter
+      {
+        {
+          sizeof (RD_TIMER),              // Resource Descriptor Length
+          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
+          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
+          6,                              // ResourceId
+        },
+        TIMER_CAP_UP_COUNTER |              // Capabilities
+        TIMER_CAP_READABLE |
+        TIMER_CAP_ALWAYS_ON,
+        47,                                 // Timer width (bits)
+        0,                                  // Source (NA)
+        SOC_LOW_FREQ_REF_HZ,                // Frequency
+        1,                                  // Frequency scale
+        IMX_SNVS_BASE,                      // 32 bit Physical address
+        TIMER_ADDRES_SIZE,                  // Size of timer address space
+        IMX_SNVS_IRQ,                       // Interrupt
+      },
+#endif
+    }
+  },
+
+#ifndef CONFIG_L2CACHE_OFF
+  // L2CacheResourceGroup
+  {
+    // L2 cache group header
+    {
+      sizeof (RG_L2_CACHE),           // Resource Group Length
+      SIGNATURE_32 ('A', 'R', 'M', 'H'), // VendorId
+      SIGNATURE_32 ('A', 'R', 'M', 'H'), // SubvendorId
+      0x0310,                         // DeviceId
+      0,                              // SubdeviceId
+      0,                              // Revision
+      0,                              // Reserved
+      0                               // No shared info
+    },
+
+    // PL310 L2 cache controller
+    {
+      {
+        sizeof (RD_L2_CACHE),           // Resource Descriptor Length
+        EFI_ACPI_CSRT_RD_TYPE_CACHE,    // Resource Type
+        EFI_ACPI_CSRT_RD_SUBTYPE_CACHE, // Resource Subtype
+        0,                              // UID
+      },
+      CSRT_PL310_VERSION_2,               // Version
+      CSRT_PL310_SMC_PROTOCOL,            // Management Protocol
+      CSP_BASE_REG_PA_PL310,              // 64 bit Physical address
+      // InvokeEnable
+      {
+        0,                              // Immediate
+        PSCI_FID_CPU_ON,                // R0
+        L2CACHE_SMC_R1,                 // R1
+        L2CACHE_OP_ENABLE,              // R2
+        0,                              // R3
+        0,                              // R12
+      },
+
+      // InvokeDisable
+      {
+        0,                              // Immediate
+        PSCI_FID_CPU_ON,                // R0
+        L2CACHE_SMC_R1,                 // R1
+        L2CACHE_OP_DISABLE,             // R2
+        0,                              // R3
+        0,                              // R12
+      },
+
+      // InvokeEnableWriteback
+      {
+        0,                              // Immediate
+        PSCI_FID_CPU_ON,                // R0
+        L2CACHE_SMC_R1,                 // R1
+        L2CACHE_OP_ENABLE_WRITEBACK,    // R2
+        0,                              // R3
+        0,                              // R12
+      },
+
+      // InvokeDisableWriteback
+      {
+        0,                              // Immediate
+        PSCI_FID_CPU_ON,                // R0
+        L2CACHE_SMC_R1,                 // R1
+        L2CACHE_OP_DISABLE_WRITEBACK,   // R2
+        0,                              // R3
+        0,                              // R12
+      },
+
+      // InvokeEnableWFLZ
+      {
+        0,                              // Immediate
+        PSCI_FID_CPU_ON,                // R0
+        L2CACHE_SMC_R1,                 // R1
+        L2CACHE_OP_ENABLE_WFLZ,         // R2
+        0,                              // R3
+        0,                              // R12
+      },
+    },
+  },
+#endif
+
+  // SdmaResourceGroup
+  {
+    // SDMA group header
+    {
+      sizeof (RG_SDMA),               // Resource Group Length
+      EFI_ACPI_VENDOR_ID,             // VendorId
+      0,                              // SubvendorId
+      0x0111,                         // DeviceId
+      0,                              // SubdeviceId
+      0,                              // Revision
+      0,                              // Reserved
+      0                               // No shared info
+    },
+
+    // SDMA controller resource
+    {
+      {
+        sizeof (RD_SDMA),                           // Resource Descriptor Length
+        EFI_ACPI_CSRT_RD_TYPE_DMA,                  // Resource Type
+        EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CONTROLLER,    // Resource Subtype
+        0,                                          // UID
+      },
+      0,                                    // IMX_CHIP_TYPE (not used)
+      CSP_BASE_REG_PA_SDMA,                 // SDMA registers base physical address
+      IOMUXC_GPR_BASE_ADDRESS,              // IoMuxGPR0 physical address
+      IRQ_SDMA,                             // IRQ number
+      IMX_SDMA_CORE_CLOCK_TWICE_CORE_FREQ,  // DMA/SDMA Core Clock Ratio:
+    },
+  }
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the executable
+  return (VOID *)&Csrt;
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
new file mode 100644
index 000000000000..65ce03d470ee
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
@@ -0,0 +1,142 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Platform.h>
+
+#include "iMX6.h"
+
+// DBG2 Definitions
+#pragma pack (1)
+
+typedef enum {
+  DBG2_TYPE_SERIAL = 0x8000,
+  DBG2_TYPE_1394,
+  DBG2_TYPE_USB,
+  DBG2_TYPE_NET
+} DBG2_PORT_TYPE;
+
+#define EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION 0x00000000
+#define UART_NAME_SPACE_STRING_LENGTH               sizeof("\\_SB.UAR1")
+#define UART_IMX6_UART_ADDRESS_SIZE       0x000000BC
+
+#if FixedPcdGet32(PcdKdUartInstance) == 1
+#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART1
+#define KD_UART_ACPI_PATH "\\_SB.UAR1"
+#elif FixedPcdGet32(PcdKdUartInstance) == 2
+#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART2
+#define KD_UART_ACPI_PATH "\\_SB.UAR2"
+#elif FixedPcdGet32(PcdKdUartInstance) == 3
+#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART3
+#define KD_UART_ACPI_PATH "\\_SB.UAR3"
+#elif FixedPcdGet32(PcdKdUartInstance) == 4
+#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART4
+#define KD_UART_ACPI_PATH "\\_SB.UAR4"
+#elif FixedPcdGet32(PcdKdUartInstance) == 5
+#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART5
+#define KD_UART_ACPI_PATH "\\_SB.UAR5"
+#else
+#error "Invalid PcdKdUartInstance. Must be 1, 2, 3, 4, or 5"
+#endif
+
+// ACPI 5.0 DBG2 structure
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER   Header;
+  UINT32                        OffsetDbgDeviceInfo;
+  UINT32                        NumberDbgdeviceInfo;
+} EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER;
+
+typedef struct {
+  UINT8 Revision;
+  UINT16 Length;
+  UINT8 NumberofGenericAddressRegisters;
+  UINT16 NameSpaceStringLength;
+  UINT16 NameSpaceStringOffset;
+  UINT16 OemDataLength;
+  UINT16 OemDataOffset;
+  UINT16 PortType;
+  UINT16 PortSubtype;
+  UINT16 Reserved;
+  UINT16 BaseAddressRegisterOffset;
+  UINT16 AddressSizeOffset;
+} DEBUG_DEVICE_INFO;
+
+typedef struct {
+  DEBUG_DEVICE_INFO DeviceInfo;
+  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
+  UINT32 AddressSize;
+  char NameSpaceString[UART_NAME_SPACE_STRING_LENGTH];
+} DEBUG_DEVICE_INFO_UART;
+
+typedef struct {
+  EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER Header;
+  DEBUG_DEVICE_INFO_UART Uart;
+} EFI_ACPI_5_0_DEBUG_PORT_2_TABLE;
+
+#pragma pack ()
+
+// Debug Port 2 table
+EFI_ACPI_5_0_DEBUG_PORT_2_TABLE Dbg2 = {
+  {
+    // Header
+    {
+      EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_SIGNATURE,     // Signature "DBG2"
+      sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE),      // Length
+      EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION,          // Revision
+      EFI_ACPI_5_0_UNDEFINED,                        // Checksum - updated at runtime
+      EFI_ACPI_OEM_ID,                               // OEM ID[6]
+      EFI_ACPI_OEM_TABLE_ID,                         // OEM Table ID
+      EFI_ACPI_OEM_REVISION,                         // OEM Revision
+      EFI_ACPI_CREATOR_ID,                           // Creator ID
+      EFI_ACPI_CREATOR_REVISION                      // Creator Revision
+    },
+    sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER), // OffsetDbgDeviceinfo
+    1,                                               // NumberDbgDeviceInfo
+  },
+  {
+    // Uart
+    {
+      // DeviceInfo
+      EFI_ACPI_RESERVED_BYTE,                                 // Revision
+      sizeof (DEBUG_DEVICE_INFO_UART),                        // Length
+      1,                                                      // NumberofGenericAddressRegisters
+      UART_NAME_SPACE_STRING_LENGTH,                          // NameSpaceStringLength
+      OFFSET_OF (DEBUG_DEVICE_INFO_UART, NameSpaceString),    // NameSpaceStringOffset
+      0,                                                      // OemDataLength
+      EFI_ACPI_RESERVED_WORD,                                 // OemDataOffset
+      DBG2_TYPE_SERIAL,                                       // PortType
+      DBG_PORT_SUBTYPE_IMX6,                                  // PortSubtype 000Ch
+      EFI_ACPI_RESERVED_WORD,                                 // Reserved
+      OFFSET_OF (DEBUG_DEVICE_INFO_UART, BaseAddressRegister), // BaseAddressRegisterOffset
+      OFFSET_OF (DEBUG_DEVICE_INFO_UART, AddressSize),        // AddressSizeOffset
+    },
+    {
+      // BaseAddressRegister
+      EFI_ACPI_5_0_SYSTEM_MEMORY,                             // AddressSpaceId
+      0x20,                                                   // RegisterBitWidth = 32
+      0,                                                      // RegisterBitOffset = 0
+      0x20,                                                   // AccessSize = 32
+      KD_UART_BASE_ADDR,                                      // Address
+    },
+    UART_IMX6_UART_ADDRESS_SIZE,                                // AddressSize
+    KD_UART_ACPI_PATH,                                          // NameSpaceString
+  },
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  return (void *) &Dbg2;
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
new file mode 100644
index 000000000000..4e4a3522e842
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
@@ -0,0 +1,106 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+// IMX alternate settings codes
+#define IMX_ALT0 0x0
+#define IMX_ALT1 0x1
+#define IMX_ALT2 0x2
+#define IMX_ALT3 0x3
+#define IMX_ALT4 0x4
+#define IMX_ALT5 0x5
+#define IMX_ALT6 0x6
+#define IMX_ALT7 0x7
+
+// IMX SDMA request lines.
+// These are logical values, the mapping to the SOC
+// actual DMA request lines are done in the HAL extension.
+#define SDMA_REQ_VPU 0
+#define SDMA_REQ_IPU2 1
+#define SDMA_REQ_IPU1 2
+#define SDMA_REQ_HDMI_AUDIO 3
+#define SDMA_REQ_ECSPI1_RX 4
+#define SDMA_REQ_ECSPI1_TX 5
+#define SDMA_REQ_ECSPI2_RX 6
+#define SDMA_REQ_ECSPI2_TX 7
+#define SDMA_REQ_ECSPI3_RX 8
+#define SDMA_REQ_ECSPI3_TX 9
+#define SDMA_REQ_ECSPI4_RX 10
+#define SDMA_REQ_ECSPI4_TX 11
+#define SDMA_REQ_ECSPI5_RX 12
+#define SDMA_REQ_ECSPI5_TX 13
+#define SDMA_REQ_I2C1_RX 14
+#define SDMA_REQ_I2C1_TX 15
+#define SDMA_REQ_I2C2_RX 16
+#define SDMA_REQ_I2C2_TX 17
+#define SDMA_REQ_I2C3_RX 18
+#define SDMA_REQ_I2C3_TX 19
+#define SDMA_REQ_UART1_RX 20
+#define SDMA_REQ_UART1_TX 21
+#define SDMA_REQ_UART2_RX 22
+#define SDMA_REQ_UART2_TX 23
+#define SDMA_REQ_UART3_RX 24
+#define SDMA_REQ_UART3_TX 25
+#define SDMA_REQ_UART4_RX 26
+#define SDMA_REQ_UART4_TX 27
+#define SDMA_REQ_UART5_RX 28
+#define SDMA_REQ_UART5_TX 29
+#define SDMA_REQ_SPDIF_RX 30
+#define SDMA_REQ_SPDIF_TX 31
+#define SDMA_REQ_EPIT1 32
+#define SDMA_REQ_EPIT2 33
+#define SDMA_REQ_GPT 34
+#define SDMA_REQ_ASRC_RXA 35
+#define SDMA_REQ_ASRC_RXB 36
+#define SDMA_REQ_ASRC_RXC 37
+#define SDMA_REQ_ASRC_TXA 38
+#define SDMA_REQ_ASRC_TXB 39
+#define SDMA_REQ_ASRC_TXC 40
+#define SDMA_REQ_ESAI_RX 41
+#define SDMA_REQ_ESAI_TX 42
+#define SDMA_REQ_ASRC_TXA_2_ESAI_TX 43
+#define SDMA_REQ_ASRC_TXB_2_ESAI_TX 44
+#define SDMA_REQ_ASRC_TXC_2_ESAI_TX 45
+#define SDMA_REQ_SSI1_RX1 46
+#define SDMA_REQ_SSI1_TX1 47
+#define SDMA_REQ_SSI1_RX0 48
+#define SDMA_REQ_SSI1_TX0 49
+#define SDMA_REQ_SSI2_RX1 50
+#define SDMA_REQ_SSI2_TX1 51
+#define SDMA_REQ_SSI2_RX0 52
+#define SDMA_REQ_SSI2_TX0 53
+#define SDMA_REQ_SSI3_RX1 54
+#define SDMA_REQ_SSI3_TX1 55
+#define SDMA_REQ_SSI3_RX0 56
+#define SDMA_REQ_SSI3_TX0 57
+#define SDMA_REQ_EXT1 58
+#define SDMA_REQ_EXT2 59
+#define SDMA_REQ_UART6_RX 60
+#define SDMA_REQ_UART6_TX 61
+#define SDMA_REQ_ADC1 62
+#define SDMA_REQ_ADC2 63
+#define SDMA_REQ_I2C4_RX 64
+#define SDMA_REQ_I2C4_TX 65
+#define SDMA_REQ_CSI1 66
+#define SDMA_REQ_CSI2 67
+#define SDMA_REQ_PXP 68
+#define SDMA_REQ_LCDIF1 69
+#define SDMA_REQ_LCDIF2 70
+#define SDMA_REQ_QSPI1_RX 71
+#define SDMA_REQ_QSPI1_TX 72
+#define SDMA_REQ_QSPI2_RX 73
+#define SDMA_REQ_QSPI2_TX 74
+#define SDMA_REQ_SAI1_TX 75
+#define SDMA_REQ_SAI1_RX 76
+#define SDMA_REQ_SAI2_TX 77
+#define SDMA_REQ_SAI2_RX 78
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
new file mode 100644
index 000000000000..eded7cdae7d0
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
@@ -0,0 +1,106 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (ENET)
+{
+  Name (_HID, "NXP010D")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0xF)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      // ENET MAC Core Base address
+      MEMORY32FIXED (ReadWrite, 0x02188000, 0x4000, )
+
+      // ENET MAC 0 Core IRQ
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 150 }
+
+      // ENET MAC 0 1588 Timer interrupt
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 151 }
+
+      // Errata ERR006687: workaround for GPIO interrupt to connect Enet interrupt
+      // to the GPC
+      GpioInt (Level, ActiveHigh, Shared, PullDefault, 0, "\\_SB.GPIO",) { 6 }
+    })
+    Return (RBUF)
+  }
+
+  Name (MAC, Buffer (6) {})
+  CreateDWordField (MAC, 0x00, MACL)
+  CreateWordField (MAC, 0x04, MACH)
+
+  // Device Specific Method takes 4 args:
+  //  Arg0 : Buffer containing a UUID [16 bytes]
+  //  Arg1 : Integer containing the Revision ID
+  //  Arg2 : Integer containing the Function Index
+  //  Arg3 : Package that contains function-specific arguments
+  Method (_DSM, 0x4, NotSerialized) {
+    switch (ToBuffer (Arg0)) {
+    // iMX Enet interface identifier
+    case (ToUUID ("4EBBCB9D-4087-4791-80BD-8F8C08024206")) {
+        // Function selector
+        switch (Arg2) {
+        // Function 0: Query support
+        //   Bit  Description
+        //   ---  -------------------------------
+        //     0  Get property (Function 0)
+        //     1  Enet PHY address on MDIO bus (Function 1)
+        //     2  Get Mac Address (Function 2)
+        //     3  Get MDIO BAse Address (Function 3)
+        case (0) {
+            // Revision selector
+            switch (Arg1) {
+            case (0) {
+                // Functions {0,1,2} supported
+                Return (Buffer() { 0x07 });
+              }
+            default {
+                Return (Buffer() { 0x00 });
+              }
+            }
+          }
+
+        // Function 1: Return Enet PHY address on MDIO bus.
+        case (1) {
+            Return (0x00);
+          }
+
+        // Function 2: Return Mac Address
+        case (2) {
+            if (LEqual (SIGN, 0x474C424C)) {
+              if (LEqual (REVN, 1)) {
+                if (Lequal (MC0V, 1)) {
+                  Store (MC0L, MACL);
+                  Store (MC0H, MACH);
+                  Return (MAC)
+                }
+              }
+            }
+            Return (Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
+          }
+
+        default {
+            Return (Buffer() { 0x00 });
+          }
+        }
+      }
+    default {
+        Return (Buffer() { 0x00 });
+      }
+    }
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
new file mode 100644
index 000000000000..eec71864210e
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
@@ -0,0 +1,74 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (VPU0)
+{
+  Name (_HID, "NXP0109")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0x0)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02040000, 0x3C000, )
+
+      // JPEG codec interrupt request
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 35 }
+
+      // VPU interrupt request
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 44 }
+    })
+    Return (RBUF)
+  }
+}
+
+// Description: Graphics Processing Unit (GPU)
+Device (GPU0)
+{
+  Name (_HID, "VERI2000")
+  Name (_CID, "VERI2000")
+  Name (_UID, 0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      // GPU 3D (GC2000)
+      MEMORY32FIXED (ReadWrite, 0x00130000, 0x4000, )
+
+      // GPU 2D (GC320)
+      MEMORY32FIXED (ReadWrite, 0x00134000, 0x4000, )
+
+      // IPU Base
+      MEMORY32FIXED (ReadWrite, 0x02600000, 0x400000, )
+
+      // HDMI PHY
+      MEMORY32FIXED (ReadWrite, 0x00120000, 0x9000, )
+
+      // GC2000
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 41 }
+
+      // GC320
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
+
+      // IPU1 sync interrupt request
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 38 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
new file mode 100644
index 000000000000..d9a5d2f8500a
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
@@ -0,0 +1,55 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (GPIO)
+{
+  Name (_HID, "NXP0103")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      // GPIO1-7
+      MEMORY32FIXED (ReadWrite, 0x0209C000, 0x1C000, )
+
+      // IOMUXC
+      MEMORY32FIXED (ReadWrite, 0x020E0000, 0x4000, )
+
+      // GPIO1 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 98, 99 }
+
+      // GPIO2 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 100, 101 }
+
+      // GPIO3 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 102, 103 }
+
+      // GPIO4 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 104, 105 }
+
+      // GPIO5 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 106, 107 }
+
+      // GPIO6 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 108, 109 }
+
+      // GPIO7 0-15, 16-31
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 110, 111 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
new file mode 100644
index 000000000000..af9f17890b97
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
@@ -0,0 +1,67 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (I2C1)
+{
+  Name (_HID, "NXP0104")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (I2C2)
+{
+  Name (_HID, "NXP0104")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021A4000, 0x14, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 69 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (I2C3)
+{
+  Name (_HID, "NXP0104")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
new file mode 100644
index 000000000000..1e0627f93000
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
@@ -0,0 +1,298 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (PCI0)
+{
+  Name (_HID, "PNP0A08")
+  Name (_UID, 0)
+  Name (_STR, Unicode ("PCIe 0 Device"))
+  Name (_BBN, 0)
+  Name (_SEG, 0)
+
+  // PCIE_PL memory map
+  OperationRegion (PLGC, SystemMemory, 0x01FFC700, 0x220)
+  Field (PLGC, DWordAcc, NoLock, Preserve) {
+    Offset (0x2C),  // Skip to register 0x01FFC72C
+    DBG1, 32,       // PCIE_PL_DEBUG1
+  }
+
+  // IOMUXC memory map
+  OperationRegion (IMXC, SystemMemory, 0x020E0000, 0x4000)
+  Field (IMXC, DWordAcc, NoLock, Preserve) {
+    Offset (0x04),  // Skip to register 0x020E0004
+    GPR1, 32,       // IOMUXC_GPR1
+  }
+
+  // PCIe is only available if PCIe PHY reference clock is enabled and link is up
+  Method (_STA) {
+    Name (LNK, 0x0);
+    Name (GPR, 0x0);
+    Store (GPR1, GPR);  // read IOMUXC_GPR1 register
+
+    // Check if the PCIe PHY reference clock is enabled
+    If (LNotEqual (And (GPR, 0x00010000), 0x00010000)) {
+      Return (0x0)
+    }
+
+    Store (DBG1, LNK);  // read PCIE_PL_DEBUG1 register
+
+    // Check if link is already up and is not in training
+    //  Bit4  : [36]: xmlh_link_up LTSSM reports PHY link up
+    //  Bit29  : [61]: xmlh_link_in_training LTSSM performing link training
+    If (LAnd (And (DBG1, 0x00000010), Lequal (And (DBG1, 0x20000000), 0x00))) {
+      Return (0xF)
+    } else {
+      Return (0x0)
+    }
+  }
+
+  // Declare the resources assigned to this root complex.
+  Method (_CRS, 0, Serialized) {
+    Name (RBUF, ResourceTemplate () {
+      WordBusNumber (
+        ResourceProducer, // Specify bus ranged is passed to child devices
+        MinFixed,         // Specify min address is fixed
+        MaxFixed,         // Specify max address is fixed
+        PosDecode,        // Positive decode of bus number
+        0,                // AddressGranularity 2 power of 0
+        0,                // AddressMinimum - Minimum Bus Number
+        1,                // AddressMaximum - Maximum Bus Number
+        0,                // AddressTranslation - Set to 0
+        2)                // RangeLength - Number of Busses
+
+      // PCI memory space
+      Memory32Fixed (ReadWrite, 0x01100000, 0x00E00000, )
+    })
+    Return (RBUF)
+  }
+
+  // Declare the PCI Routing Table.
+  Name (_PRT, Package() {
+    // Routing for device 0, all functions.
+    // Note: ARM doesn't support LNK nodes, so the third param
+    // is 0 and the fourth param is the SPI number of the interrupt
+    // line.
+    Package() {0x0000FFFF, 0, 0, 155}, // INTA
+    Package() {0x0000FFFF, 1, 0, 154}, // INTB
+    Package() {0x0000FFFF, 2, 0, 153}, // INTC
+    Package() {0x0000FFFF, 3, 0, 152}, // INTD/MSI
+  })
+
+  Name (SUPP, 0) // PCI _OSC Support Field value
+  Name (CTRL, 0) // PCI _OSC Control Field value
+
+  // Declare an _OSC (OS Control Hand-off) method which takes 4 arguments.
+  //
+  // Arguments:
+  //   Arg0  A Buffer containing a UUID
+  //   Arg1  An Integer containing a Revision ID of the buffer format
+  //   Arg2  An Integer containing a count of entries in Arg3
+  //   Arg3  A Buffer containing a list of DWORD capabilities
+  // Return Value:
+  //   A Buffer containing a list of capabilities
+  Method (_OSC, 4) {
+
+    // Create DWord-addressable fields from the Capabilities Buffer
+    // Create CDW1 outside the test as it's used in the else clause.
+    // The first DWORD in the _OSC Capabilities Buffer contains bits
+    // that are generic to _OSC
+    // PCI Firmware Specification - 4.5.1.
+    //
+    // ACPI - 6.2.10
+    // CDW return value information
+    // Bit 0 - Reserved (not used)
+    // Bit 1 - _OSC failure. Platform Firmware was unable to process the request or query
+    // Bit 2 - Unrecognized UUID
+    // Bit 3 - Unrecognized Revision
+    // Bit 4 - Capabilities Masked
+    // All others reserved
+
+    CreateDWordField (Arg3, 0, CDW1)
+    If (LEqual (Arg0, ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
+      CreateDWordField (Arg3, 4, CDW2)
+      CreateDWordField (Arg3, 8, CDW3)
+
+      // Save Capabilities DWord 2 & 3
+      // The second DWORD in the _OSC Capabilities Buffer is the Support Field
+      // The third DWORD in the _OSC Capabilities Buffer is the Control Field
+      // PCI Firmware Specification - 4.5.1.
+      // Supported feature should be set in the control field
+      //
+      // Support field
+      // Bit 0 - Extended PCI Config operation regions supported
+      // Bit 1 - Active State Power Management supported
+      // Bit 2 - Clock Power Management Capability supported
+      // Bit 3 - PCI Segment Groups supported
+      // Bit 4 - MSI supported
+      // Bit 5 - Optimized Buffer Flush and Fill supported
+      // Bit 6 - ASPM Optionality supported
+      //
+      // Control field
+      // Bit 0 - PCI Express Native Hot Plug control
+      // Bit 1 - SHPC Native Hot Plug control
+      // Bit 2 - PCI Express Native Power Management Events control
+      // Bit 3 - PCI Express Advanced Error Reporting control
+      // Bit 4 - PCI Express Capability Structure control
+      // Bit 5 - Latency Tolerance Reporting control
+
+      Store (CDW2, SUPP)
+      Store (CDW3, CTRL)
+
+      // Only allow native hot plug control if OS supports:
+      //  ASPM
+      //  Clock PM
+      //  MSI/MSI-X
+      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
+        And (CTRL, 0x1E, CTRL)
+      }
+
+      // Spec does not mention if standard hot plug is supported
+      // so unmask the bit
+      And (CTRL, 0x1D, CTRL)
+
+      // Check for unknown revision.
+      If (LNotEqual (Arg1, One)) {
+        Or (CDW1, 0x08, CDW1)
+      }
+
+      // Check if capabilities bits were masked.
+      If (LNotEqual (CDW3, CTRL)) {
+        Or (CDW1, 0x10, CDW1)
+      }
+
+      // Update DWORD3 in the buffer.
+      Store (CTRL, CDW3)
+      Return (Arg3)
+    } else {
+      // Unrecognized UUID
+      Or (CDW1, 4, CDW1)
+      Return (Arg3)
+    }
+  }
+
+  // Declare a _DSM method for various functions called by the OS.
+  // See the APCI spec, Section 9.14.1,
+  // and the PCI FW spec, Section 4.6.
+  // See also:
+  // http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/PCI-rsc.doc
+  Method (_DSM, 0x4, Serialized) {
+    // Match against the _DSM PCI UUID. PCI firmware spec - 4.6.1
+    //     Arg0 - UUID
+    //     Arg1 - Revision ID
+    //     Arg2 - Function Index
+    //     Arg3 - Empty Package
+    //
+    // Revision 1 & 2
+    //     Function 1 - PCI Express Slot Information
+    //     Function 2 - PCI Express Slot Number
+    //     Function 3 - Vendor-specific Token ID
+    //     Function 4 - PCI Bus Capabilities
+    //     Function 5 - Ignore PCI Boot Configuration
+    // Revision 2 only
+    //     Function 6 - LTR Maximum Latency
+    //     Function 7 - Express device under OS
+    If (LEqual (Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+
+      switch (ToInteger (Arg2)) {
+      // Function 0: Return supported functions as a bit-field
+      // with one bit for each supported function.
+      // Bit 0 must always be set, as that represents
+      // function 0 (which is what is being called here).
+      // Support for different functions may depend on
+      // the revision ID of the interface, passed as Arg1.
+
+      // Function 0: Get supported functions
+      case (0) {
+          // Functions 0,1,5 are supported.
+          if (LEqual (Arg1, 1)) {
+            return (Buffer() { 0x23 })
+          }
+
+          // Functions 0,1,5,7 are supported.
+          if (LEqual (Arg1, 2)) {
+            return (Buffer() { 0xA3 })
+          }
+
+          // Functions 0,1,5,7 are supported for
+          // future revision. Expect backward compatibility
+          return (Buffer() { 0xA3 })
+        }
+
+      // Function 1: PCI Express Slot Information
+      // PCI firmware spec - 4.6.1
+      case (1) {
+          // Package item 1:
+          //    0: Failure
+          //    1: Success
+          // Package item 2:
+          //  Integer 1:Bit Position
+          //        0 Supports x1
+          //        1 Supports x2
+          //        2 Supports x4
+          //        3 Supports x8
+          //        4 Supports x12
+          //        5 Supports x16
+          //  Integer 2:
+          //        0h Unknown
+          //        1h PCI Express Card Slot
+          //        2h PCI Express Server I/O Module Slot
+          //        3h PCI Express ExpressCard* Slot
+          //        4h PCI Express Mini Card Slot
+          //        5h PCI Express Wireless Form Factor Slot
+          //        Others Reserved
+          //  Integer 3:
+          //        0 SMBus signal
+          //        1 WAKE# signal
+          return ( Package (2) {
+            0x01, // Status success (1)
+            Package() {
+              0, // Supports x1
+              4, // PCI Express Mini Card Slot
+              1  // Supported signals (no SMBus, WAKE#)
+            }
+          })
+        }
+
+      // Function 5: Ignore PCI Boot Configurations
+      // PCI firmware spec - 4.6.5
+      case (5) {
+          // Always allow OS to rebalance
+          return (0x01)
+        }
+
+      // Function 7: Naming a PCI or PCI Express Device Under
+      //             Operating Systems
+      // PCI firmware spec - 4.6.7
+      case (7) {
+          // Verify revision 2
+          if (LEqual (Arg1, 2)) {
+            // PCI Express Slot Parsing
+            Return ( Package (2) {
+              1,            // Instance of the enumeration
+              "PCIe Slot 1" // String name which matches the label on the chassis
+            })
+          }
+        }
+      }
+    }
+    return (Buffer() { 0 })
+  }
+
+  // Root Port 0 Device within the Root Complex.
+  Device (RP0) {
+    Name (_ADR, 0)  // Device 0, Function 0
+    Name (_S0W, 4)  // Supports wake
+  }
+
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
new file mode 100644
index 000000000000..0bdc78080d26
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
@@ -0,0 +1,106 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+OperationRegion (GLBL, SystemMemory, 0x10817000, 0x10)
+Field (GLBL, AnyAcc, Nolock, Preserve)
+{
+  Offset (0),       // Miscellaneous Dynamic Registers:
+  SIGN, 32,         // Global Page Signature 'GLBL'
+  REVN, 8,          // Revision
+      , 8,          // Reserved
+      , 8,          // Reserved
+      , 8,          // Reserved
+  M0ID, 8,          // MAC 0 ID
+  MC0V, 8,          // MAC 0 Valid
+  MC0L, 32,         // MAC Address 0 Low
+  MC0H, 16,         // MAC Address 0 High
+}
+
+Device (CPU0)
+{
+  Name (_HID, "ACPI0007")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+}
+
+Device (CPU1)
+{
+  Name (_HID, "ACPI0007")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+}
+
+Device (CPU2)
+{
+  Name (_HID, "ACPI0007")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+}
+
+Device (CPU3)
+{
+  Name (_HID, "ACPI0007")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+}
+
+// Timers HAL extension
+Device (EPIT)
+{
+  Name (_HID, "NXP0101")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+}
+
+// Platform Extension Plugin
+Device (PEP0)
+{
+  Name (_HID, "NXP0102")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      // CCM request 1
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 119 }
+
+      // CCM request 2
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 120 }
+
+      // GPC request 1
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 121 }
+
+      // UART1
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
new file mode 100644
index 000000000000..22bab0cff575
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
@@ -0,0 +1,85 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (PWM1)
+{
+  Name (_HID, "NXP010E")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (PWM2)
+{
+  Name (_HID, "NXP010E")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02084000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 116 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (PWM3)
+{
+  Name (_HID, "NXP010E")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02088000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 117 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (PWM4)
+{
+  Name (_HID, "NXP010E")
+  Name (_UID, 0x4)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x0208C000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 118 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
new file mode 100644
index 000000000000..fad33d2e9d6c
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
@@ -0,0 +1,133 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+// uSDHC1
+Device (SDH1)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
+    })
+    Return (RBUF)
+  }
+
+  // Child node to represent the only SD/MMC slot on this SD/MMC bus
+  // In theory an SDHC can be connected to multiple SD/MMC slots at
+  // the same time, but only 1 device will be selected and active at
+  // a time
+  Device (SD0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+}
+
+// uSDHC2
+Device (SDH2)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
+    })
+    Return (RBUF)
+  }
+
+  Device (SD0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+}
+
+// uSDHC3
+Device (SDH3)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
+    })
+    Return (RBUF)
+  }
+
+  Device (SD0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+}
+
+// uSDHC4
+Device (SDH4)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x4)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x0219C000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 57 }
+    })
+    Return (RBUF)
+  }
+
+  Device (SD0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
new file mode 100644
index 000000000000..f68a7f306ecc
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
@@ -0,0 +1,103 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (SPI1)
+{
+  Name (_HID, "NXP0105")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02008000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 63 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (SPI2)
+{
+  Name (_HID, "NXP0105")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (SPI3)
+{
+  Name (_HID, "NXP0105")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02010000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 65 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (SPI4)
+{
+  Name (_HID, "NXP0105")
+  Name (_UID, 0x4)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02014000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 66 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (SPI5)
+{
+  Name (_HID, "NXP0105")
+  Name (_UID, 0x5)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02018000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 67 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
new file mode 100644
index 000000000000..83975792bcaf
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
@@ -0,0 +1,33 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (TREE)
+{
+  Name (_HID, "NXP010F")
+  Name (_CID, "TrEECSMP")
+  Name (_UID, 0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      // OP-TEE Shared memory area.
+      // Needs to match: PcdTrustZoneSharedMemoryBase, PcdTrustZoneSharedMemorySize
+      MEMORY32FIXED (ReadWrite, 0x12800000, 0x00200000, )
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
new file mode 100644
index 000000000000..58181ee9eda7
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
@@ -0,0 +1,60 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+// Advertise support for PSCI
+#define FADT_ARM_BOOT_ARCH       0x01
+
+char FACP[268] = {
+  0x46, 0x41, 0x43, 0x50,                         // Signature : 'FACP'
+  0x0C, 0x01, 0x00, 0x00,                         // Length
+  0x05,                                           // Revision
+  0x00,                                           // Checksum
+  0x4E, 0x58, 0x50, 0x4D, 0x58, 0x36,             // OEMID : 'NXPMX6'
+  0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, // OEMTABLE : 'EDK2'
+  0x01, 0x00, 0x00, 0x00,                         // OEM Revision
+  0x4D, 0x53, 0x46, 0x54,                         // CreatorID : 'MSFT'
+  0x01, 0x00, 0x00, 0x00,                         // Creator revision
+  0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x04, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C,
+  0x00, 0x00, 0x21, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, FADT_ARM_BOOT_ARCH,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  return (void *) &FACP;
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
new file mode 100644
index 000000000000..1c382306c780
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
@@ -0,0 +1,120 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/AcpiLib.h>
+
+#include <Platform.h>
+#include <iMX6.h>
+
+#define GICC_BASE                 FixedPcdGet64 (PcdGicInterruptInterfaceBase)
+#define GICD_BASE                 FixedPcdGet64 (PcdGicDistributorBase)
+
+// Virtualization related fields. Not supported on IMX6
+#define GICH_BASE                 0
+#define GICV_BASE                 0
+#define VGIC_MAINT_INT            0
+#define PMU_INTERRUPT             0
+
+#pragma pack(push, 1)
+typedef struct {
+  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
+  EFI_ACPI_6_0_GIC_STRUCTURE GicC[FixedPcdGet32 (PcdCoreCount)];
+  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE GicD;
+} ACPI_6_0_MADT_STRUCTURE;
+#pragma pack(pop)
+
+ACPI_6_0_MADT_STRUCTURE Madt = {
+  {
+    {
+      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, // Signature
+      sizeof (ACPI_6_0_MADT_STRUCTURE),                       // Length
+      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,  // Revision
+      0,                                                      // Checksum
+      EFI_ACPI_OEM_ID,                                        // OemId[6]
+      EFI_ACPI_OEM_TABLE_ID,                                  // OemTableId
+      EFI_ACPI_OEM_REVISION,                                  // OemRevision
+      EFI_ACPI_CREATOR_ID,                                    // CreatorId
+      EFI_ACPI_CREATOR_REVISION                               // CreatorRevision
+    },
+    0,      // LocalApicAddress
+    0       // Flags
+  },
+  {
+    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (0,                        // GicId
+                                      0x000,                     // AcpiCpuUid
+                                      0x000,                     // Mpidr
+                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
+                                      PMU_INTERRUPT,             // PmuIrq
+                                      GICC_BASE,                 // GicBase
+                                      GICV_BASE,                 // GicVBase
+                                      GICH_BASE,                 // GicHBase
+                                      VGIC_MAINT_INT,            // GsivId
+                                      0,                         // GicRBase
+                                      0                          // Efficiency
+                                     ),
+#if FixedPcdGet32(PcdCoreCount) > 1
+    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (1,                        // GicId
+                                      0x001,                     // AcpiCpuUid
+                                      0x001,                     // Mpidr
+                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
+                                      PMU_INTERRUPT,             // PmuIrq
+                                      GICC_BASE,                 // GicBase
+                                      GICV_BASE,                 // GicVBase
+                                      GICH_BASE,                 // GicHBase
+                                      VGIC_MAINT_INT,            // GsivId
+                                      0,                         // GicRBase
+                                      0                          // Efficiency
+                                     ),
+#if FixedPcdGet32(PcdCoreCount) > 2
+    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (2,                        // GicId
+                                      0x002,                     // AcpiCpuUid
+                                      0x002,                     // Mpidr
+                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
+                                      PMU_INTERRUPT,             // PmuIrq
+                                      GICC_BASE,                 // GicBase
+                                      GICV_BASE,                 // GicVBase
+                                      GICH_BASE,                 // GicHBase
+                                      VGIC_MAINT_INT,            // GsivId
+                                      0,                         // GicRBase
+                                      0                          // Efficiency
+                                     ),
+    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (3,                        // GicId
+                                      0x003,                     // AcpiCpuUid
+                                      0x003,                     // Mpidr
+                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
+                                      PMU_INTERRUPT,             // PmuIrq
+                                      GICC_BASE,                 // GicBase
+                                      GICV_BASE,                 // GicVBase
+                                      GICH_BASE,                 // GicHBase
+                                      VGIC_MAINT_INT,            // GsivId
+                                      0,                         // GicRBase
+                                      0                          // Efficiency
+                                     ),
+#endif
+#endif
+  },
+  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (0x0,                   // GicDistHwId
+                                     GICD_BASE,             // GicDistBase
+                                     IC_DIST_VECTOR_BASE,   // GicDistVector
+                                     EFI_ACPI_6_0_GIC_V1    // GicVersion
+                                    )
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  return (VOID *)&Madt;
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
new file mode 100644
index 000000000000..3e9d163cb52e
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
@@ -0,0 +1,92 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Platform.h>
+
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#include "iMX6.h"
+#include "../Drivers/PciExpress/iMX6PciExpress.h"
+
+#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
+
+// Size in bytes a single bus consumes in ECAM space
+// Configuration size = 4K
+// Max device = 32
+// Max function = 8
+// Max bus size = 4K * 32 * 8
+#define ECAM_BUS_ADDR_SIZE  (1 << 20)
+
+// Provide 2 differenct base PCI space address. The first list would represent
+// the host config space and the second list would be the device config space.
+// Windows is expected to be able to parse the information.
+#define NUM_PCI 2
+
+// MCFG structure
+// PCI Firmware specification Table 4-2
+#pragma pack(push, 1)
+
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER Header;
+  UINT64                      Reserved;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE AllocationStructure[NUM_PCI];
+} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;
+
+#pragma pack(pop)
+
+//
+// Multiple APIC Description Table
+//
+EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg = {
+  {
+    EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE),
+    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+    0x00,                           // Checksum will be updated at runtime
+    EFI_ACPI_OEM_ID,                // OEMID
+    EFI_ACPI_OEM_TABLE_ID,          // OEM Table ID
+    EFI_ACPI_OEM_MCFG_REVISION,     // OEM Revision
+    EFI_ACPI_CREATOR_ID,            // Creator ID
+    EFI_ACPI_CREATOR_REVISION,      // Creator revision
+  },
+  0x00,                             // Reserved
+
+  {
+    // PCIe Host
+    {
+      PCIE_HOST_CONFIG_BASE_REG,        // PCIE Host Config Base Address
+      0x00,                             // PciSegmentGroupNumber (_SEG)
+      0x00,                             // StartBusNumber
+      0x00,                             // EndBusNumber
+      0x00000000                        // Reserved
+    },
+
+    // PCIe Device
+    {
+      PCIE_DEVICE_CONFIG_BASE_REG - ECAM_BUS_ADDR_SIZE,  // BaseAddress
+      0x00,                              // PciSegmentGroupNumber (_SEG)
+      0x01,                              // StartBusNumber
+      0x01,                              // EndBusNumber
+      0x00000000                         // Reserved
+    }
+  }
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  return (VOID *)&Mcfg;
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
new file mode 100644
index 000000000000..603422a737c4
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
@@ -0,0 +1,95 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "Platform.h"
+#include "iMX6.h"
+
+// Ensure proper structure formats
+#pragma pack (1)
+
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER Header;
+  UINT8 Interface_Type;
+  UINT8 Reserved1[3];
+  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
+  UINT8 Interrupt_Type;
+  UINT8 PCAT_compatible_IRQ;
+  UINT32 Interrupt;
+  UINT8 Baud_Rate;
+  UINT8 Parity;
+  UINT8 Stop_Bits;
+  UINT8 Flow_Control;
+  UINT8 Terminal_Type;
+  UINT8 Reserved2;
+  UINT16 PCI_Device_ID;
+  UINT16 PCI_Vender_ID;
+  UINT8 PCI_Bus;
+  UINT8 PCI_Device;
+  UINT8 PCI_Function;
+  UINT32 PCI_Flags;
+  UINT8 PCI_Segment;
+  UINT32 Reserved3;
+} EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE SPCR = {
+  {
+    EFI_ACPI_5_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE),
+    0x02,
+    0x00,                           // Checksum will be updated at runtime
+    EFI_ACPI_OEM_ID,
+    EFI_ACPI_OEM_TABLE_ID,
+    EFI_ACPI_OEM_REVISION,
+    EFI_ACPI_CREATOR_ID,
+    EFI_ACPI_CREATOR_REVISION,
+  },
+  DBG_PORT_SUBTYPE_IMX6,   // Serial Interface type = Serial Port Subtypes of the DBG2
+  {0x00, 0x00, 0x00},      // Reserved
+
+  // ACPI Generic Address Structure. Set to all zeroes to disable console redirection
+  {
+    EFI_ACPI_5_0_SYSTEM_MEMORY,         // AddressSpaceId: SystemMemory
+    0x20,                               // RegisterBitWidth
+    0,                                  // RegisterBitOffset
+    EFI_ACPI_5_0_DWORD,                 // AccessSize
+    (UINT64)CSP_BASE_REG_PA_UART3       // Address UART3
+  },
+  0x08,        // Interrupt Type = Bit[3] ARMH GIC interrupt. 0 means not supported.
+  0x00,        // IRQ. Not used since Bit[0] of the Interrupt Type field is not set
+  0x3c,        // Global System Interrupt used by the UART (UART3 interrupt 60)
+  0x07,        // Baud Rate
+  0x00,        // No Parity
+  0x01,        // One Stop Bit
+  0x00,        // Flow Control: None
+  0x03,        // Terminal Type: ANSI
+  0X00,        // Reserved
+  0xffff,      // 0xFFFF - not a PCI device
+  0xffff,      // 0xFFFF - not a PCI device
+  0x00,        // Bus Number. 0 - not a PCI device
+  0x00,        // Device Number. 0 - not a PCI device
+  0x00,        // Function. 0 - not a PCI device
+  0x00000000,  // PCI Flags
+  0x00,        // PCI Segment
+  0x00000000,  //Reserved
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  return (VOID *)&SPCR;
+}
diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
new file mode 100644
index 000000000000..a5abb2bf15d1
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
@@ -0,0 +1,53 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <IndustryStandard/Tpm2Acpi.h>
+
+#include <Library/PcdLib.h>
+
+#include <Platform.h>
+#include "iMX6.h"
+
+// Definition is missing from MdePkg/Include/IndustryStandard/Tpm2Acpi.h
+#ifdef EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE
+#error "EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE is defined elsewhere."
+#else
+#define EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE 9
+#endif
+
+EFI_TPM2_ACPI_TABLE Tpm2Table = {
+  {
+    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
+    sizeof (EFI_TPM2_ACPI_TABLE),
+    EFI_TPM2_ACPI_TABLE_REVISION,
+    0,                          // Checksum will be updated at runtime
+    EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
+    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
+    EFI_ACPI_OEM_REVISION,      // OEM revision number
+    EFI_ACPI_CREATOR_ID,        // Creator vendor ID
+    EFI_ACPI_CREATOR_REVISION,  // Creator revision number
+  },
+  0,                            // Flags
+  FixedPcdGet64 (PcdTpm2AcpiBufferBase),  // Control Area
+  // StartMethod
+  EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE,
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  return (VOID *)&Tpm2Table;
+}
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 21/27] Silicon/NXP: Add i.MX6 PCIe DXE driver
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (19 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 20/27] Silicon/NXP: Add i.MX6 Board init library Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 21:59   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 23/27] Silicon/NXP: Add i.MX6 Smbios Driver Chris Co
                   ` (6 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds DXE driver support for PCIe on NXP i.MX6 SoCs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c   | 1139 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h   |  145 +++
 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf |   66 ++
 3 files changed, 1350 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
new file mode 100644
index 000000000000..424ab2d77227
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
@@ -0,0 +1,1139 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <IndustryStandard/Pci.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMX6IoMux.h>
+#include "iMX6PciExpress.h"
+
+PCI_RESOURCE PcieResource[] = {
+  // Memory resource
+  {
+    PCIE_MEMORY_SPACE_BASE,
+    PCIE_MEMORY_SPACE_SIZE,
+    PCIE_MEMORY_SPACE_BASE
+  },
+};
+
+// Pcie read and write function
+EFI_STATUS
+PciePciWrite (
+  IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+  IN UINTN Address,
+  IN UINTN Count,
+  IN VOID *Buffer
+  );
+
+EFI_STATUS
+PciePciRead (
+  IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+  IN UINTN Address,
+  IN UINTN Count,
+  IN VOID *Buffer
+  );
+
+// Internal Address Translation Unit configuration table. Map the Pcie device
+// configuration baesd on configuration. Pci IO space is not supported on
+// Windows. Memory space segment is just mapped back to the same address.
+//
+// The following table is used to setup basic translation setting on various
+// ATU (Address Translation Unit). The ATU is responsible to retranslate
+// address for inbound and outbound message.
+//
+// Address match mode address translation is based on the following formula :
+//     Address = Address - Base Address + Target Address
+//
+// There really isnt a need to retranslate the address for iMX6 however proceed
+// the program the ATU to for configuration and memory message.
+IATU_SETTINGS iMX6iAtuSettings[] = {
+  // Configuration message
+  {
+    OUTBOUND,
+    0,
+    CFG0_TYPE,
+    PCIE_DEVICE_CONFIG_BASE_REG,
+    0,
+    PCIE_DEVICE_CONFIG_BASE_REG + PCIE_DEVICE_CONFIG_SIZE - 1,
+    PCIE_DEVICE_CONFIG_BASE_REG,
+    0,
+    REGION_ENABLE,
+  },
+
+  // Memory message
+  {
+    OUTBOUND,
+    2,
+    MEMORY_TYPE,
+    PCIE_MEMORY_SPACE_BASE,
+    0,
+    PCIE_MEMORY_SPACE_BASE + PCIE_MEMORY_SPACE_SIZE - 1,
+    PCIE_MEMORY_SPACE_BASE,
+    0,
+    REGION_ENABLE,
+  },
+};
+
+VOID
+PcieSetupiAtu (
+  IN  IATU_SETTINGS   *SettingsPtr
+  )
+{
+  volatile CSP_PCIE_PL_REGS *pPortLogicRegs;
+
+  ASSERT (SettingsPtr->RegionIndex < MAX_iATU_REGION);
+  pPortLogicRegs = (CSP_PCIE_PL_REGS *)PCIE_CTRL_PORT_LOGIG_BASE_REG;
+
+  // Program specific ATU region
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATUVR,
+    (SettingsPtr->RegionDirection << 31 | SettingsPtr->RegionIndex));
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURC2,
+    REGION_DISABLE);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURLBA,
+    SettingsPtr->LowerBaseAddr);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURUBA,
+    SettingsPtr->UpperBaseAddr);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURLA,
+    SettingsPtr->LimitAddr);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURLTA,
+    SettingsPtr->LowerTargetAddr);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURUTA,
+    SettingsPtr->UpperTargetAddr);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURC1,
+    SettingsPtr->Type);
+
+  MmioWrite32 (
+    (UINTN)&pPortLogicRegs->PCIE_PL_iATURC2,
+    SettingsPtr->State);
+}
+
+VOID
+PcieSetupiAtuSettings (
+  VOID
+  )
+{
+  UINT32 i;
+
+  // Initialize internal Address Translation Unit based on settings specify
+  // in iMX6iAtuSettings table.
+  for (i = 0; i < ARRAYSIZE (iMX6iAtuSettings); ++i) {
+    PcieSetupiAtu (&iMX6iAtuSettings[i]);
+  }
+
+  return;
+}
+
+EFI_STATUS
+PcieSetPhyState (
+  IN  BOOLEAN   State
+  )
+{
+  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcGprRegisters;
+  IMX_IOMUXC_GPR1_REG                 Gpr1Reg;
+
+  pIoMuxcGprRegisters = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
+  Gpr1Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR1);
+  if (State == TRUE) {
+#if defined(CPU_IMX6DQP)
+    Gpr1Reg.PCIE_SW_RST = 0;
+#endif
+    Gpr1Reg.REF_SSP_EN = 1;     // Enable Pcie PHY
+    Gpr1Reg.TEST_POWERDOWN = 0; // Power down is not requested
+  } else {
+    Gpr1Reg.REF_SSP_EN = 0;     // Disable Pcie PHY
+    Gpr1Reg.TEST_POWERDOWN = 1; // Power down is requested
+  }
+  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR1, Gpr1Reg.AsUint32);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcieSetupInitSetting (
+  VOID
+  )
+{
+  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcGprRegisters;
+  EFI_STATUS                          Status;
+  IMX_IOMUXC_GPR1_REG                 Gpr1Reg;
+  IMX_IOMUXC_GPR12_REG                Gpr12Reg;
+  IMX_IOMUXC_GPR8_REG                 Gpr8Reg;
+
+  pIoMuxcGprRegisters = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
+
+  // If Pcie PHY is already enabled we are in an unexpected state, just exit
+  // and assume a bootloader has already setup Pcie and assigned resources.
+  Gpr1Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR1);
+  if (Gpr1Reg.REF_SSP_EN == 1) {
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Disable the PHY first, without this Pci link randomly does not come up
+  Status = PcieSetPhyState (FALSE);
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to disable Pcie PHY\n");
+    goto Exit;
+  }
+
+  // First configure Pcie and Pcie PHY default setting
+  Gpr12Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR12);
+  Gpr12Reg.APP_LTSSM_ENABLE = 0;          // Set application not ready
+  Gpr12Reg.DIA_STATUS_BUS_SELECT = 0xB;   // Debug functionality
+  Gpr12Reg.DEVICE_TYPE = 0x4;             // Set to RC mode
+  Gpr12Reg.LOS_LEVEL = 0x9;               // Set to 0x9 per reference manual
+  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR12, Gpr12Reg.AsUint32);
+
+  // Gen1 | Gen2 3p5 | Gen2 6 | Swing full 127 | Swing low 127
+  Gpr8Reg.PCS_TX_DEEMPH_GEN1 = 0;
+  Gpr8Reg.PCS_TX_DEEMPH_GEN2_3P5DB = 0;
+  Gpr8Reg.PCS_TX_DEEMPH_GEN2_6DB = 20;
+  Gpr8Reg.PCS_TX_SWING_FULL = 127;
+  Gpr8Reg.PCS_TX_SWING_LOW = 127;
+  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR8, Gpr8Reg.AsUint32);
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieSetClockGate (
+  IN  IMX_CLOCK_GATE_STATE  State
+  )
+{
+  ImxClkPwrSetClockGate (IMX_PCIE_ROOT_ENABLE, State);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcieVerifyClocks (
+  VOID
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
+  IMX_CCM_ANALOG_PLL_ENET_REG         CcmAnalogPllReg;
+
+  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
+  CcmAnalogPllReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_ENET);
+  if ((CcmAnalogPllReg.POWERDOWN == 0) &&
+      (CcmAnalogPllReg.BYPASS == 0) &&
+      (CcmAnalogPllReg.ENABLE_125M == 1) &&
+      (CcmAnalogPllReg.LOCK == 1)) {
+    return EFI_SUCCESS;
+  }
+
+  return EFI_DEVICE_ERROR;
+}
+
+VOID
+PcieEnablePerstLine (
+  VOID
+  )
+{
+  // Enable board specific PERST line if one is defined
+  if (FixedPcdGet32 (PcdPcieResetGpio)) {
+    ImxGpioWrite (
+      FixedPcdGet32 (PcdPcieResetGpioBankNumber),
+      FixedPcdGet32 (PcdPcieResetGpioIoNumber),
+      IMX_GPIO_HIGH);
+    gBS->Stall (20000);
+  }
+}
+
+EFI_STATUS
+PcieSetupPciBridge (
+  VOID
+  )
+{
+  UINT8 classCode[0];
+
+  // Setup the bridge class
+  classCode[0] = PCI_IF_BRIDGE_P2P;
+  classCode[1] = PCI_CLASS_BRIDGE_P2P;
+  classCode[2] = PCI_CLASS_BRIDGE;
+
+  return PciePciWrite (
+           EfiPciIoWidthUint8,
+           PCIE_HOST_CONFIG_BASE_REG + PCI_CLASSCODE_OFFSET,
+           3,
+           classCode);
+}
+
+EFI_STATUS
+PcieSetLinkStatus (
+  IN  BOOLEAN   State
+  )
+{
+  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcGprRegisters;
+  IMX_IOMUXC_GPR12_REG                Gpr12Reg;
+
+  pIoMuxcGprRegisters = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
+  Gpr12Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR12);
+  if (State == TRUE) {
+    Gpr12Reg.APP_LTSSM_ENABLE = 1; // Enable link
+  } else {
+    Gpr12Reg.APP_LTSSM_ENABLE = 0; // Disable link
+  }
+  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR12, Gpr12Reg.AsUint32);
+
+  return EFI_SUCCESS;
+}
+
+BOOLEAN
+PcieIsLinkUp (
+  VOID
+  )
+{
+  volatile CSP_PCIE_PL_REGS   *pPortLogicRegs;
+  UINT32                      Debug1Reg;
+
+  pPortLogicRegs = (CSP_PCIE_PL_REGS *)PCIE_CTRL_PORT_LOGIG_BASE_REG;
+  Debug1Reg = MmioRead32 ((UINTN)&pPortLogicRegs->PCIE_PL_DEBUG1);
+  return (Debug1Reg & PCIE_PL_DEBUG1_PHY_LINK_UP) ? TRUE : FALSE;
+}
+
+EFI_STATUS
+PcieWaitForLink (
+  VOID
+  )
+{
+  UINT32    Counter;
+  BOOLEAN   LinkStatus;
+
+  Counter = 200;
+  LinkStatus = PcieIsLinkUp ();
+
+  // To optimize boot time, consider lowering timeout value
+  while (LinkStatus == FALSE && Counter > 0) {
+    --Counter;
+    gBS->Stall (1000);
+    LinkStatus = PcieIsLinkUp ();
+  }
+
+  return (LinkStatus) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
+EFI_STATUS
+PcieGetAlignAddress (
+  IN  UINTN   Address,
+  IN  UINTN   AlignmentSize,
+  OUT UINTN   *AlignAddress
+  )
+{
+  EFI_STATUS Status;
+
+  *AlignAddress = 0;
+  if ((AlignmentSize & (AlignmentSize - 1)) != 0) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  // Even though we do not add a (AlignmentSize + 1) to the incoming address
+  // we would still align to the upper boundary as bit [19:00] is assumed to
+  // be 0x000FFFFF per Pcie spec.
+  *AlignAddress = (Address) & ~(AlignmentSize - 1);
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieGetPciConfigAddress (
+  IN  UINTN   BusNumber,
+  IN  UINTN   DevNumber,
+  IN  UINTN   FuncNumber,
+  IN  UINTN   Register,
+  OUT UINTN   *Address
+  )
+{
+  UINT64      Offset;
+  EFI_STATUS  Status;
+
+  // For now only support bus 0 and bus 1 with one device in each bus
+  if (BusNumber == 0 && DevNumber == 0) {
+    Offset = EFI_PCI_ADDRESS (BusNumber, DevNumber, FuncNumber, Register);
+    *Address = PCIE_HOST_CONFIG_BASE_REG + Offset;
+    Status = EFI_SUCCESS;
+  } else if (BusNumber == 1 && DevNumber == 0) {
+    Offset = EFI_PCI_ADDRESS (BusNumber, DevNumber, FuncNumber, Register);
+    Offset -= EFI_PCI_ADDRESS (1, 0, FuncNumber, 0);
+    *Address = PCIE_DEVICE_CONFIG_BASE_REG + Offset;
+    Status = EFI_SUCCESS;
+  } else {
+    *Address = 0;
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+PciePciRead (
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
+  IN  UINTN                       Address,
+  IN  UINTN                       Count,
+  OUT VOID                        *Buffer
+  )
+{
+  UINT8       *pDest;
+  EFI_STATUS  Status;
+  UINTN       Stride;
+
+  pDest = (UINT8 *)Buffer;
+  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+  Stride = (UINTN)1 << Width;
+
+  switch (Width) {
+  case EfiPciWidthUint8:
+    for (; Count > 0; --Count, pDest += Stride, Address += Stride) {
+      *pDest = MmioRead8 (Address);
+    }
+    Status = EFI_SUCCESS;
+    break;
+  case EfiPciWidthUint16:
+    for (; Count > 0; --Count, pDest += Stride, Address += Stride) {
+      *((UINT16 *)pDest) = MmioRead16 (Address);
+    }
+    Status = EFI_SUCCESS;
+    break;
+  case EfiPciWidthUint32:
+    for (; Count > 0; --Count, pDest += Stride, Address += Stride) {
+      *((UINT32 *)pDest) = MmioRead32 (Address);
+    }
+    Status = EFI_SUCCESS;
+    break;
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PciePciWrite (
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
+  IN  UINTN                       Address,
+  IN  UINTN                       Count,
+  IN  VOID                        *Buffer
+  )
+{
+  UINT8       *pSrc;
+  EFI_STATUS  Status;
+  UINTN       Stride;
+
+  pSrc = (UINT8 *)Buffer;
+  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+  Stride = (UINTN)1 << Width;
+
+  switch (Width) {
+  case EfiPciWidthUint8:
+    for (; Count > 0; --Count, pSrc += Stride, Address += Stride) {
+      MmioWrite8 (Address, *pSrc);
+    }
+    Status = EFI_SUCCESS;
+    break;
+  case EfiPciWidthUint16:
+    for (; Count > 0; --Count, pSrc += Stride, Address += Stride) {
+      MmioWrite16 (Address, *((UINT16 *)pSrc));
+    }
+    Status = EFI_SUCCESS;
+    break;
+  case EfiPciWidthUint32:
+    for (; Count > 0; --Count, pSrc += Stride, Address += Stride) {
+      MmioWrite32 (Address, *((UINT32 *)pSrc));
+    }
+    Status = EFI_SUCCESS;
+    break;
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieDevicePresent (
+  OUT PCI_TYPE00  *PciDevice,
+  IN  UINTN       Bus,
+  IN  UINTN       Device,
+  IN  UINTN       Func
+  )
+{
+  UINTN       Address;
+  EFI_STATUS  Status;
+
+  // Create Pci address map in terms of Bus, Device, and Func
+  Status = PcieGetPciConfigAddress (Bus, Device, Func, 0, &Address);
+  if (EFI_ERROR (Status)) {
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  // Read the Vendor ID register
+  Status = PciePciRead (
+             EfiPciWidthUint32,
+             Address,
+             1,
+             PciDevice);
+  if (!EFI_ERROR (Status) && (PciDevice->Hdr).VendorId != 0xffff) {
+    // Read the entire config header for the device
+    Status = PciePciRead (
+               EfiPciWidthUint32,
+               Address,
+               sizeof (PCI_TYPE00) / sizeof (UINT32),
+               PciDevice);
+    if (EFI_ERROR (Status)) {
+      PCIE_ERROR ("Failed to read Pci config space\n");
+    }
+  } else {
+    PCIE_INFO ("No Pcie device found\n");
+    Status = EFI_NOT_FOUND;
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieGetMemoryBarResource (
+  IN  UINTN     BarSize,
+  IN  UINTN     *BarAddress,
+  IN  BOOLEAN   IsBridgeDevice
+  )
+{
+  EFI_STATUS  Status;
+
+  if (BarSize > PcieResource->Size) {
+    PCIE_ERROR ("Insufficient Pcie memory for 0x%08x (Current size 0x%08x)\n",
+                BarSize,
+                PcieResource->Size);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  *BarAddress = PcieResource->Curr;
+
+  if (IsBridgeDevice == FALSE) {
+    PcieResource->Curr += BarSize;
+    PcieResource->Size -= BarSize;
+
+    PCIE_INFO ("Allocating memory resource 0x%08x size 0x%08x\n",
+               *BarAddress,
+               BarSize);
+  }
+
+  PCIE_INFO ("Current memory resource 0x%08x Size 0x%08x\n",
+             PcieResource->Curr,
+             PcieResource->Size);
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieParseAssignBar (
+  IN  UINTN     BaseAddress,
+  IN  UINTN     MaxBarIndex,
+  IN  BOOLEAN   IsBridgeDevice
+  )
+{
+  UINT32        AllOne32;
+  UINT32        AllZero;
+  UINTN         BarIndex;
+  UINTN         BarOffset;
+  UINTN         BarSize;
+  UINTN         Originalvalue;
+  UINTN         ResourceAddress;
+  UINTN         ResponseValue;
+  EFI_STATUS    Status;
+
+  AllZero = 0;
+  AllOne32 = MAX_UINT32;
+  for (BarOffset = 0x10, BarIndex = 0;
+       BarOffset <= 0x24 && BarIndex < MaxBarIndex;
+       BarOffset += sizeof (UINT32), ++BarIndex) {
+
+    Status = PciePciRead (
+               EfiPciWidthUint32,
+               BaseAddress + BarOffset,
+               1,
+               &Originalvalue);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint32,
+               BaseAddress + BarOffset,
+               1,
+               &AllOne32);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciRead (
+               EfiPciWidthUint32,
+               BaseAddress + BarOffset,
+               1,
+               &ResponseValue);
+    ASSERT_EFI_ERROR (Status);
+
+    // No support for IO memory
+    // Refer : Pci Local Bus Specification (6.2.5.1)
+    if ((ResponseValue & 0x01) == 0x01) {
+      Status = PciePciWrite (
+                 EfiPciIoWidthUint32,
+                 BaseAddress + BarOffset,
+                 1,
+                 &Originalvalue);
+      ASSERT_EFI_ERROR (Status);
+      continue;
+    }
+
+    // No support for prefetch memory
+    if (((ResponseValue & 0x01) == 0x00) &&
+        ((ResponseValue & 0x08) == 0x08)) {
+      Status = PciePciWrite (
+                 EfiPciIoWidthUint32,
+                 BaseAddress + BarOffset,
+                 1,
+                 &Originalvalue);
+      ASSERT_EFI_ERROR (Status);
+      continue;
+    }
+
+    BarSize = (~(ResponseValue & 0xFFFFFFF0)) + 1;
+
+    Status = PcieGetMemoryBarResource (
+               BarSize,
+               &ResourceAddress,
+               IsBridgeDevice);
+    if (EFI_ERROR (Status)) {
+      PCIE_ERROR ("Failed to acquire BAR resource\n");
+      goto Exit;
+    }
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint32,
+               BaseAddress + BarOffset,
+               1,
+               &ResourceAddress);
+    ASSERT_EFI_ERROR (Status);
+
+    // The subsequent BAR is the upper 32 bit address
+    if (((ResponseValue & 0x04) == 0x04) &&
+        (BarIndex + 1) < MaxBarIndex) {
+      BarOffset += sizeof (UINT32);
+      ++BarIndex;
+
+      Status = PciePciWrite (
+                 EfiPciIoWidthUint32,
+                 BaseAddress + BarOffset,
+                 1,
+                 &AllZero);
+      ASSERT_EFI_ERROR (Status);
+
+      continue;
+    }
+  }
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieConfigureDevice (
+  IN  PCI_TYPE00  PciDevice,
+  IN  UINTN       BusNumber,
+  IN  UINTN       DevNumber,
+  IN  UINTN       FuncNumber
+  )
+{
+  UINT32      AllZero;
+  UINTN       BaseAddress;
+  UINT8       FixedCacheLineSize;
+  UINT16      PciCommand;
+  EFI_STATUS  Status;
+
+  AllZero = 0;
+
+  PCIE_INFO (
+    "Configuring B:%02d D:%02d F:%02d\n",
+    BusNumber,
+    DevNumber,
+    FuncNumber);
+
+  Status = PcieGetPciConfigAddress (
+             BusNumber,
+             DevNumber,
+             FuncNumber,
+             0,
+             &BaseAddress);
+  ASSERT_EFI_ERROR (Status);
+
+  // Use a fixed cacheline size
+  FixedCacheLineSize = 0x10;
+
+  Status = PciePciWrite (
+             EfiPciIoWidthUint8,
+             BaseAddress + PCI_CACHELINE_SIZE_OFFSET,
+             1,
+             &FixedCacheLineSize);
+  ASSERT_EFI_ERROR (Status);
+
+  if (IS_PCI_BRIDGE (&PciDevice)) {
+    PCIE_INFO ("Pci Bridge\n");
+    // Pcie initialization sequence, referenced from
+    // InitializePpb in MdeModulePkg/Bus/Pci/PciBusDxe
+    // No support for IO and prefetch memory
+    Status = PciePciWrite (
+               EfiPciIoWidthUint8,
+               BaseAddress + 0x1C,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint8,
+               BaseAddress + 0x1D,
+               1,
+               &AllZero);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint16,
+               BaseAddress + 0x24,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint16,
+               BaseAddress + 0x26,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint32,
+               BaseAddress + 0x28,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint32,
+               BaseAddress + 0x2C,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint16,
+               BaseAddress + 0x30,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = PciePciWrite (
+               EfiPciIoWidthUint16,
+               BaseAddress + 0x32,
+               1,
+               &AllZero);
+    ASSERT_EFI_ERROR (Status);
+
+    // Type 1 bridge only has 2 BAR register
+    Status = PcieParseAssignBar (
+               BaseAddress,
+               2,
+               TRUE);
+    if (EFI_ERROR (Status)) {
+      PCIE_ERROR ("Failed to assign resource to Pci bridge\n");
+      goto Exit;
+    }
+  } else {
+    // Device specific configuration should be implemented here
+    PCIE_INFO ("Pci device\n");
+
+    Status = PcieParseAssignBar (
+               BaseAddress,
+               PCI_MAX_BAR,
+               FALSE);
+    if (EFI_ERROR (Status)) {
+      PCIE_ERROR ("Failed to assign resource to Pci device\n");
+      goto Exit;
+    }
+  }
+
+  Status = PciePciRead (
+             EfiPciIoWidthUint16,
+             BaseAddress + PCI_COMMAND_OFFSET,
+             1,
+             &PciCommand);
+  ASSERT_EFI_ERROR (Status);
+
+  PciCommand |=
+    (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+
+  Status = PciePciWrite (
+             EfiPciIoWidthUint16,
+             BaseAddress + PCI_COMMAND_OFFSET,
+             1,
+             &PciCommand);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieSimpleScanBusAndAssignResource (
+  IN  UINTN   BusNumber
+  )
+{
+  UINTN         BridgeMemory;
+  UINTN         BridgeMemoryBase;
+  UINTN         BridgeMemoryLimit;
+  UINTN         BusBaseRegisterAddress;
+  UINT16        BusRegister;
+  UINTN         DevNumber;
+  UINTN         FunctionNumber;
+  PCI_TYPE00    PciDevice;
+  UINTN         ResourceAddress;
+  EFI_STATUS    Status;
+  UINT8         SubBus;
+
+  for (DevNumber = 0; DevNumber <= PCI_MAX_DEVICE; ++DevNumber) {
+    for (FunctionNumber = 0; FunctionNumber <= PCI_MAX_FUNC; ++FunctionNumber) {
+      PCIE_INFO ("Scanning device B: %02d D: %02d F: %02d\n",
+                 BusNumber,
+                 DevNumber,
+                 FunctionNumber);
+
+      Status = PcieDevicePresent (
+                 &PciDevice,
+                 BusNumber,
+                 DevNumber,
+                 FunctionNumber);
+      if (Status == EFI_NOT_FOUND) {
+        PCIE_INFO ("No Pci device found\n");
+        Status = EFI_SUCCESS;
+        goto Exit;
+      } else if (EFI_ERROR (Status)) {
+        PCIE_ERROR ("Error detecting Pci device\n");
+        goto Exit;
+      }
+
+      Status = PcieConfigureDevice (
+                 PciDevice,
+                 BusNumber,
+                 DevNumber,
+                 FunctionNumber);
+      if (EFI_ERROR (Status)) {
+        PCIE_ERROR (
+          "Failed to configure device B:%02d D:%02d F:%02d\n",
+          BusNumber,
+          DevNumber,
+          FunctionNumber);
+        continue;
+      }
+
+      if (IS_PCI_BRIDGE (&PciDevice)) {
+        BusRegister = (UINT16) (((BusNumber + 1) << 8) | (UINT16)BusNumber);
+        Status = PcieGetPciConfigAddress (
+                   BusNumber,
+                   DevNumber,
+                   FunctionNumber,
+                   0,
+                   &BusBaseRegisterAddress);
+
+        ASSERT_EFI_ERROR (Status);
+
+        Status = PciePciWrite (
+                   EfiPciWidthUint16,
+                   BusBaseRegisterAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+                   1,
+                   &BusRegister);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR ("Failed to update bridge bus number %d\n", BusNumber);
+          continue;
+        }
+
+        // Temporarily set maximum subordinate bus number, although for now
+        // only support 2 buses.
+        SubBus = 0XFF;
+        Status = PciePciWrite (
+                   EfiPciWidthUint8,
+                   BusBaseRegisterAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET,
+                   1,
+                   &SubBus);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR ("Failed to update bridge bus number %d\n", BusNumber);
+          continue;
+        }
+
+        // Setup the memory base.
+        Status = PcieGetMemoryBarResource (
+                   0,
+                   &BridgeMemoryBase,
+                   TRUE);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR ("Failed to acquire BAR resource\n");
+          goto Exit;
+        }
+
+        BridgeMemory = (BridgeMemoryBase >> 16) & 0xFFF0;
+
+        Status = PciePciWrite (
+                   EfiPciIoWidthUint32,
+                   BusBaseRegisterAddress + 0x20,
+                   1,
+                   &BridgeMemory);
+        ASSERT_EFI_ERROR (Status);
+
+        Status = PcieSimpleScanBusAndAssignResource (
+                   BusNumber + 1);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR ("Failed to scan new bus %d\n", BusNumber + 1);
+          continue;
+        }
+
+        // Setup the memory limit.
+        Status = PcieGetMemoryBarResource (
+                   0,
+                   &ResourceAddress,
+                   TRUE);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR ("Failed to acquire BAR resource\n");
+          goto Exit;
+        }
+
+        ASSERT (BridgeMemoryBase != ResourceAddress);
+
+        // Per spec align address has to be 1MB boundary
+        PcieGetAlignAddress (
+          ResourceAddress,
+          0x00100000,
+          &BridgeMemoryLimit);
+        ASSERT_EFI_ERROR (Status);
+
+        BridgeMemory |= BridgeMemoryLimit;
+
+        Status = PciePciWrite (
+                   EfiPciIoWidthUint32,
+                   BusBaseRegisterAddress + 0x20,
+                   1,
+                   &BridgeMemory);
+        ASSERT_EFI_ERROR (Status);
+
+        SubBus = (BusNumber + 1);
+        Status = PciePciWrite (
+                   EfiPciWidthUint8,
+                   BusBaseRegisterAddress +
+                   PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET,
+                   1,
+                   &SubBus);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR (
+            "Failed to update subordinate bus number %d\n",
+            BusNumber);
+          continue;
+        }
+
+        // Claim any memory that is used for padding
+        Status = PcieGetMemoryBarResource (
+                   (BridgeMemoryLimit + 0x00100000) - ResourceAddress,
+                   &ResourceAddress,
+                   FALSE);
+        if (EFI_ERROR (Status)) {
+          PCIE_ERROR ("Failed to realign resource\n");
+          goto Exit;
+        }
+      }
+
+      // Skip sub functions, this is not a multi function device
+      if (FunctionNumber == 0 && !IS_PCI_MULTI_FUNC (&PciDevice)) {
+        FunctionNumber = PCI_MAX_FUNC;
+      }
+    }
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PcieInitialize (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTablePtr
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = PcieSetupInitSetting ();
+  if (EFI_ERROR (Status)) {
+    // EFI_DEVICE_ERROR indicates that a bootloader has already setup the
+    // Pcie controller. In this case just return success immediately
+    if (Status == EFI_DEVICE_ERROR) {
+      Status = EFI_SUCCESS;
+      PCIE_WARNING ("Pcie already initialized\n");
+      goto Exit;
+    }
+
+    PCIE_ERROR ("Failed to enable Pcie gates\n");
+    goto Exit;
+  }
+
+  Status = PcieSetClockGate (IMX_CLOCK_GATE_STATE_ON);
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to enable Pcie gates\n");
+    goto Exit;
+  }
+
+  Status = PcieVerifyClocks ();
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to verify Pcie clocks, not configured!\n");
+    goto Exit;
+  }
+
+  Status = PcieSetPhyState (TRUE);
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to enable Pcie PHY\n");
+    goto Exit;
+  }
+
+  // Very important to wait for Pcie PHY to settle here or the controller
+  // behaviour becomes unpredictable.
+  gBS->Stall (50000);
+
+  PcieEnablePerstLine ();
+
+  Status = PcieSetupPciBridge ();
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to setup Pci bridge\n");
+    goto Exit;
+  }
+
+  Status = PcieSetLinkStatus (TRUE);
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to enable Pcie link\n");
+    goto Exit;
+  }
+
+  Status = PcieWaitForLink ();
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Pci link never came up\n");
+    goto Exit;
+  }
+
+  PcieSetupiAtuSettings ();
+
+  // Start scanning from bus 0 onward
+  Status = PcieSimpleScanBusAndAssignResource (0);
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("PcieSimpleScanBusAndAssignResource failed %r\n", Status);
+    goto Exit;
+  }
+
+#ifdef DEBUG
+  volatile UINT32   *pPrintAddr;
+  UINT32            PrintIndex;
+
+  pPrintAddr = (UINT32 *)PCIE_HOST_CONFIG_BASE_REG;
+
+  PCIE_INFO ("===============================\n");
+  PCIE_INFO ("Host Device Configuration space\n");
+  PCIE_INFO ("===============================\n");
+  for (PrintIndex = 0; PrintIndex < 16; ++PrintIndex) {
+    PCIE_INFO ("PCI [%02x] 0x%08x 0x%08x 0x%08x 0x%08x\n", \
+                PrintIndex * 16, \
+                pPrintAddr[0], \
+                pPrintAddr[1], \
+                pPrintAddr[2], \
+                pPrintAddr[3]);
+
+    pPrintAddr += 4;
+  }
+
+  PCIE_INFO ("===============================\n");
+  PCIE_INFO ("Device Configuration space 0x%08x\n", pPrintAddr);
+  PCIE_INFO ("===============================\n");
+  for (PrintIndex = 0; PrintIndex < 16; ++PrintIndex) {
+    PCIE_INFO ("PCI [%02x] 0x%08x 0x%08x 0x%08x 0x%08x\n", \
+                PrintIndex * 16, \
+                pPrintAddr[0], \
+                pPrintAddr[1], \
+                pPrintAddr[2], \
+                pPrintAddr[3]);
+
+    pPrintAddr += 4;
+  }
+  PCIE_INFO ("===============================\n");
+#endif
+
+Exit:
+
+  if (EFI_ERROR (Status)) {
+    PCIE_ERROR ("Failed to initialize Pcie, disabling controller\n");
+    PcieSetLinkStatus (FALSE);
+    PcieSetPhyState (FALSE);
+    PcieSetClockGate (IMX_CLOCK_GATE_STATE_OFF);
+  }
+
+  // For debug printout the state of the PLL/PHY
+#ifdef DEBUG
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegs;
+  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcRegs;
+
+  pCcmAnalogRegs = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
+  pIoMuxcRegs = (IMX_IOMUXC_GPR_REGISTERS *)IMX_IOMUXC_BASE;
+
+  PCIE_INFO ( "IMX_CCM_PLL_ENET 0x%08X\n",
+              MmioRead32 ((UINTN) &pCcmAnalogRegs->PLL_ENET));
+  PCIE_INFO ( "IOMUXC_GPR1 0x%08X\n", MmioRead32 ((UINTN) &pIoMuxcRegs->GPR1));
+#endif
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
new file mode 100644
index 000000000000..029e93b277cf
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
@@ -0,0 +1,145 @@
+/** @file
+*
+*  Copyright (c) Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#pragma once
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(__array__) (sizeof((__array__))/sizeof((__array__[0])))
+#endif
+
+// Print macro
+#define PCIE_INIT(PRINT_OUT, ...) \
+    DEBUG((DEBUG_INIT, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
+#define PCIE_INFO(PRINT_OUT, ...) \
+    DEBUG((DEBUG_INFO, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
+#define PCIE_WARNING(PRINT_OUT, ...) \
+    DEBUG((DEBUG_WARN, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
+#define PCIE_ERROR(PRINT_OUT, ...) \
+    DEBUG((DEBUG_ERROR, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
+
+// PCIe related base address
+#define PCIE_HOST_CONFIG_BASE_REG       FixedPcdGet32(PcdPcieHostConfigBase)
+#define PCIE_CTRL_PORT_LOGIG_BASE_REG   0x01FFC700
+#define PCIE_DEVICE_CONFIG_BASE_REG     FixedPcdGet32(PcdPcieDeviceConfigBase)
+#define PCIE_DEVICE_CONFIG_SIZE         FixedPcdGet32(PcdPcieDeviceConfigSize)
+#define PCIE_IO_SPACE_BASE              FixedPcdGet32(PcdPcieIOBase)
+#define PCIE_IO_SPACE_SIZE              FixedPcdGet32(PcdPcieIOSize)
+#define PCIE_MEMORY_SPACE_BASE          FixedPcdGet32(PcdPciMemoryBase)
+#define PCIE_MEMORY_SPACE_SIZE          FixedPcdGet32(PcdPciMemorySize)
+#define PCIE_PREFETCH_MEMORY_SPACE_BASE FixedPcdGet32(PcdPciPrefetchMemoryBase)
+#define PCIE_PREFETCH_MEMORY_SPACE_SIZE FixedPcdGet32(PcdPciPrefetchMemorySize)
+
+#pragma pack(push, 1)
+
+typedef struct {
+  UINT64 Base;
+  UINT64 Size;
+  UINT64 Curr;
+} PCI_RESOURCE;
+
+// Debug register related bits
+#define PCIE_PL_DEBUG1_PHY_LINK_UP          (1 << 4)
+#define PCIE_PL_DEBUG1_LINK_IN_TRAINING     (1 << 29)
+
+// Address Translation Unit related definition
+#define MAX_iATU_REGION          4
+
+typedef enum _REGION_DIRECTION {
+  OUTBOUND,
+  INBOUND,
+} REGION_DIRECTION;
+
+typedef enum _TLP_TYPE {
+  MEMORY_TYPE,
+  MEMORY_LOCK_TYPE,
+  IO_TYPE,
+  CFG0_TYPE = 4,
+  CFG1_TYPE = 5,
+} TLP_TYPE;
+
+typedef enum _REGION_STATE {
+  REGION_DISABLE = 0,
+  REGION_ENABLE = 0x80000000,
+} REGION_STATE;
+
+typedef struct {
+  UINT32 PCIE_PL_ALTRTR;          // ACK latency timer and replay timer
+  UINT32 PCIE_PL_VSDR;            // Vendor specific DLLP
+  UINT32 PCIE_PL_PFLR;            // Port force link
+  UINT32 PCIE_PL_AFLACR;          // ACK frequency and L0-L1 ASPM control
+  UINT32 PCIE_PL_PLCR;            // Port link control
+  UINT32 PCIE_PL_LSR;             // Lane skew
+  UINT32 PCIE_PL_SNR;             // Symbol number
+  UINT32 PCIE_PL_STRFM1;          // Symbol timer and filter mask 1
+  UINT32 PCIE_PL_STRFM2;          // Filter mask 2
+  UINT32 PCIE_PL_AMODNPSR;        // AMBA Multiple Outbound Decomposed NP Sub-Requests
+                                  //   Control
+  UINT32 PCIE_PL_DEBUG0;          // Debug 0
+  UINT32 PCIE_PL_DEBUG1;          // Debug 1
+  UINT32 PCIE_PL_TPFCSR;          // Transmit Posted FC Credit Status
+  UINT32 PCIE_PL_TNFCSR;          // Transmit Non-Posted FC Credit Status
+  UINT32 PCIE_PL_TCFCSR;          // Transmit Completion FC Credit Status
+  UINT32 PCIE_PL_QSR;             // Queue status
+  UINT32 PCIE_PL_VCTAR1;          // Transmit Completion FC Status 1
+  UINT32 PCIE_PL_VCTAR2;          // Transmit Completion FC Status 1
+  UINT32 PCIE_PL_VC0PRQC;         // VC0 Posted Receive Queue Control
+  UINT32 PCIE_PL_VC0NRQC;         // VC0 Non-Posted Receive Queue Control
+  UINT32 PCIE_PL_VC0CRQC;         // VC0 Completion Receive Queue Control
+  UINT32 PCIE_PL_VCnPRQC;         // VCn Posted Receive Queue Control
+  UINT32 PCIE_PL_VCnNRQC;         // VCn Non-Posted Receive Queue Control
+  UINT32 PCIE_PL_VCnCRQC;         // VCn Completion Receive Queue Control
+  UINT32 PCIE_PL_RESERVED_0[18];
+  UINT32 PCIE_PL_VC0PBD;          // VC0 Posted Buffer Depth
+  UINT32 PCIE_PL_VC0NPBD;         // VC0 Non-Posted Buffer Depth
+  UINT32 PCIE_PL_VC0CBD;          // VC0 Completion Buffer Depth
+  UINT32 PCIE_PL_VC1PBD;          // VCn Posted Buffer Depth
+  UINT32 PCIE_PL_VC1NPBD;         // VCn Non-Posted Buffer Depth
+  UINT32 PCIE_PL_VC1CBD;          // VCn Completion Buffer Depth
+  UINT32 PCIE_PL_RESERVED_1[19];
+  UINT32 PCIE_PL_G2CR;            // Gen2 Control
+  UINT32 PCIE_PL_PHY_STATUS;      // PHY status
+  UINT32 PCIE_PL_PHY_CTRL;        // PHY control
+  UINT32 PCIE_PL_MRCCR0;          // Master Response Composer Control 0
+  UINT32 PCIE_PL_MRCCR1;          // Master Response Composer Control 1
+  UINT32 PCIE_PL_MSICA;           // MSI Controller Address
+  UINT32 PCIE_PL_MSICUA;          // MSI Controller Upper Address
+  UINT32 PCIE_PL_MSICIn_ENB;      // MSI Controller Interrupt n Enable
+  UINT32 PCIE_PL_MSICIn_MASK;     // MSI Controller Interrupt n Mask
+  UINT32 PCIE_PL_MSICIn_STATUS;   // MSI Controller Interrupt n Status
+  UINT32 PCIE_PL_RESERVED_2[21];
+  UINT32 PCIE_PL_MSICGPIO;        // MSI Controller General Purpose IO
+  UINT32 PCIE_PL_RESERVED_3[29];
+  UINT32 PCIE_PL_iATUVR;          // iATU Viewport
+  UINT32 PCIE_PL_iATURC1;         // iATU Control 1
+  UINT32 PCIE_PL_iATURC2;         // iATU Control 2
+  UINT32 PCIE_PL_iATURLBA;        // iATU Region Lower Base Address
+  UINT32 PCIE_PL_iATURUBA;        // iATU Region Upper Base Address
+  UINT32 PCIE_PL_iATURLA;         // iATU Region Limit Address
+  UINT32 PCIE_PL_iATURLTA;        // iATU Region Lower Target Address
+  UINT32 PCIE_PL_iATURUTA;        // iATU Region Upper Target Address
+} CSP_PCIE_PL_REGS, *PCSP_PCIE_PL_REGS;
+
+typedef struct _IATU_SETTINGS {
+  UINT32 RegionDirection;
+  UINT32 RegionIndex;
+  TLP_TYPE Type;
+  UINT32 LowerBaseAddr;
+  UINT32 UpperBaseAddr;
+  UINT32 LimitAddr;
+  UINT32 LowerTargetAddr;
+  UINT32 UpperTargetAddr;
+  UINT32 State;
+} IATU_SETTINGS, *PIATU_SETTINGS;
+
+#pragma pack(pop)
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
new file mode 100644
index 000000000000..99dbe9a4344e
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
@@ -0,0 +1,66 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION       = 0x0001001A
+  BASE_NAME         = iMX6PciExpress
+  FILE_GUID         = 5A7FB871-8A19-48D5-A268-441E79AAFD9E
+  MODULE_TYPE       = DXE_DRIVER
+  VERSION_STRING    = 1.0
+  ENTRY_POINT       = PcieInitialize
+
+[Sources.common]
+  iMX6PciExpress.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  IntelFrameworkPkg/IntelFrameworkPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DxeServicesTableLib
+  iMX6ClkPwrLib
+  IoLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+  UefiRuntimeServicesTableLib
+
+[Protocols]
+
+[Pcd]
+  giMX6TokenSpaceGuid.PcdPcieDeviceConfigBase
+  giMX6TokenSpaceGuid.PcdPcieDeviceConfigSize
+  giMX6TokenSpaceGuid.PcdPcieHostConfigBase
+  giMX6TokenSpaceGuid.PcdPcieIOBase
+  giMX6TokenSpaceGuid.PcdPcieIOSize
+  giMX6TokenSpaceGuid.PcdPciMemoryBase
+  giMX6TokenSpaceGuid.PcdPciMemorySize
+  giMX6TokenSpaceGuid.PcdPciPrefetchMemoryBase
+  giMX6TokenSpaceGuid.PcdPciPrefetchMemorySize
+  giMX6TokenSpaceGuid.PcdPcieResetGpio
+  giMX6TokenSpaceGuid.PcdPcieResetGpioBankNumber
+  giMX6TokenSpaceGuid.PcdPcieResetGpioIoNumber
+
+[FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
+
+[Depex]
+  gEfiCpuArchProtocolGuid AND gEfiMetronomeArchProtocolGuid
+
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 23/27] Silicon/NXP: Add i.MX6 Smbios Driver
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (20 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 21/27] Silicon/NXP: Add i.MX6 PCIe DXE driver Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 23:07   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver Chris Co
                   ` (5 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds support populating the SMBIOS tables on an i.MX6 SoC.
Platforms just need to define the relevant PCDs in their dsc file and
this driver will fill out the SMBIOS table structures.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c   | 1774 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h   |   44 +
 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf |   84 +
 3 files changed, 1902 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
new file mode 100644
index 000000000000..93c56dec254b
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
@@ -0,0 +1,1774 @@
+/** @file
+
+  Static SMBIOS Table for the SolidRun HummingBoard-Edge iMX6 Quad platform
+  Derived from EmulatorPkg package
+
+  Note SMBIOS 2.7.1 Required structures:
+    BIOS Information (Type 0)
+    System Information (Type 1)
+    Board Information (Type 2)
+    System Enclosure (Type 3)
+    Processor Information (Type 4) - CPU Driver
+    Cache Information (Type 7) - For cache that is external to processor
+    Physical Memory Array (Type 16)
+    Memory Device (Type 17) - For each socketed system-memory Device
+    Memory Array Mapped Address (Type 19) - One per contiguous block per Physical Memroy Array
+    System Boot Information (Type 32)
+
+  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012, Apple Inc. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, ARM Limited. All rights reserved.
+  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Guid/SmBios.h>
+
+#include <IndustryStandard/SmBios.h>
+
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/Smbios.h>
+
+#include "PlatformSmbiosDxe.h"
+
+// Default SMBIOS Tables for i.MX6
+SMBIOS_TABLE_TYPE0 mBiosInfoType0 = {
+  {
+    EFI_SMBIOS_TYPE_BIOS_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE0),
+    SMBIOS_HANDLE_PI_RESERVED
+  },
+  1,                    // Vendor String
+  2,                    // BiosVersion String
+  0xE000,               // BiosSegment
+  3,                    // BiosReleaseDate String
+  (FixedPcdGet32 (PcdFdSize) - 1) / SIZE_64KB, // BiosSize
+  {       // BiosCharacteristics
+    0,    //  Reserved                          :2;
+    0,    //  Unknown                           :1;
+    0,    //  BiosCharacteristicsNotSupported   :1;
+    0,    //  IsaIsSupported                    :1;
+    0,    //  McaIsSupported                    :1;
+    0,    //  EisaIsSupported                   :1;
+    1,    //  PciIsSupported                    :1;
+    0,    //  PcmciaIsSupported                 :1;
+    0,    //  PlugAndPlayIsSupported            :1;
+    0,    //  ApmIsSupported                    :1;
+    1,    //  BiosIsUpgradable                  :1;
+    0,    //  BiosShadowingAllowed              :1;
+    0,    //  VlVesaIsSupported                 :1;
+    0,    //  EscdSupportIsAvailable            :1;
+    0,    //  BootFromCdIsSupported             :1;
+    1,    //  SelectableBootIsSupported         :1;
+    0,    //  RomBiosIsSocketed                 :1;
+    0,    //  BootFromPcmciaIsSupported         :1;
+    0,    //  EDDSpecificationIsSupported       :1;
+    0,    //  JapaneseNecFloppyIsSupported      :1;
+    0,    //  JapaneseToshibaFloppyIsSupported  :1;
+    0,    //  Floppy525_360IsSupported          :1;
+    0,    //  Floppy525_12IsSupported           :1;
+    0,    //  Floppy35_720IsSupported           :1;
+    0,    //  Floppy35_288IsSupported           :1;
+    0,    //  PrintScreenIsSupported            :1;
+    0,    //  Keyboard8042IsSupported           :1;
+    0,    //  SerialIsSupported                 :1;
+    0,    //  PrinterIsSupported                :1;
+    0,    //  CgaMonoIsSupported                :1;
+    0,    //  NecPc98                           :1;
+    0     //  ReservedForVendor                 :32;
+  },
+  {       // BIOSCharacteristicsExtensionBytes[]
+    0x01, //  AcpiIsSupported                   :1;
+          //  UsbLegacyIsSupported              :1;
+          //  AgpIsSupported                    :1;
+          //  I2OBootIsSupported                :1;
+          //  Ls120BootIsSupported              :1;
+          //  AtapiZipDriveBootIsSupported      :1;
+          //  Boot1394IsSupported               :1;
+          //  SmartBatteryIsSupported           :1;
+    0x0C, //  BiosBootSpecIsSupported           :1;
+          //  FunctionKeyNetworkBootIsSupported :1;
+          //  TargetContentDistributionEnabled  :1;
+          //  UefiSpecificationSupported        :1;
+          //  VirtualMachineSupported           :1;
+          //  ExtensionByte2Reserved            :3;
+  },
+  FixedPcdGet32 (PcdFirmwareRevision) >> 16, // SystemBiosMajorRelease
+  FixedPcdGet32 (PcdFirmwareRevision) & 0xff, // SystemBiosMinorRelease
+  0xFF,   // EmbeddedControllerFirmwareMajorRelease
+  0xFF,   // EmbeddedControllerFirmwareMinorRelease
+};
+
+SMBIOS_TABLE_TYPE1 mSysInfoType1 = {
+  {
+    EFI_SMBIOS_TYPE_SYSTEM_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE1),
+    SMBIOS_HANDLE_PI_RESERVED
+  },
+  1,    // Manufacturer String
+  2,    // ProductName String
+  3,    // Version String
+  4,    // SerialNumber String
+  { 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } },
+  SystemWakeupTypePowerSwitch, // WakeUp Type
+  5,    // SKUNumber String
+  6,    // Family String
+};
+
+SMBIOS_TABLE_TYPE2 mBoardInfoType2 = {
+  {
+    EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE2),
+    SMBIOS_HANDLE_BOARD
+  },
+  1,      // Manufacturer String
+  2,      // ProductName String
+  3,      // Version String
+  4,      // SerialNumber String
+  5,      // AssetTag String
+  {       // FeatureFlag
+    1,    //  Motherboard           :1;
+    0,    //  RequiresDaughterCard  :1;
+    0,    //  Removable             :1;
+    0,    //  Replaceable           :1;
+    0,    //  HotSwappable          :1;
+    0,    //  Reserved              :3;
+  },
+  6,                        // LocationInChassis String
+  SMBIOS_HANDLE_CHASSIS,    // ChassisHandle;
+  BaseBoardTypeMotherBoard, // BoardType;
+  1,                        // NumberOfContainedObjectHandles;
+  { SMBIOS_HANDLE_PROCESSOR } // ContainedObjectHandles[1];
+};
+
+SMBIOS_TABLE_TYPE3 mEnclosureInfoType3 = {
+  {
+    EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE,
+    sizeof (SMBIOS_TABLE_TYPE3),
+    SMBIOS_HANDLE_CHASSIS
+  },
+  1,                          // Manufacturer String
+  MiscChassisTypeOther,       // Type;
+  2,                          // Version String
+  3,                          // SerialNumber String
+  4,                          // AssetTag String
+  ChassisStateSafe,           // BootupState;
+  ChassisStateSafe,           // PowerSupplyState;
+  ChassisStateSafe,           // ThermalState;
+  ChassisSecurityStatusNone,  // SecurityStatus;
+  { 0, 0, 0, 0 },             // OemDefined[4];
+  0,                          // Height;
+  0,                          // NumberofPowerCords;
+  0,                          // ContainedElementCount;
+  0,                          // ContainedElementRecordLength;
+  { { 0 } },                  // ContainedElements[1];
+};
+
+SMBIOS_TABLE_TYPE4 mProcessorInfoType4 = {
+  {
+    EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE4),
+    SMBIOS_HANDLE_PROCESSOR
+  },
+  1,                                // Socket String;
+  CentralProcessor,                 // ProcessorType;
+  ProcessorFamilyIndicatorFamily2,  // ProcessorFamily;
+  2,                                // ProcessorManufacture String;
+  {{0,},{0.}}, // ProcessorId;
+  3,      // ProcessorVersion String;
+  {       // Voltage;
+    1,    // ProcessorVoltageCapability5V        :1;
+    1,    // ProcessorVoltageCapability3_3V      :1;
+    1,    // ProcessorVoltageCapability2_9V      :1;
+    0,    // ProcessorVoltageCapabilityReserved  :1;
+    0,    // ProcessorVoltageReserved            :3;
+    0     // ProcessorVoltageIndicateLegacy      :1;
+  },
+  0,                      // ExternalClock;
+  0,                      // MaxSpeed;
+  0,                      // CurrentSpeed;
+  0x41,                   // Status;
+  ProcessorUpgradeOther,  // ProcessorUpgrade;
+  SMBIOS_HANDLE_L1I,      // L1CacheHandle;
+  SMBIOS_HANDLE_L2U,      // L2CacheHandle;
+  0xFFFF,                 // L3CacheHandle;
+  4,                      // SerialNumber;
+  5,                      // AssetTag;
+  6,                      // PartNumber;
+  0,                      // CoreCount;
+  0,                      // EnabledCoreCount;
+  0,                      // ThreadCount;
+  0,                      // ProcessorCharacteristics;
+  ProcessorFamilyARMv7,   // ProcessorFamily2;
+};
+
+SMBIOS_TABLE_TYPE7 mCacheInfoType7L1I = {
+  {
+    EFI_SMBIOS_TYPE_CACHE_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE7),
+    SMBIOS_HANDLE_L1I
+  },
+  1,      // SocketDesignation String
+  0x0180, // Cache Configuration
+  0x0020, // Maximum Size 32k
+  0x0020, // Install Size 32k
+  {       // Supported SRAM Type
+    0,    //Other             :1
+    0,    //Unknown           :1
+    0,    //NonBurst          :1
+    1,    //Burst             :1
+    0,    //PiplelineBurst    :1
+    1,    //Synchronous       :1
+    0,    //Asynchronous      :1
+    0     //Reserved          :9
+  },
+  {       // Current SRAM Type
+    0,    //Other             :1
+    0,    //Unknown           :1
+    0,    //NonBurst          :1
+    1,    //Burst             :1
+    0,    //PiplelineBurst    :1
+    1,    //Synchronous       :1
+    0,    //Asynchronous      :1
+    0     //Reserved          :9
+  },
+  0,                      // Cache Speed unknown
+  CacheErrorMultiBit,     // Error Correction Multi
+  CacheTypeInstruction,   // System Cache Type
+  CacheAssociativity2Way  // Associativity
+};
+
+SMBIOS_TABLE_TYPE7 mCacheInfoType7L1D = {
+  {
+    EFI_SMBIOS_TYPE_CACHE_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE7),
+    SMBIOS_HANDLE_L1D
+  },
+  1,      // SocketDesignation String
+  0x0180, // Cache Configuration
+  0x0020, // Maximum Size 32k
+  0x0020, // Install Size 32k
+  {       // Supported SRAM Type
+    0,    //Other             :1
+    0,    //Unknown           :1
+    0,    //NonBurst          :1
+    1,    //Burst             :1
+    0,    //PiplelineBurst    :1
+    1,    //Synchronous       :1
+    0,    //Asynchronous      :1
+    0     //Reserved          :9
+  },
+  {       // Current SRAM Type
+    0,    //Other             :1
+    0,    //Unknown           :1
+    0,    //NonBurst          :1
+    1,    //Burst             :1
+    0,    //PiplelineBurst    :1
+    1,    //Synchronous       :1
+    0,    //Asynchronous      :1
+    0     //Reserved          :9
+  },
+  0,                      // Cache Speed unknown
+  CacheErrorMultiBit,     // Error Correction Multi
+  CacheTypeData,          // System Cache Type
+  CacheAssociativity2Way  // Associativity
+};
+
+SMBIOS_TABLE_TYPE7 mCacheInfoType7L2U = {
+  {
+    EFI_SMBIOS_TYPE_CACHE_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE7),
+    SMBIOS_HANDLE_L2U
+  },
+  1,      // SocketDesignation String
+  0x0181, // Cache Configuration
+  0,      // Maximum Size
+  0,      // Install Size
+  {       // Supported SRAM Type
+    0,    //Other             :1
+    0,    //Unknown           :1
+    0,    //NonBurst          :1
+    1,    //Burst             :1
+    0,    //PiplelineBurst    :1
+    1,    //Synchronous       :1
+    0,    //Asynchronous      :1
+    0     //Reserved          :9
+  },
+  {       // Current SRAM Type
+    0,    //Other             :1
+    0,    //Unknown           :1
+    0,    //NonBurst          :1
+    1,    //Burst             :1
+    0,    //PiplelineBurst    :1
+    1,    //Synchronous       :1
+    0,    //Asynchronous      :1
+    0     //Reserved          :9
+  },
+  0,                      // Cache Speed unknown
+  CacheErrorMultiBit,     // Error Correction Multi
+  CacheTypeUnified,       // System Cache Type
+  CacheAssociativity2Way  // Associativity
+};
+
+SMBIOS_TABLE_TYPE16 mPhysicalMemoryArrayInfoType16 = {
+  {
+    EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY,
+    sizeof (SMBIOS_TABLE_TYPE16),
+    SMBIOS_HANDLE_MEMORY_ARRAY
+  },
+  MemoryArrayLocationSystemBoard, // Location;
+  MemoryArrayUseSystemMemory,     // Use;
+  MemoryErrorCorrectionNone,      // MemoryErrorCorrection;
+  0x80000000,                     // MaximumCapacity
+  0xFFFE,                         // MemoryErrorInformationHandle;
+  1,                              // NumberOfMemoryDevices;
+  0x80000000ULL,                  // ExtendedMaximumCapacity
+};
+
+SMBIOS_TABLE_TYPE17 mMemoryDeviceInfoType17 = {
+  {
+    EFI_SMBIOS_TYPE_MEMORY_DEVICE,
+    sizeof (SMBIOS_TABLE_TYPE17),
+    SMBIOS_HANDLE_MEMORY_DEVICE
+  },
+  SMBIOS_HANDLE_MEMORY_ARRAY, // MemoryArrayHandle;
+  0xFFFE,     // MemoryErrorInformationHandle;
+  0xFFFF,     // TotalWidth;
+  0xFFFF,     // DataWidth;
+  0xFFFF,     // Size; When bit 15 is 0: Size in MB
+              // When bit 15 is 1: Size in KB, and continues in ExtendedSize
+  MemoryFormFactorRowOfChips,  // FormFactor;
+  0,                        // DeviceSet;
+  1,                        // DeviceLocator String
+  2,                        // BankLocator String
+  MemoryTypeDdr3,           // MemoryType;
+  {           // TypeDetail;
+    0,        // Reserved        :1;
+    0,        // Other           :1;
+    0,        // Unknown         :1;
+    0,        // FastPaged       :1;
+    0,        // StaticColumn    :1;
+    0,        // PseudoStatic    :1;
+    0,        // Rambus          :1;
+    0,        // Synchronous     :1;
+    0,        // Cmos            :1;
+    0,        // Edo             :1;
+    0,        // WindowDram      :1;
+    0,        // CacheDram       :1;
+    0,        // Nonvolatile     :1;
+    0,        // Registered      :1;
+    1,        // Unbuffered      :1;
+    0,        // Reserved1       :1;
+  },
+  0,          // Speed;
+  0,          // Manufacturer String
+  0,          // SerialNumber String
+  0,          // AssetTag String
+  0,          // PartNumber String
+  0,          // Attributes;
+  0,          // ExtendedSize;
+  0,          // ConfiguredMemoryClockSpeed;
+};
+
+SMBIOS_TABLE_TYPE19 mMemoryArrayMappedInfoType19 = {
+  {
+    EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS,
+    sizeof (SMBIOS_TABLE_TYPE19),
+    SMBIOS_HANDLE_PI_RESERVED
+  },
+  0xFFFFFFFF, // StartingAddress;
+  0xFFFFFFFF, // EndingAddress;
+  SMBIOS_HANDLE_MEMORY_ARRAY, // MemoryArrayHandle;
+  1,          // PartitionWidth;
+  0xFFFFFFFF, // ExtendedStartingAddress;
+  0xFFFFFFFF, // ExtendedEndingAddress;
+};
+
+SMBIOS_TABLE_TYPE32 mBootInfoType32 = {
+  {
+    EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION,
+    sizeof (SMBIOS_TABLE_TYPE32),
+    SMBIOS_HANDLE_PI_RESERVED
+  },
+  { 0, 0, 0, 0, 0, 0 },         // Reserved[6];
+  BootInformationStatusNoError  // BootStatus
+};
+
+struct MonthDescription {
+  CONST CHAR8* MonthStr;
+  UINT32    MonthInt;
+} gMonthDescription[] = {
+  { "Jan", 1 },
+  { "Feb", 2 },
+  { "Mar", 3 },
+  { "Apr", 4 },
+  { "May", 5 },
+  { "Jun", 6 },
+  { "Jul", 7 },
+  { "Aug", 8 },
+  { "Sep", 9 },
+  { "Oct", 10 },
+  { "Nov", 11 },
+  { "Dec", 12 },
+  { "???", 1 },  // Use 1 as default month
+};
+
+EFI_STATUS
+LogSmbiosData (
+  IN       UINT8                      *Buffer,
+  IN  OUT  EFI_SMBIOS_HANDLE          *SmbiosHandle
+  )
+{
+  EFI_STATUS         Status;
+  EFI_SMBIOS_PROTOCOL       *Smbios;
+
+  *SmbiosHandle = ((EFI_SMBIOS_TABLE_HEADER *)Buffer)->Handle;
+  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Smbios->Add (
+                    Smbios,
+                    NULL,
+                    SmbiosHandle,
+                    (EFI_SMBIOS_TABLE_HEADER *)Buffer
+                    );
+
+  return Status;
+}
+
+VOID
+GetReleaseTime (
+  EFI_TIME *Time
+  )
+{
+  CONST CHAR8      *ReleaseDate = __DATE__;
+  CONST CHAR8      *ReleaseTime = __TIME__;
+  UINTN            i;
+
+  for (i = 0; i < 12; i++) {
+    if (0 == AsciiStrnCmp (ReleaseDate, gMonthDescription[i].MonthStr, 3)) {
+      break;
+    }
+  }
+  Time->Month = gMonthDescription[i].MonthInt;
+  Time->Day = AsciiStrDecimalToUintn (ReleaseDate + 4);
+  Time->Year = AsciiStrDecimalToUintn (ReleaseDate + 7);
+  Time->Hour = AsciiStrDecimalToUintn (ReleaseTime);
+  Time->Minute = AsciiStrDecimalToUintn (ReleaseTime + 3);
+  Time->Second = AsciiStrDecimalToUintn (ReleaseTime + 6);
+
+  return;
+}
+
+UINT64
+GetImx6SerialNumber (
+  VOID
+  )
+{
+  UINT64 ProcessorSerialNumber;
+
+  ProcessorSerialNumber = ((UINT64)MmioRead32 (OCOTP_BANK_0_WORD_2)) << 32;
+  ProcessorSerialNumber |=(UINT64)MmioRead32 (OCOTP_BANK_0_WORD_1);
+
+  DEBUG ((DEBUG_INFO, "iMX6 Serial Number %08X%08Xh \r\n",
+          (UINT32) (ProcessorSerialNumber >> 32), (UINT32)ProcessorSerialNumber));
+  return ProcessorSerialNumber;
+}
+
+EFI_STATUS
+BiosInfoUpdateSmbiosType0 (
+  VOID
+  )
+{
+  CHAR8                 *OptionalStrStart;
+  CHAR16                *ReleaseDate;
+  SMBIOS_TABLE_TYPE0    *SmbiosRecord;
+  CHAR16                *Vendor;
+  CHAR16                *Version;
+  UINTN                 ReleaseDateLen;
+  UINT32                Revision;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+  UINTN                 VendorLen;
+  UINTN                 VersionLen;
+  EFI_TIME              Time;
+
+  Version = NULL;
+  ReleaseDate = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE0);
+
+  // 04h - Vendor Name String
+  Vendor = (CHAR16 *)FixedPcdGetPtr (PcdFirmwareVendor);
+  VendorLen = StrLen (Vendor);
+  if (VendorLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdFirmwareVendor not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += VendorLen + 1;
+
+  // 05h - BIOS Version string
+  Revision = FixedPcdGet32 (PcdFirmwareRevision);
+  if (Revision == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdFirmwareRevision not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  GetReleaseTime (&Time);
+
+  Version = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+  if (Version == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (
+    Version,
+    (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH,
+    "\nBoot firmware (version %x built on %t)\n",
+    Revision,
+    &Time
+    );
+  VersionLen = StrLen(Version);
+  SmbiosRecordLen += VersionLen + 1;
+
+  // 08h - BIOS Release Date must be in mm/dd/yyyy format
+  ReleaseDate = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+  if (ReleaseDate == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat ( ReleaseDate,
+                        (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH,
+                        "%02d/%02d/%4d",
+                        Time.Month,
+                        Time.Day,
+                        Time.Year
+                        );
+  ReleaseDateLen = StrLen(ReleaseDate);
+  SmbiosRecordLen += ReleaseDateLen + 1;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mBiosInfoType0, sizeof (SMBIOS_TABLE_TYPE0));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (Vendor, OptionalStrStart);
+  OptionalStrStart += VendorLen + 1;
+  UnicodeStrToAsciiStr (Version, OptionalStrStart);
+  OptionalStrStart += VersionLen + 1;
+  UnicodeStrToAsciiStr (ReleaseDate, OptionalStrStart);
+
+  // Commit SMBIOS entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (Version != NULL) {
+    FreePool (Version);
+  }
+  if (ReleaseDate != NULL) {
+    FreePool (ReleaseDate);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+SysInfoUpdateSmbiosType1 (
+  VOID
+  )
+{
+  CHAR16                *Family;
+  GLOBAL_PAGE_DATA      *GlobalDataAddress;
+  CHAR16                *Manufacturer;
+  CHAR8                 *OptionalStrStart;
+  CHAR16                *ProductName;
+  CHAR16                *SerialNumber;
+  CHAR16                *SkuNumber;
+  SMBIOS_TABLE_TYPE1    *SmbiosRecord;
+  EFI_GUID              *SystemUuidFromPcd;
+  EFI_GUID              *SystemUuid;
+  CHAR16                *Version;
+  UINT64                ProcessorSerialNumber;
+  UINTN                 FamilyLen;
+  UINT32                i;
+  UINTN                 ManufacturerLen;
+  UINTN                 ProductNameLen;
+  UINTN                 SerialNumberLen;
+  UINTN                 SkuNumberLen;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+  UINTN                 VersionLen;
+
+  SerialNumber = NULL;
+  SmbiosRecord = NULL;
+  SystemUuid = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE1);
+
+  // 04h - Manufacturer String
+  Manufacturer = (CHAR16 *)FixedPcdGetPtr (PcdSystemManufacturer);
+  ManufacturerLen = StrLen (Manufacturer);
+  if (ManufacturerLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdSystemManufacturer not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += ManufacturerLen + 1;
+
+  // 05h - Product Name String
+  ProductName = (CHAR16 *)FixedPcdGetPtr (PcdSystemProductName);
+  ProductNameLen = StrLen (ProductName);
+  if (ProductNameLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdSystemProductName not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += ProductNameLen + 1;
+
+  // 06h - Version String
+  Version = (CHAR16 *)FixedPcdGetPtr (PcdSystemVersionNumber);
+  VersionLen = StrLen (Version);
+  if (VersionLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdSystemVersionNumber not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += VersionLen + 1;
+
+  // 07h - Serial Number String
+  ProcessorSerialNumber = GetImx6SerialNumber ();
+  SerialNumber = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SerialNumber == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SerialNumber,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "%08X%08X",
+                                  (UINT32)(ProcessorSerialNumber >> 32),
+                                  (UINT32)ProcessorSerialNumber
+                                  );
+  SerialNumberLen = StrLen (SerialNumber);
+  SmbiosRecordLen += SerialNumberLen + 1;
+
+  // 08h - UUID
+  // RFC4122 - Initial UUID must be the same across all boards of the same type
+  //   And the last 6 bytes are to be populated with system's MAC Address
+  SystemUuidFromPcd = (EFI_GUID *)FixedPcdGetPtr (PcdSystemUuid);
+  SystemUuid = AllocateZeroPool (sizeof (EFI_GUID));
+  if (SystemUuid == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  CopyMem (SystemUuid, SystemUuidFromPcd, sizeof (EFI_GUID));
+
+  GlobalDataAddress = (GLOBAL_PAGE_DATA *)FixedPcdGet32 (PcdGlobalDataBaseAddress);
+  if (GlobalDataAddress == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdGlobalDataBaseAddress not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  // Verify signature and version of global page
+  if (GlobalDataAddress->Signature != GLOBAL_PAGE_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "%a: Global Page Signature mismatch.\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (GlobalDataAddress->Revision > 1) {
+    DEBUG ((DEBUG_ERROR, "%a: Global Page Revision mismatch.\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  // Check validity of Mac address and assign to UUID
+  if (GlobalDataAddress->Mac0Valid == TRUE) {
+    for (i = 0; i < 6; i++) {
+      SystemUuid->Data4[i + 2] = GlobalDataAddress->MacAddress[i];
+    }
+  } else {
+    DEBUG ((DEBUG_ERROR, "%a: Mac Address not present.\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  mSysInfoType1.Uuid = *SystemUuid;
+
+  // 19h - SKU Number String
+  SkuNumber = (CHAR16 *)FixedPcdGetPtr (PcdSystemSkuNumber);
+  SkuNumberLen = StrLen (SkuNumber);
+  if (SkuNumberLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdSystemSkuNumber not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += SkuNumberLen + 1;
+
+  // 1Ah - Family String
+  Family = (CHAR16 *)FixedPcdGetPtr (PcdSystemFamily);
+  FamilyLen = StrLen (Family);
+  if (FamilyLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdSystemFamily not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += FamilyLen + 1;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mSysInfoType1, sizeof (SMBIOS_TABLE_TYPE1));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (Manufacturer, OptionalStrStart);
+  OptionalStrStart += ManufacturerLen + 1;
+  UnicodeStrToAsciiStr (ProductName, OptionalStrStart);
+  OptionalStrStart += ProductNameLen + 1;
+  UnicodeStrToAsciiStr (Version, OptionalStrStart);
+  OptionalStrStart += VersionLen + 1;
+  UnicodeStrToAsciiStr (SerialNumber, OptionalStrStart);
+  OptionalStrStart += SerialNumberLen + 1;
+  UnicodeStrToAsciiStr (SkuNumber, OptionalStrStart);
+  OptionalStrStart += SkuNumberLen + 1;
+  UnicodeStrToAsciiStr (Family, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+  if (SystemUuid != NULL) {
+    FreePool (SystemUuid);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+BoardInfoUpdateSmbiosType2 (
+  VOID
+  )
+{
+  CHAR16                *AssetTag;
+  CHAR16                *Location;
+  CHAR16                *Manufacturer;
+  CHAR8                 *OptionalStrStart;
+  CHAR16                *ProductName;
+  CHAR16                *SerialNumber;
+  SMBIOS_TABLE_TYPE2    *SmbiosRecord;
+  CHAR16                *Version;
+  UINTN                 AssetTagLen;
+  UINT64                ProcessorSerialNumber;
+  UINTN                 LocationLen;
+  UINTN                 ManufacturerLen;
+  UINTN                 ProductNameLen;
+  UINTN                 SerialNumberLen;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+  UINTN                 VersionLen;
+
+  SerialNumber = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE2);
+
+  // 04h - Manufacturer String
+  Manufacturer = (CHAR16 *)FixedPcdGetPtr (PcdBoardManufacturer);
+  ManufacturerLen = StrLen (Manufacturer);
+  if (ManufacturerLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdBoardManufacturer not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += ManufacturerLen + 1;
+
+  // 05h - Product Name String
+  ProductName = (CHAR16 *)FixedPcdGetPtr (PcdBoardProductName);
+  ProductNameLen = StrLen (ProductName);
+  if (ProductNameLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdBoardProductName not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += ProductNameLen + 1;
+
+  // 06h - Version String
+  Version = (CHAR16 *)FixedPcdGetPtr (PcdBoardVersionNumber);
+  VersionLen = StrLen (Version);
+  if (VersionLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdBoardVersionNumber not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += VersionLen + 1;
+
+  // 07h - Serial Number String
+  ProcessorSerialNumber = GetImx6SerialNumber ();
+  SerialNumber = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SerialNumber == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SerialNumber,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "%08X%08X",
+                                  (UINT32)(ProcessorSerialNumber >> 32),
+                                  (UINT32)ProcessorSerialNumber
+                                  );
+  SerialNumberLen = StrLen (SerialNumber);
+  SmbiosRecordLen += SerialNumberLen + 1;
+
+  // 08h - Asset Tag String
+  AssetTag = (CHAR16 *)FixedPcdGetPtr (PcdBoardAssetTag);
+  AssetTagLen = StrLen (AssetTag);
+  if (AssetTagLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdBoardAssetTag not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += AssetTagLen + 1;
+
+  // 0Ah - Location in Chassis String
+  Location = (CHAR16 *)FixedPcdGetPtr (PcdBoardLocationInChassis);
+  LocationLen = StrLen (Location);
+  if (LocationLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdBoardLocationInChassis not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += LocationLen + 1;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mBoardInfoType2, sizeof (SMBIOS_TABLE_TYPE2));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (Manufacturer, OptionalStrStart);
+  OptionalStrStart += ManufacturerLen + 1;
+  UnicodeStrToAsciiStr (ProductName, OptionalStrStart);
+  OptionalStrStart += ProductNameLen + 1;
+  UnicodeStrToAsciiStr (Version, OptionalStrStart);
+  OptionalStrStart += VersionLen + 1;
+  UnicodeStrToAsciiStr (SerialNumber, OptionalStrStart);
+  OptionalStrStart += SerialNumberLen + 1;
+  UnicodeStrToAsciiStr (AssetTag, OptionalStrStart);
+  OptionalStrStart += AssetTagLen + 1;
+  UnicodeStrToAsciiStr (Location, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+EnclosureInfoUpdateSmbiosType3 (
+  VOID
+  )
+{
+  CHAR16                *AssetTag;
+  CHAR16                *Manufacturer;
+  CHAR8                 *OptionalStrStart;
+  CHAR16                *SerialNumber;
+  SMBIOS_TABLE_TYPE3    *SmbiosRecord;
+  CHAR16                *Version;
+  UINTN                 AssetTagLen;
+  UINT64                ProcessorSerialNumber;
+  UINTN                 ManufacturerLen;
+  UINTN                 SerialNumberLen;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+  UINTN                 VersionLen;
+
+  SerialNumber = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE3);
+
+  // 04h - Manufacturer String
+  Manufacturer = (CHAR16 *)FixedPcdGetPtr (PcdChassisManufacturer);
+  ManufacturerLen = StrLen (Manufacturer);
+  if (ManufacturerLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdChassisManufacturer not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += ManufacturerLen + 1;
+
+  // 06h - Version String
+  Version = (CHAR16 *)FixedPcdGetPtr (PcdChassisVersionNumber);
+  VersionLen = StrLen (Version);
+  if (VersionLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdChassisVersionNumber not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += VersionLen + 1;
+
+  // 07h - Serial Number String
+  ProcessorSerialNumber = GetImx6SerialNumber ();
+  SerialNumber = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SerialNumber == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SerialNumber,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "%08X%08X",
+                                  (UINT32)(ProcessorSerialNumber >> 32),
+                                  (UINT32)ProcessorSerialNumber
+                                  );
+  SerialNumberLen = StrLen (SerialNumber);
+  SmbiosRecordLen += SerialNumberLen + 1;
+
+  // 08h - Asset Tag String
+  AssetTag = (CHAR16 *)FixedPcdGetPtr (PcdChassisAssetTag);
+  AssetTagLen = StrLen (AssetTag);
+  if (AssetTagLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdChassisAssetTag not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += AssetTagLen + 1;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mEnclosureInfoType3, sizeof (SMBIOS_TABLE_TYPE3));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (Manufacturer, OptionalStrStart);
+  OptionalStrStart += ManufacturerLen + 1;
+  UnicodeStrToAsciiStr (Version, OptionalStrStart);
+  OptionalStrStart += VersionLen + 1;
+  UnicodeStrToAsciiStr (SerialNumber, OptionalStrStart);
+  OptionalStrStart += SerialNumberLen + 1;
+  UnicodeStrToAsciiStr (AssetTag, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+ProcessorInfoUpdateSmbiosType4 (
+  IN  UINTN   MaxCpus
+  )
+{
+  CHAR16                *AssetTag;
+  CHAR16                *Manufacturer;
+  CHAR8                 *OptionalStrStart;
+  CHAR16                *PartNumber;
+  CHAR16                *SerialNumber;
+  SMBIOS_TABLE_TYPE4    *SmbiosRecord;
+  CHAR16                *SocketDesignation;
+  CHAR16                *Version;
+  UINT32                ArmMidr;
+  UINTN                 AssetTagLen;
+  UINTN                 i;
+  UINT32                Midr;
+  UINT64                ProcessorSerialNumber;
+  UINTN                 ManufacturerLen;
+  UINTN                 PartNumberLen;
+  UINTN                 SerialNumberLen;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  UINTN                 SocketDesignationLen;
+  EFI_STATUS            Status;
+  UINTN                 VersionLen;
+
+  SerialNumber = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE4);
+  Midr = 0;
+
+  // 04h - Socket Designation String
+  SocketDesignation = (CHAR16 *)FixedPcdGetPtr (PcdProcessorSocketDesignation);
+  SocketDesignationLen = StrLen (SocketDesignation);
+  if (SocketDesignationLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdProcessorSocketDesignation not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += SocketDesignationLen + 1;
+
+  // 07h - Processor Manufacturer String
+  Manufacturer = (CHAR16 *)FixedPcdGetPtr (PcdProcessorManufacturer);
+  ManufacturerLen = StrLen (Manufacturer);
+  if (ManufacturerLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdProcessorManufacturer not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += ManufacturerLen + 1;
+
+  // 08h - Processor ID - On ARM32, first DWORD is MIDR value. Second DWORD is 0
+  ArmMidr = (UINT32)ArmReadMidr ();
+  DEBUG ((DEBUG_INFO, "%a: ArmMidr = %x\n", __FUNCTION__, ArmMidr));
+  // Need to reverse byte order so the value is populated correctly
+  for (i = 0; i < 32; i += 8) {
+    Midr |= ((ArmMidr >> i) & 0xFF) << (24-i);
+  }
+  CopyMem(&mProcessorInfoType4.ProcessorId.Signature, &Midr, sizeof (UINT32));
+
+  // 10h - Processor Version String
+  Version = (CHAR16 *)FixedPcdGetPtr (PcdProcessorVersionNumber);
+  VersionLen = StrLen (Version);
+  if (VersionLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdProcessorVersionNumber not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += VersionLen + 1;
+
+  // 14h - Max Speed
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  mProcessorInfoType4.MaxSpeed = 1200;
+  mProcessorInfoType4.CurrentSpeed = 1200;
+#elif defined(CPU_IMX6SDL) || defined(CPU_IMX6SX)
+  mProcessorInfoType4.MaxSpeed = 1000;
+  mProcessorInfoType4.CurrentSpeed = 1000;
+#else
+  #error iMX6 CPU Type not defined
+#endif
+
+  // 20h - Processor Serial Number String
+  ProcessorSerialNumber = GetImx6SerialNumber ();
+  SerialNumber = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SerialNumber == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SerialNumber,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "%08X%08X",
+                                  (UINT32)(ProcessorSerialNumber >> 32),
+                                  (UINT32)ProcessorSerialNumber
+                                  );
+  SerialNumberLen = StrLen (SerialNumber);
+  SmbiosRecordLen += SerialNumberLen + 1;
+
+  // 21h - Asset Tag String
+  AssetTag = (CHAR16 *)FixedPcdGetPtr (PcdProcessorAssetTag);
+  AssetTagLen = StrLen (AssetTag);
+  if (AssetTagLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdProcessorAssetTag not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += AssetTagLen + 1;
+
+  // 22h - Part Number String
+  PartNumber = (CHAR16 *)FixedPcdGetPtr (PcdProcessorPartNumber);
+  PartNumberLen = StrLen (PartNumber);
+  if (PartNumberLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdProcessorPartNumber not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += PartNumberLen + 1;
+
+  // 23h - Core Count
+  // 24h - Core Enabled
+  // 25h - Thread Count
+  mProcessorInfoType4.CoreCount        = (UINT8) MaxCpus;
+  mProcessorInfoType4.EnabledCoreCount = (UINT8) MaxCpus;
+  mProcessorInfoType4.ThreadCount      = (UINT8) MaxCpus;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mProcessorInfoType4, sizeof (SMBIOS_TABLE_TYPE4));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (SocketDesignation, OptionalStrStart);
+  OptionalStrStart += SocketDesignationLen + 1;
+  UnicodeStrToAsciiStr (Manufacturer, OptionalStrStart);
+  OptionalStrStart += ManufacturerLen + 1;
+  UnicodeStrToAsciiStr (Version, OptionalStrStart);
+  OptionalStrStart += VersionLen + 1;
+  UnicodeStrToAsciiStr (SerialNumber, OptionalStrStart);
+  OptionalStrStart += SerialNumberLen + 1;
+  UnicodeStrToAsciiStr (AssetTag, OptionalStrStart);
+  OptionalStrStart += AssetTagLen + 1;
+  UnicodeStrToAsciiStr (PartNumber, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+CacheInfoUpdateSmbiosType7L1I (
+  VOID
+  )
+{
+  CHAR8                 *OptionalStrStart;
+  SMBIOS_TABLE_TYPE7    *SmbiosRecord;
+  CHAR16                *SocketDesignation;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  UINTN                 SocketDesignationLen;
+  EFI_STATUS            Status;
+
+  SocketDesignation = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE7);
+
+  // 04h - Socket Designation String
+  SocketDesignation = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SocketDesignation == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SocketDesignation,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "L1 ICache"
+                                  );
+  SocketDesignationLen = StrLen (SocketDesignation);
+  SmbiosRecordLen += SocketDesignationLen + 1;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mCacheInfoType7L1I, sizeof (SMBIOS_TABLE_TYPE7));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (SocketDesignation, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SocketDesignation != NULL) {
+    FreePool (SocketDesignation);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+CacheInfoUpdateSmbiosType7L1D (
+  VOID
+  )
+{
+  CHAR8                 *OptionalStrStart;
+  SMBIOS_TABLE_TYPE7    *SmbiosRecord;
+  CHAR16                *SocketDesignation;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  UINTN                 SocketDesignationLen;
+  EFI_STATUS            Status;
+
+  SocketDesignation = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE7);
+
+  // 04h - Socket Designation String
+  SocketDesignation = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SocketDesignation == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SocketDesignation,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "L1 DCache"
+                                  );
+  SocketDesignationLen = StrLen (SocketDesignation);
+  SmbiosRecordLen += SocketDesignationLen + 1;
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mCacheInfoType7L1D, sizeof (SMBIOS_TABLE_TYPE7));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (SocketDesignation, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SocketDesignation != NULL) {
+    FreePool (SocketDesignation);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+CacheInfoUpdateSmbiosType7L2U (
+  VOID
+  )
+{
+  CHAR8                 *OptionalStrStart;
+  SMBIOS_TABLE_TYPE7    *SmbiosRecord;
+  CHAR16                *SocketDesignation;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  UINTN                 SocketDesignationLen;
+  EFI_STATUS            Status;
+
+  SocketDesignation = NULL;
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE7);
+
+  // 04h - Socket Designation String
+  SocketDesignation = AllocateZeroPool (sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH);
+  if (SocketDesignation == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+  (VOID)UnicodeSPrintAsciiFormat (SocketDesignation,
+                                  sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH,
+                                  "L2 UCache (PL310)"
+                                  );
+  SocketDesignationLen = StrLen (SocketDesignation);
+  SmbiosRecordLen += SocketDesignationLen + 1;
+
+  // 07h - Maximum Cache Size
+  // 09h - Installed Size
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  mCacheInfoType7L2U.MaximumCacheSize = 0x400; // 1MB
+  mCacheInfoType7L2U.InstalledSize = 0x400; // 1MB
+#elif defined(CPU_IMX6SDL)
+  mCacheInfoType7L2U.MaximumCacheSize = 0x200; // 512KB
+  mCacheInfoType7L2U.InstalledSize = 0x200; // 512KB
+#elif defined(CPU_IMX6SX)
+  mCacheInfoType7L2U.MaximumCacheSize = 0x100; // 256KB
+  mCacheInfoType7L2U.InstalledSize = 0x100; // 256KB
+#else
+  #error iMX6 CPU Type not defined
+#endif
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mCacheInfoType7L2U, sizeof (SMBIOS_TABLE_TYPE7));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (SocketDesignation, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SocketDesignation != NULL) {
+    FreePool (SocketDesignation);
+  }
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+CacheInfoUpdateSmbiosType7 (
+  VOID
+  )
+{
+  EFI_STATUS Status;
+
+  // L1I Table
+  Status = CacheInfoUpdateSmbiosType7L1I ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  // L1D Table
+  Status = CacheInfoUpdateSmbiosType7L1D ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  // L2U Table
+  Status = CacheInfoUpdateSmbiosType7L2U ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+PhysicalMemoryArrayInfoUpdateSmbiosType16 (
+  VOID
+  )
+{
+  SMBIOS_TABLE_TYPE16   *SmbiosRecord;
+  UINT32                MaximumCapacity;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE16);
+
+  // 07h - Maximum Capacity
+  MaximumCapacity = FixedPcdGet32 (PcdPhysicalMemoryMaximumCapacity);
+  if (MaximumCapacity == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdPhysicalMemoryMaximumCapacity not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  mPhysicalMemoryArrayInfoType16.MaximumCapacity = MaximumCapacity;
+
+  // 0Fh - Extended Maximum Capacity
+  mPhysicalMemoryArrayInfoType16.ExtendedMaximumCapacity = 0;
+
+  // Since there are no strings, need to add one extra to the record length
+  // in order to have the record end with double NULL.
+  SmbiosRecordLen += 2;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mPhysicalMemoryArrayInfoType16, sizeof (SMBIOS_TABLE_TYPE16));
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+MemoryDeviceInfoUpdateSmbiosType17 (
+  VOID
+  )
+{
+  CHAR16                *BankLocation;
+  CHAR16                *DeviceLocation;
+  CHAR8                 *OptionalStrStart;
+  SMBIOS_TABLE_TYPE17   *SmbiosRecord;
+  UINTN                 BankLocationLen;
+  UINTN                 DeviceLocationLen;
+  UINT32                MaximumCapacity;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE17);
+
+  // 08h - Total Width
+  // 0Ah - Data Width
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) || defined(SOCTYPE_DUALLITE)
+  mMemoryDeviceInfoType17.TotalWidth = 64;
+  mMemoryDeviceInfoType17.DataWidth = 64;
+#elif defined(CPU_IMX6SX) || defined(SOCTYPE_SOLO)
+  mMemoryDeviceInfoType17.TotalWidth = 32;
+  mMemoryDeviceInfoType17.DataWidth = 32;
+#else
+  #error iMX6 CPU Type not defined
+#endif
+
+  // 0Ch - Size - in MB
+  MaximumCapacity = FixedPcdGet32 (PcdPhysicalMemoryMaximumCapacity);
+  if (MaximumCapacity == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdPhysicalMemoryMaximumCapacity not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  MaximumCapacity = MaximumCapacity / 1024;
+  mMemoryDeviceInfoType17.Size = MaximumCapacity;
+
+  // 10h - Device Locator String
+  DeviceLocation = (CHAR16 *)FixedPcdGetPtr (PcdMemoryDeviceLocation);
+  DeviceLocationLen = StrLen (DeviceLocation);
+  if (DeviceLocationLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdMemoryDeviceLocation not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += DeviceLocationLen + 1;
+
+  // 11h - Bank Locator String
+  BankLocation = (CHAR16 *)FixedPcdGetPtr (PcdMemoryBankLocation);
+  BankLocationLen = StrLen (BankLocation);
+  if (BankLocationLen == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdMemoryBankLocation not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  SmbiosRecordLen += BankLocationLen + 1;
+
+  // 15h - Speed
+#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
+  mMemoryDeviceInfoType17.Speed = 533; // 533 MHz DDR3
+#elif defined(CPU_IMX6SDL) || defined(CPU_IMX6SX)
+  mMemoryDeviceInfoType17.Speed = 400; // 400 MHz DDR3
+#else
+  #error iMX6 CPU Type not defined
+#endif
+
+  // Record must end in double NULL
+  SmbiosRecordLen += 1;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mMemoryDeviceInfoType17, sizeof (SMBIOS_TABLE_TYPE17));
+
+  // Populate optional string area at the end of the entry
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStr (DeviceLocation, OptionalStrStart);
+  OptionalStrStart += DeviceLocationLen + 1;
+  UnicodeStrToAsciiStr (BankLocation, OptionalStrStart);
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+MemoryArrayMappingInfoUpdateSmbiosType19 (
+  VOID
+  )
+{
+  SMBIOS_TABLE_TYPE19   *SmbiosRecord;
+  UINT32                EndAddress;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  UINT32                StartAddress;
+  EFI_STATUS            Status;
+
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE19);
+
+  // 04h - Starting Address
+  StartAddress = FixedPcdGet32 (PcdMemoryStartAddress);
+  if (StartAddress == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdMemoryStartAddress not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  mMemoryArrayMappedInfoType19.StartingAddress = StartAddress;
+  mMemoryArrayMappedInfoType19.ExtendedStartingAddress = 0;
+
+  // 08h - Ending Address
+  EndAddress = FixedPcdGet32 (PcdMemoryEndAddress);
+  if (EndAddress == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PcdMemoryEndAddress not filled\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  if (EndAddress <= StartAddress) {
+    DEBUG ((DEBUG_ERROR,
+          "%a: Start/End addresses invalid. Start = %x, End = %x\n",
+          __FUNCTION__,
+          StartAddress,
+          EndAddress));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+  mMemoryArrayMappedInfoType19.EndingAddress = EndAddress;
+  mMemoryArrayMappedInfoType19.ExtendedEndingAddress = 0;
+
+  // Since there are no strings, need to add one extra to the record length
+  // in order to have the record end with double NULL.
+  SmbiosRecordLen += 2;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mMemoryArrayMappedInfoType19, sizeof (SMBIOS_TABLE_TYPE19));
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+BootInfoUpdateSmbiosType32 (
+  VOID
+  )
+{
+  SMBIOS_TABLE_TYPE19   *SmbiosRecord;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  UINT32                SmbiosRecordLen;
+  EFI_STATUS            Status;
+
+  SmbiosRecord = NULL;
+  SmbiosRecordLen = sizeof (SMBIOS_TABLE_TYPE32);
+
+  // Since there are no strings, need to add one extra to the record length
+  // in order to have the record end with double NULL.
+  SmbiosRecordLen += 2;
+
+  // Create new SMBIOS record entry
+  SmbiosRecord = AllocateZeroPool (SmbiosRecordLen);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  // Populate entry with default values
+  CopyMem (SmbiosRecord, &mBootInfoType32, sizeof (SMBIOS_TABLE_TYPE32));
+
+  // Commit SMBIOS Entry
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Smbios Table Log Failed %x\n", __FUNCTION__, Status));
+  }
+
+Exit:
+  if (SmbiosRecord != NULL) {
+    FreePool (SmbiosRecord);
+  }
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformSmbiosDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS Status;
+
+  Status = BiosInfoUpdateSmbiosType0 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = SysInfoUpdateSmbiosType1 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = BoardInfoUpdateSmbiosType2 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = EnclosureInfoUpdateSmbiosType3 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = ProcessorInfoUpdateSmbiosType4 (FixedPcdGet32 (PcdCoreCount));
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = CacheInfoUpdateSmbiosType7 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = PhysicalMemoryArrayInfoUpdateSmbiosType16 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = MemoryDeviceInfoUpdateSmbiosType17 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = MemoryArrayMappingInfoUpdateSmbiosType19 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Status = BootInfoUpdateSmbiosType32 ();
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h
new file mode 100644
index 000000000000..4842015afcdf
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h
@@ -0,0 +1,44 @@
+/** @file
+*
+*  Copyright (c) 2015, ARM Limited. All rights reserved.
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _PLATFORM_SMBIOS_DXE_H_
+#define _PLATFORM_SMBIOS_DXE_H_
+
+#define OCOTP_BANK_0_WORD_1 0x021BC410
+#define OCOTP_BANK_0_WORD_2 0x021BC420
+
+#define GLOBAL_PAGE_SIGNATURE 0x474C424C // 'GLBL'
+
+enum SMBIOS_REFRENCE_HANDLES {
+  SMBIOS_HANDLE_BOARD = 0x1000,
+  SMBIOS_HANDLE_CHASSIS,
+  SMBIOS_HANDLE_PROCESSOR,
+  SMBIOS_HANDLE_L1I,
+  SMBIOS_HANDLE_L1D,
+  SMBIOS_HANDLE_L2U,
+  SMBIOS_HANDLE_MEMORY_ARRAY,
+  SMBIOS_HANDLE_MEMORY_DEVICE
+};
+
+typedef struct {
+  UINT32 Signature;
+  UINT8 Revision;
+  UINT8 reserved[3];
+  UINT8 Mac0Id;
+  UINT8 Mac0Valid;
+  UINT8 MacAddress[6];
+} GLOBAL_PAGE_DATA;
+
+#endif  /* _PLATFORM_SMBIOS_DXE_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
new file mode 100644
index 000000000000..9e9b386f1b08
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
@@ -0,0 +1,84 @@
+#/** @file
+#
+#  Copyright (c) 2013 Linaro.org
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = PlatformSmbiosDxe
+  FILE_GUID                      = 3847D23F-1D95-4772-B60C-4BBFBC4D532F
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PlatformSmbiosDriverEntryPoint
+
+[Sources]
+  PlatformSmbiosDxe.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  MemoryAllocationLib
+  PrintLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Protocols]
+  gEfiSmbiosProtocolGuid                        # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+  gArmTokenSpaceGuid.PcdFdSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor
+  giMXPlatformTokenSpaceGuid.PcdGlobalDataBaseAddress
+  giMX6TokenSpaceGuid.PcdSystemFamily
+  giMX6TokenSpaceGuid.PcdSystemManufacturer
+  giMX6TokenSpaceGuid.PcdSystemProductName
+  giMX6TokenSpaceGuid.PcdSystemSkuNumber
+  giMX6TokenSpaceGuid.PcdSystemUuid
+  giMX6TokenSpaceGuid.PcdSystemVersionNumber
+  giMX6TokenSpaceGuid.PcdBoardAssetTag
+  giMX6TokenSpaceGuid.PcdBoardLocationInChassis
+  giMX6TokenSpaceGuid.PcdBoardManufacturer
+  giMX6TokenSpaceGuid.PcdBoardProductName
+  giMX6TokenSpaceGuid.PcdBoardVersionNumber
+  giMX6TokenSpaceGuid.PcdChassisAssetTag
+  giMX6TokenSpaceGuid.PcdChassisManufacturer
+  giMX6TokenSpaceGuid.PcdChassisVersionNumber
+  giMX6TokenSpaceGuid.PcdProcessorAssetTag
+  giMX6TokenSpaceGuid.PcdProcessorManufacturer
+  giMX6TokenSpaceGuid.PcdProcessorPartNumber
+  giMX6TokenSpaceGuid.PcdProcessorSocketDesignation
+  giMX6TokenSpaceGuid.PcdProcessorVersionNumber
+  giMX6TokenSpaceGuid.PcdPhysicalMemoryMaximumCapacity
+  giMX6TokenSpaceGuid.PcdMemoryBankLocation
+  giMX6TokenSpaceGuid.PcdMemoryDeviceLocation
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress
+  giMX6TokenSpaceGuid.PcdMemoryStartAddress
+
+[Depex]
+  gEfiSmbiosProtocolGuid
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (21 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 23/27] Silicon/NXP: Add i.MX6 Smbios Driver Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 22:37   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 24/27] Silicon/NXP: Add i.MX6 common dsc and fdf files Chris Co
                   ` (4 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds GOP display support for NXP i.MX6 SoCs.  It has support for
HDMI, LVDS, IPU, and parses EDID using I2C.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c             | 423 +++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h             | 277 +++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c               |  69 ++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h               |  28 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c           | 455 ++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h           | 175 +++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c | 399 ++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h | 331 +++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c  | 458 ++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h  | 195 +++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c              |  96 +++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h              |  33 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c            | 475 ++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h            |  20 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf          |  70 ++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c              | 761 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h              | 529 ++++++++++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c             |  88 +++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h             |  32 +
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h               | 236 ++++++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c              |  93 +++
 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h              |  67 ++
 22 files changed, 5310 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c
new file mode 100644
index 000000000000..a8ab78128719
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c
@@ -0,0 +1,423 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "CPMem.h"
+#include "GopDxe.h"
+#include "Ipu.h"
+
+CPMEM_PARAM *CpMemParamBasePtr = (CPMEM_PARAM *)(IPU1_BASE + CSP_IPUV3_CPMEM_REGS_OFFSET);
+
+STATIC CONST UINT8 ChannelMap[] = {
+  5, 0,
+  11, 2,
+  12, 4,
+  14, 6,
+  15, 8,
+  20, 10,
+  21, 12,
+  22, 14,
+  23, 16,
+  27, 18,
+  28, 20,
+  45, 0,
+  46, 2,
+  47, 4,
+  48, 6,
+  49, 8,
+  50, 10,
+};
+
+#ifdef DEBUG
+VOID
+DumpCpmemParamPack (
+  IN  CPMEM_PARAM   *ParamPtr
+  )
+{
+  DEBUG ((DEBUG_VERBOSE, "%a: --WORD0--\n", __FUNCTION__));
+  DEBUG ((DEBUG_VERBOSE, "%a: XVVirtualCoordinate 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.XVVirtualCoordinate));
+  DEBUG ((DEBUG_VERBOSE, "%a: YVVirtualCoordinate 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.YVVirtualCoordinate));
+  DEBUG ((DEBUG_VERBOSE, "%a: XBinnerBlockCoordinate 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.XBinnerBlockCoordinate));
+  DEBUG ((DEBUG_VERBOSE, "%a: YBinnerBlockCoordinate 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.YBinnerBlockCoordinate));
+  DEBUG ((DEBUG_VERBOSE, "%a: NewSubBlock 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.NewSubBlock));
+  DEBUG ((DEBUG_VERBOSE, "%a: CurrentField 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.CurrentField));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollXCounter 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollXCounter));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollYCounter 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollYCounter));
+  DEBUG ((DEBUG_VERBOSE, "%a: NumberOfScroll 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.NumberOfScroll));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollDeltaX 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollDeltaX));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollMax 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollMax));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollingConfiguration 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollingConfiguration));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollingEnable 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollingEnable));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollDeltaY 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollDeltaY));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollHorizontalDirection 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollHorizontalDirection));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScrollVerticalDirection 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScrollVerticalDirection));
+  DEBUG ((DEBUG_VERBOSE, "%a: BitsPerPixel 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.BitsPerPixel));
+  DEBUG ((DEBUG_VERBOSE, "%a: DecodeAddressSelect 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.DecodeAddressSelect));
+  DEBUG ((DEBUG_VERBOSE, "%a: AccessDimension 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.AccessDimension));
+  DEBUG ((DEBUG_VERBOSE, "%a: ScanOrder 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ScanOrder));
+  DEBUG ((DEBUG_VERBOSE, "%a: BandMode 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.BandMode));
+  DEBUG ((DEBUG_VERBOSE, "%a: BlockMode 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.BlockMode));
+  DEBUG ((DEBUG_VERBOSE, "%a: Rotation 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.Rotation));
+  DEBUG ((DEBUG_VERBOSE, "%a: HorizontalFlip 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.HorizontalFlip));
+  DEBUG ((DEBUG_VERBOSE, "%a: VerticalFlip 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.VerticalFlip));
+  DEBUG ((DEBUG_VERBOSE, "%a: ThresholdEnable 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ThresholdEnable));
+  DEBUG ((DEBUG_VERBOSE, "%a: ConditionalAccessPolarity 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ConditionalAccessPolarity));
+  DEBUG ((DEBUG_VERBOSE, "%a: ConditionalAccessEnable 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.ConditionalAccessEnable));
+  DEBUG ((DEBUG_VERBOSE, "%a: FrameWidth 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.FrameWidth));
+  DEBUG ((DEBUG_VERBOSE, "%a: FrameHeight 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.FrameHeight));
+  DEBUG ((DEBUG_VERBOSE, "%a: EndOfLineInterrupt 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word0Pack.EndOfLineInterrupt));
+
+  DEBUG ((DEBUG_VERBOSE, "%a: --WORD1--\n", __FUNCTION__));
+  DEBUG ((DEBUG_VERBOSE, "%a: ExtMemBuffer0Address 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.ExtMemBuffer0Address));
+  DEBUG ((DEBUG_VERBOSE, "%a: ExtMemBuffer1Address 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.ExtMemBuffer1Address));
+  DEBUG ((DEBUG_VERBOSE, "%a: InterlaceOffset 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.InterlaceOffset));
+  DEBUG ((DEBUG_VERBOSE, "%a: NumberOfPixelsInWholeBurstAccess 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.NumberOfPixelsInWholeBurstAccess));
+  DEBUG ((DEBUG_VERBOSE, "%a: PixelFormatSelect 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.PixelFormatSelect));
+  DEBUG ((DEBUG_VERBOSE, "%a: AlphaUsed 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.AlphaUsed));
+  DEBUG ((DEBUG_VERBOSE, "%a: AlphaChannelMapping 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.AlphaChannelMapping));
+  DEBUG ((DEBUG_VERBOSE, "%a: AxiId 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.AxiId));
+  DEBUG ((DEBUG_VERBOSE, "%a: Threshold 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Threshold));
+  DEBUG ((DEBUG_VERBOSE, "%a: StrideLine 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.StrideLine));
+  DEBUG ((DEBUG_VERBOSE, "%a: Width0 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Width0));
+  DEBUG ((DEBUG_VERBOSE, "%a: Width1 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Width1));
+  DEBUG ((DEBUG_VERBOSE, "%a: Width2 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Width2));
+  DEBUG ((DEBUG_VERBOSE, "%a: Width3 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Width3));
+  DEBUG ((DEBUG_VERBOSE, "%a: Offset0 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Offset0));
+  DEBUG ((DEBUG_VERBOSE, "%a: Offset1 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Offset1));
+  DEBUG ((DEBUG_VERBOSE, "%a: Offset2 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Offset2));
+  DEBUG ((DEBUG_VERBOSE, "%a: Offset3 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.Offset3));
+  DEBUG ((DEBUG_VERBOSE, "%a: SelectSXSYSet 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.SelectSXSYSet));
+  DEBUG ((DEBUG_VERBOSE, "%a: ConditionalReadEnable 0x%08x\n", __FUNCTION__,
+    ParamPtr->Word1Pack.ConditionalReadEnable));
+}
+
+VOID
+DumpBasicCpmemReg (
+  IN  CPMEM_PARAM   *pCpmemChannel
+  )
+{
+  DEBUG ((DEBUG_VERBOSE, "%a: ---------- CPMEM Register Dump ----------\n",
+    __FUNCTION__));
+  DEBUG ((DEBUG_VERBOSE, "%a: CPMEM\n", __FUNCTION__));
+  DEBUG ((DEBUG_VERBOSE, "%a: IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE\n",
+    __FUNCTION__));
+  DumpCpmemParamPack (pCpmemChannel);
+  DEBUG ((DEBUG_VERBOSE, "%a: ------------------------------------\n",
+    __FUNCTION__));
+}
+#endif /* DEBUG */
+
+// Enable IDMAC lock setting, which optimises memory accesses and reduces
+// power consumption
+VOID
+SetIdmacLockEn (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  UINT32                      Channel,
+  IN  UINT32                      Setting
+  )
+{
+  UINT32 i;
+  UINTN   LockReg;
+  UINT32 Shift;
+  UINT32 Value;
+
+  Shift = -1;
+
+  for (i = 0; i < ARRAYSIZE (ChannelMap); i += 2) {
+    if (ChannelMap[i] == Channel) {
+      Shift = ChannelMap[i + 1];
+      break;
+    }
+  }
+
+  if (Shift == -1) {
+    DEBUG ((DEBUG_WARN, "%a: Channel %d does not have lock bits\n",
+      __FUNCTION__, Channel));
+    return;
+  }
+
+  if (Channel < 29) {
+    LockReg = (UINTN)DisplayInterfaceContextPtr->IpuMmioBasePtr + IPU_IDMAC_LOCK_EN_1;
+  } else {
+    LockReg = (UINTN)DisplayInterfaceContextPtr->IpuMmioBasePtr + IPU_IDMAC_LOCK_EN_2;
+  }
+
+  Value = MmioRead32 ((UINT32)LockReg);
+  Value &= ~(0x3 << Shift);
+  Value |= (Setting & 0x3) << Shift;
+  MmioWrite32 ((UINT32)LockReg, Value);
+}
+
+EFI_STATUS
+ConfigureCpmemFrameBuffer (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  UINT32                      Channel,
+  IN  SURFACE_INFO                *FrameBufferPtr
+  )
+{
+  CPMEM_PARAM *pCpmemChannel;
+  EFI_STATUS Status;
+  CPMEM_WORD0_PACKED_REG CpmemWord0PackedReg;
+  CPMEM_WORD1_PACKED_REG CpmemWord1PackedReg;
+  CPMEM_DEC_SEL DecodeAddressSelect;
+  UINT32 PixelBurst;
+  CPMEM_PFS_PACKED PixelFormatSelector;
+  UINT32 Width0;
+  UINT32 Width1;
+  UINT32 Width2;
+  UINT32 Width3;
+  UINT32 Offset0;
+  UINT32 Offset1;
+  UINT32 Offset2;
+  UINT32 Offset3;
+  UINT32 BytesPerPixel;
+
+  pCpmemChannel = DisplayInterfaceContextPtr->CpMemParamBasePtr;
+  Status = EFI_SUCCESS;
+  PixelBurst = 1;
+  DecodeAddressSelect = CPMEM_DEC_SEL_0_15; // Only applicable for 4 bpp
+  ZeroMem (&CpmemWord0PackedReg, sizeof (CpmemWord0PackedReg));
+  ZeroMem (&CpmemWord1PackedReg, sizeof (CpmemWord1PackedReg));
+
+  switch (FrameBufferPtr->PixelFormat) {
+  case PIXEL_FORMAT_BGRA32:
+    PixelBurst = 15; // 16 Pixel. Valid range is 1 - 64 pixel
+    PixelFormatSelector = CPMEM_PFS_RGB;
+    Offset0 = 8;
+    Offset1 = 16;
+    Offset2 = 24;
+    Offset3 = 0;
+    BytesPerPixel = 4;
+    break;
+  default:
+    ASSERT (FALSE);
+    Status = EFI_UNSUPPORTED;
+    break;
+  }
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  switch (FrameBufferPtr->Bpp) {
+  case 8:
+    Width0 = 0;
+    Width1 = 0;
+    Width2 = 0;
+    Width3 = 0;
+    break;
+  case 32:
+    if (PixelFormatSelector == CPMEM_PFS_RGB) {
+      Width0 = 7;
+      Width1 = 7;
+      Width2 = 7;
+      Width3 = 7;
+    } else {
+      Width0 = 0;
+      Width1 = 0;
+      Width2 = 0;
+      Width3 = 0;
+    }
+    break;
+  default:
+    ASSERT (FALSE);
+    Status = EFI_UNSUPPORTED;
+    break;
+  }
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+  // Setting up CPMEM word 0
+  CpmemWord0PackedReg.XVVirtualCoordinate = 0;
+  CpmemWord0PackedReg.YVVirtualCoordinate = 0;
+
+  // Subblock is unused although expect to have some Value after write
+  CpmemWord0PackedReg.XBinnerBlockCoordinate = 0;
+  CpmemWord0PackedReg.YBinnerBlockCoordinate = 0;
+  CpmemWord0PackedReg.NewSubBlock = 0;
+
+  // Verify "current field" definition
+  CpmemWord0PackedReg.CurrentField = 0;
+
+  // Disable scrolling
+  CpmemWord0PackedReg.ScrollXCounter = 0;
+  CpmemWord0PackedReg.ScrollYCounter = 0;
+  CpmemWord0PackedReg.NumberOfScroll = 0;
+  CpmemWord0PackedReg.ScrollDeltaX = 0;
+  CpmemWord0PackedReg.ScrollMax = 0;
+  CpmemWord0PackedReg.ScrollingConfiguration = 0;
+  CpmemWord0PackedReg.ScrollingEnable = 0;
+  CpmemWord0PackedReg.ScrollDeltaY = 0;
+  CpmemWord0PackedReg.ScrollHorizontalDirection = 0;
+  CpmemWord0PackedReg.ScrollVerticalDirection = 0;
+
+  // Bits per pixel
+  CpmemWord0PackedReg.BitsPerPixel = FrameBufferPtr->Bpp;
+
+  // Decode Address Select
+  CpmemWord0PackedReg.DecodeAddressSelect = DecodeAddressSelect;
+
+  // Scan order is progressive no support for interlace mode
+  CpmemWord0PackedReg.ScanOrder = CPMEM_SO_PROGRESSIVE;
+
+  // Band mode is sub frame double buffering
+  CpmemWord0PackedReg.BandMode = CPMEM_BNDM_DISABLE;
+
+  // Block mode used for post filtering and rotation
+  CpmemWord0PackedReg.BlockMode = CPMEM_BM_DISABLE;
+
+  // No support for rotation and flipping for now
+  CpmemWord0PackedReg.Rotation = CPMEM_ROT_NO_ROTATION;
+  CpmemWord0PackedReg.HorizontalFlip = CPMEM_HF_NO_HFLIP;
+  CpmemWord0PackedReg.VerticalFlip = CPMEM_HF_NO_VFLIP;
+  CpmemWord0PackedReg.ThresholdEnable = CPMEM_THE_DISABLE;
+
+  // Disable conditional access
+  CpmemWord0PackedReg.ConditionalAccessEnable = CPMEM_CAP_SKIP_LOW;
+  CpmemWord0PackedReg.ConditionalAccessPolarity = CPMEM_CAE_DISABLE;
+
+  // Frame width and height, minus one as 0 == 1 pixel
+  CpmemWord0PackedReg.FrameWidth = FrameBufferPtr->Width - 1;
+  CpmemWord0PackedReg.FrameHeight = FrameBufferPtr->Height - 1;
+
+  // No interrupt required at the end of line
+  CpmemWord0PackedReg.EndOfLineInterrupt = CPMEM_EOLI_DISABLE;
+
+  // Setting up CPMEM word 1
+  // Buffer 0, use the [31:3] bit address
+  CpmemWord1PackedReg.ExtMemBuffer0Address = FrameBufferPtr->PhyAddr >> 3;
+
+  // Buffer 1, use the same buffer for now
+  CpmemWord1PackedReg.ExtMemBuffer1Address = FrameBufferPtr->PhyAddr >> 3;
+
+  // Currently do not support interlace mode
+  CpmemWord1PackedReg.InterlaceOffset = 0;
+
+  // Pixel format and burst
+  CpmemWord1PackedReg.NumberOfPixelsInWholeBurstAccess = PixelBurst;
+  CpmemWord1PackedReg.PixelFormatSelect = PixelFormatSelector;
+
+  // Alpha config
+  CpmemWord1PackedReg.AlphaUsed = CPMEM_ALU_SAME_BUFFER;
+
+  // AXI ID 0 should be okay, we don't have anything else contending for it
+  CpmemWord1PackedReg.AxiId = CPMEM_ID_ID_0;
+
+  CpmemWord1PackedReg.Threshold = CPMEM_THE_DISABLE;
+
+  // Stride, width and offset
+  CpmemWord1PackedReg.StrideLine = (FrameBufferPtr->Pitch * BytesPerPixel) - 1;
+  CpmemWord1PackedReg.Width0 = Width0;
+  CpmemWord1PackedReg.Width1 = Width1;
+  CpmemWord1PackedReg.Width2 = Width2;
+  CpmemWord1PackedReg.Width3 = Width3;
+  CpmemWord1PackedReg.Offset0 = Offset0;
+  CpmemWord1PackedReg.Offset1 = Offset1;
+  CpmemWord1PackedReg.Offset2 = Offset2;
+  CpmemWord1PackedReg.Offset3 = Offset3;
+
+  // SX SY is ignored since scrolling is disabled
+  CpmemWord1PackedReg.SelectSXSYSet = 0;
+
+  // Conditional read is always enabled so fully transperant pixel are
+  // not read.
+  CpmemWord1PackedReg.ConditionalReadEnable = CPMEM_CRE_ENABLE;
+
+  // Finally write into cpmem IDMAC channel
+  pCpmemChannel = (pCpmemChannel + Channel);
+
+  CopyMem (
+    &pCpmemChannel->Word0Pack,
+    &CpmemWord0PackedReg,
+    sizeof (pCpmemChannel->Word0Pack)
+  );
+
+  CopyMem (
+    &pCpmemChannel->Word1Pack,
+    &CpmemWord1PackedReg,
+    sizeof (pCpmemChannel->Word1Pack)
+  );
+
+  // IDMAC will generate 8 AXI bursts upon assertion of the DMA request
+  // This significantly reduces memory activity and power consumption
+  SetIdmacLockEn (DisplayInterfaceContextPtr, Channel, 0x3);
+
+#ifdef DEBUG
+  DumpBasicCpmemReg (pCpmemChannel);
+#endif /* DEBUG */
+
+Exit:
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
new file mode 100644
index 000000000000..06e96538f2d1
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
@@ -0,0 +1,277 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _CPMEM_H_
+#define _CPMEM_H_
+
+// IDMAC channel definition
+#define IDMAC_CHANNEL_CSI_0                                 0
+#define IDMAC_CHANNEL_CSI_1                                 1
+#define IDMAC_CHANNEL_CSI_2                                 2
+#define IDMAC_CHANNEL_CSI_3                                 3
+#define IDMAC_CHANNEL_VDIC_VF1_VF2                          5
+#define IDMAC_CHANNEL_VDIC_PREVIOUS_FIELD                   8
+#define IDMAC_CHANNEL_VDIC_CURRENT_FIELD                    9
+#define IDMAC_CHANNEL_VDIC_NEXT_FIELD                       10
+#define IDMAC_CHANNEL_IC_VIDEO_POST_PROCESSSING             11
+#define IDMAC_CHANNEL_IC_VIDEO_PRP_TASK                     12
+
+#define IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE            23
+
+typedef enum {
+  CPMEM_SO_PROGRESSIVE,
+  CPMEM_SO_INTERLACE,
+} CPMEM_SO;
+
+typedef enum {
+  CPMEM_BNDM_DISABLE,
+  CPMEM_BNDM_BAND_HEIGHT_4,
+  CPMEM_BNDM_BAND_HEIGHT_8,
+  CPMEM_BNDM_BAND_HEIGHT_16,
+  CPMEM_BNDM_BAND_HEIGHT_32,
+  CPMEM_BNDM_BAND_HEIGHT_64,
+  CPMEM_BNDM_BAND_HEIGHT_128,
+  CPMEM_BNDM_BAND_HEIGHT_256,
+} CPMEM_BNDM;
+
+typedef enum {
+  CPMEM_BM_DISABLE,
+  CPMEM_BM_BW_BH_8,
+  CPMEM_BM_BW_BH_16,
+  CPMEM_BM_UNUSED,
+} CPMEM_BM;
+
+typedef enum {
+  CPMEM_ROT_NO_ROTATION,
+  CPMEM_ROT_90_ROTATION,
+} CPMEM_ROT;
+
+typedef enum {
+  CPMEM_HF_NO_HFLIP,
+  CPMEM_HF_HFLIP_ENABLE,
+} CPMEM_HF;
+
+typedef enum {
+  CPMEM_HF_NO_VFLIP,
+  CPMEM_HF_VFLIP_ENABLE,
+} CPMEM_VF;
+
+typedef enum {
+  CPMEM_THE_DISABLE,
+  CPMEM_THE_ENABLE,
+} CPMEM_THE;
+
+typedef enum {
+  CPMEM_CAP_SKIP_LOW,
+  CPMEM_CAP_SKIP_HIGH,
+} CPMEM_CAP;
+
+typedef enum {
+  CPMEM_CAE_DISABLE,
+  CPMEM_CAE_ENABLE,
+} CPMEM_CAE;
+
+typedef enum {
+  CPMEM_EOLI_DISABLE,
+  CPMEM_EOLI_ENABLE,
+} CPMEM_EOLI;
+
+typedef enum {
+  CPMEM_PFS_NON_INT_444,
+  CPMEM_PFS_NON_INT_422,
+  CPMEM_PFS_NON_INT_420,
+  CPMEM_PFS_PAR_INT_422,
+  CPMEM_PFS_PAR_INT_420,
+} CPMEM_PFS_PLANAR;
+
+typedef enum {
+  CPMEM_DEC_SEL_0_15,
+  CPMEM_DEC_SEL_64_79,
+  CPMEM_DEC_SEL_128_143,
+  CPMEM_DEC_SEL_192_207,
+} CPMEM_DEC_SEL;
+
+typedef enum {
+  CPMEM_PFS_CODE = 5,
+  CPMEM_PFS_GENERIC_DATA,
+  CPMEM_PFS_RGB,
+  CPMEM_PFS_INT_422_Y1U1Y2V1,
+  CPMEM_PFS_INT_422_Y2U1Y1V1,
+  CPMEM_PFS_INT_422_U1Y1V1Y2,
+  CPMEM_PFS_INT_422_U1Y2V1Y1,
+} CPMEM_PFS_PACKED;
+
+typedef enum {
+  CPMEM_ALU_SAME_BUFFER,
+  CPMEM_ALU_SEPERATE_BUFFER,
+} CPMEM_ALU;
+
+typedef enum {
+  CPMEM_ID_ID_0,
+  CPMEM_ID_ID_1,
+  CPMEM_ID_ID_2,
+  CPMEM_ID_ID_3,
+} CPMEM_ID;
+
+typedef enum {
+  CPMEM_CRE_DISABLE,
+  CPMEM_CRE_ENABLE,
+} CPMEM_CRE;
+
+#pragma pack(push, 1)
+
+// CPMEM_WORD0_PLANAR - Non interlaved
+typedef union {
+  struct {
+    UINT32 XVVirtualCoordinate : 10;
+    UINT32 YVVirtualCoordinate : 9;
+    UINT32 XBinnerBlockCoordinate : 13;
+    UINT32 YBinnerBlockCoordinate : 12;
+    UINT32 NewSubBlock : 1;
+    UINT32 CurrentField : 1;
+    UINT32 MemUBufferOffset : 22;
+    UINT32 MemVBufferOffset : 22;
+    UINT32 InitialOffsetX : 4;
+    UINT32 ReduceDoubleReadOrWrites : 1;
+    UINT32 Reserved1 : 18;
+    UINT32 ScanOrder : 1;
+    UINT32 BandMode : 3;
+    UINT32 BlockMode : 2;
+    UINT32 Rotation : 1;
+    UINT32 HorizontalFlip : 1;
+    UINT32 VerticalFlip : 1;
+    UINT32 ThresholdEnable : 1;
+    UINT32 ConditionalAccessPolarity : 1;
+    UINT32 ConditionalAccessEnable : 1;
+    UINT32 FrameWidth : 13; // Max 8192 Pixel
+    UINT32 FrameHeight : 12; // Max 4096 Pixel
+    UINT32 EndOfLineInterrupt : 1;
+    UINT32 Reserved2 : 9;
+  };
+  UINT32 Word0[5];
+} CPMEM_WORD0_PLANAR_REG;
+
+// CPMEM_WORD1_PLANAR - Non interleaved
+typedef union {
+  struct {
+    UINT32 ExtMemBuffer0Address : 29;
+    UINT32 ExtMemBuffer1Address : 29;
+    UINT32 InterlaceOffset : 20;
+    UINT32 NumberOfPixelsInWholeBurstAccess : 7;
+    UINT32 PixelFormatSelect : 4;
+    UINT32 AlphaUsed : 1;
+    UINT32 AlphaChannelMapping : 3;
+    UINT32 AxiId : 2;
+    UINT32 Threshold : 7;
+    UINT32 StrideLine : 14;
+    UINT32 Reserved1 : 9;
+    UINT32 Width3 : 3;
+    UINT32 StrideLineUV : 14;
+    UINT32 Reserved2 : 7;
+    UINT32 ConditionalReadEnable : 1;
+    UINT32 Reserved3 : 10;
+  };
+  UINT32 Word1[5];
+} CPMEM_WORD1_PLANAR_REG;
+
+// CPMEM_WORD0_PACKED - Interlaved
+typedef union {
+  struct {
+    UINT32 XVVirtualCoordinate : 10;
+    UINT32 YVVirtualCoordinate : 9;
+    UINT32 XBinnerBlockCoordinate : 13;
+    UINT32 YBinnerBlockCoordinate : 12;
+    UINT32 NewSubBlock : 1;
+    UINT32 CurrentField : 1;
+    UINT32 ScrollXCounter : 12;
+    UINT32 ScrollYCounter : 11;
+    UINT32 NumberOfScroll : 10;
+    UINT32 ScrollDeltaX : 7;
+    UINT32 ScrollMax : 10;
+    UINT32 ScrollingConfiguration : 1;
+    UINT32 ScrollingEnable : 1;
+    UINT32 ScrollDeltaY : 7;
+    UINT32 ScrollHorizontalDirection : 1;
+    UINT32 ScrollVerticalDirection : 1;
+    UINT32 BitsPerPixel : 3;
+    UINT32 DecodeAddressSelect : 2;
+    UINT32 AccessDimension : 1;
+    UINT32 ScanOrder : 1;
+    UINT32 BandMode : 3;
+    UINT32 BlockMode : 2;
+    UINT32 Rotation : 1;
+    UINT32 HorizontalFlip : 1;
+    UINT32 VerticalFlip : 1;
+    UINT32 ThresholdEnable : 1;
+    UINT32 ConditionalAccessPolarity : 1;
+    UINT32 ConditionalAccessEnable : 1;
+    UINT32 FrameWidth : 13; // Max 8192 Pixel
+    UINT32 FrameHeight : 12; // Max 4096 Pixel
+    UINT32 EndOfLineInterrupt : 1;
+    UINT32 Reserved2 : 9;
+  };
+  UINT32 Word0[5];
+} CPMEM_WORD0_PACKED_REG;
+
+// CPMEM_WORD1_PACKED - Non interleaved
+typedef union {
+  struct {
+    UINT32 ExtMemBuffer0Address : 29;
+    UINT32 ExtMemBuffer1Address : 29;
+    UINT32 InterlaceOffset : 20;
+    UINT32 NumberOfPixelsInWholeBurstAccess : 7;
+    UINT32 PixelFormatSelect : 4;
+    UINT32 AlphaUsed : 1;
+    UINT32 AlphaChannelMapping : 3;
+    UINT32 AxiId : 2;
+    UINT32 Threshold : 7;
+    UINT32 StrideLine : 14;
+    UINT32 Width0 : 3;
+    UINT32 Width1 : 3;
+    UINT32 Width2 : 3;
+    UINT32 Width3 : 3;
+    UINT32 Offset0 : 5;
+    UINT32 Offset1 : 5;
+    UINT32 Offset2 : 5;
+    UINT32 Offset3 : 5;
+    UINT32 SelectSXSYSet : 1;
+    UINT32 ConditionalReadEnable : 1;
+    UINT32 Reserved1 : 10;
+  };
+  UINT32 Word1[5];
+} CPMEM_WORD1_PACKED_REG;
+
+typedef struct _CPMEM_PARAM {
+  union {
+    CPMEM_WORD0_PLANAR_REG Word0Planar;
+    CPMEM_WORD0_PACKED_REG Word0Pack;
+  };
+  UINT32 Reserved1[3];
+  union {
+    CPMEM_WORD1_PLANAR_REG Word1Planar;
+    CPMEM_WORD1_PACKED_REG Word1Pack;
+  };
+  UINT32 Reserved2[3];
+} CPMEM_PARAM, *PCPMEM_PARAM;
+
+#pragma pack(pop)
+
+EFI_STATUS
+ConfigureCpmemFrameBuffer (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  UINT32                      Channel,
+  IN  SURFACE_INFO                *FrameBufferPtr
+  );
+
+#endif  /* _CPMEM_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
new file mode 100644
index 000000000000..30b737b2f4f5
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
@@ -0,0 +1,69 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "Edid.h"
+#include "Ddc.h"
+#include "Hdmi.h"
+#include "Lvds.h"
+
+EFI_STATUS
+Imx6DdcRead (
+  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
+  IN  UINT8               SlaveAddress,
+  IN  UINT8               RegisterAddress,
+  IN  UINT32              ReadSize,
+  IN  UINT8               *DataReadPtr
+  )
+{
+  EFI_STATUS Status;
+
+  switch (DisplayInterface) {
+  case HdmiDisplay:
+    Status = HdmiDdcRead (
+               &DisplayContextPtr->DiContext[HdmiDisplay],
+               SlaveAddress,
+               RegisterAddress,
+               ReadSize,
+               HDMI_DDC_STANDARD_MODE,
+               DataReadPtr
+             );
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR, "%a: HdmiDdcRead failed\n", __FUNCTION__));
+    }
+    break;
+  case MipiDisplay:
+  case Lvds0Display:
+  case Lvds1Display:
+  default:
+    Status = EFI_UNSUPPORTED;
+    break;
+  }
+
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
new file mode 100644
index 000000000000..5a10f3d0c26c
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
@@ -0,0 +1,28 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _DDC_H_
+#define _DDC_H_
+
+EFI_STATUS
+Imx6DdcRead (
+  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
+  IN  UINT8               SlaveAddress,
+  IN  UINT8               RegisterAddress,
+  IN  UINT32              ReadSize,
+  IN  UINT8               *DataReadPtr
+  );
+
+#endif  /* _DDC_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
new file mode 100644
index 000000000000..334e7362d3b8
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
@@ -0,0 +1,455 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+// Display muxing register
+#include "iMX6.h"
+
+#include "Display.h"
+#include "Edid.h"
+#include "Hdmi.h"
+#include "Lvds.h"
+#include "DisplayInterface.h"
+#include "DisplayController.h"
+#include "CPMem.h"
+#include "Ipu.h"
+#include "IoMux.h"
+
+DISPLAY_TIMING DefaultTiming = {
+  65000000,   // PixelClock
+  1024,       // HActive
+  320,        // HBlank
+  768,        // VActive
+  38,         // VBlank
+  136,        // HSync
+  6,          // VSync
+  24,         // HSyncOffset;
+  3,          // VSyncOffset;
+  1024,       // HImageSize
+  768,        // VImageSize
+  0,          // HBorder
+  0,          // VBorder
+  0,          // EdidFlags
+  0,          // Flags
+  1,          // PixelRepetition
+  32,          // Bpp
+  PIXEL_FORMAT_BGRA32,       // PixelFormat
+};
+
+DISPLAY_TIMING Hannstar_XGA = {
+  65000000,   // PixelClock
+  1024,       // HActive
+  320,        // HBlank
+  768,        // VActive
+  38,         // VBlank
+  60,         // HSync
+  10,         // VSync
+  24,         // HSyncOffset;
+  3,          // VSyncOffset;
+  1024,       // HImageSize
+  768,        // VImageSize
+  0,          // HBorder
+  0,          // VBorder
+  0,          // EdidFlags
+  0,          // Flags
+  1,          // PixelRepetition
+  32,         // Bpp
+  PIXEL_FORMAT_BGRA32,       // PixelFormat
+};
+
+EFI_STATUS
+GetPreferredTiming (
+  IN  UINT8           *EdidDataPtr,
+  IN  UINT32          EdidDataSize,
+  IN  DISPLAY_TIMING  *PreferredTimingPtr
+  )
+{
+  EFI_STATUS Status;
+
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    *PreferredTimingPtr = Hannstar_XGA;
+    Status = EFI_SUCCESS;
+  } else {
+    Status = GetEdidPreferredTiming (EdidDataPtr, EdidDataSize, PreferredTimingPtr);
+    if (Status != EFI_SUCCESS) {
+      // If EDID is unavailable use the default timing
+      Status = EFI_SUCCESS;
+      *PreferredTimingPtr = DefaultTiming;
+      DEBUG ((DEBUG_WARN,
+        "%a: EDID data not available, falling back to default timing\n",
+        __FUNCTION__));
+    }
+  }
+
+  // Only support 8 bit per pixel and no pixel repetition for now
+  PreferredTimingPtr->PixelRepetition = 1;
+  PreferredTimingPtr->PixelFormat = PIXEL_FORMAT_BGRA32;
+  PreferredTimingPtr->Bpp = 32;
+
+#ifdef DEBUG
+  PrintDisplayTiming ("Preferred Timing", PreferredTimingPtr);
+#endif /* DEBUG */
+  DEBUG ((DEBUG_WARN, "%a: --GetPreferredTiming\n", __FUNCTION__));
+  return Status;
+}
+
+EFI_STATUS
+InitDisplay (
+  IN  DISPLAY_CONTEXT   **DisplayConfigPPtr
+  )
+{
+  DISPLAY_CONTEXT     *pTempDisplayContext;
+  DISPLAY_INTERFACE_TYPE   DisplayCounter;
+  EFI_STATUS          Status;
+
+  pTempDisplayContext = AllocateRuntimePool (sizeof (*pTempDisplayContext));
+  if (pTempDisplayContext == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate display context\n", __FUNCTION__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  ZeroMem (pTempDisplayContext, sizeof (*pTempDisplayContext));
+
+  pTempDisplayContext->IoMuxMmioBasePtr = (VOID *)IOMUXC_GPR_BASE_ADDRESS;
+  if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to map IO Mux register\n", __FUNCTION__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  pTempDisplayContext->IpuMmioBasePtr[IPU1] = (VOID *)IPU1_BASE;
+  if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to map IPU1 IO Mux register\n", __FUNCTION__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+#if !defined(CPU_IMX6SDL)
+  pTempDisplayContext->IpuMmioBasePtr[IPU2] = (VOID *)IPU2_BASE;
+  if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to map IPU2 IO Mux register\n", __FUNCTION__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+#endif
+  for (DisplayCounter = HdmiDisplay; DisplayCounter < DisplayTypeMax; ++DisplayCounter) {
+    pTempDisplayContext->DiContext[DisplayCounter].displayInterface =
+      DisplayCounter;
+  }
+
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    Status = InitLvds (pTempDisplayContext);
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR, "%a: Fail to intialize LVDS\n", __FUNCTION__));
+      goto Exit;
+    }
+  } else {
+    Status = InitHdmi (pTempDisplayContext);
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR, "%a: Fail to intialize HDMI\n", __FUNCTION__));
+      goto Exit;
+    }
+  }
+
+  *DisplayConfigPPtr = pTempDisplayContext;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+ValidateDisplayConfig (
+  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN  DISPLAY_MODE        DisplayMode,
+  IN  DISPLAY_INTERFACE_TYPE   *DiOrder
+  )
+{
+  DISPLAY_INTERFACE_TYPE   DisplayDevice;
+  EFI_STATUS          Status;
+
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    DisplayDevice = Lvds0Display;
+  } else {
+    DisplayDevice = HdmiDisplay;
+  }
+
+  // Currently only support single display mode on HDMI/LVDS
+  if (DisplayMode != SINGLE_MODE && DiOrder[0] != DisplayDevice) {
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  // Currently going to a very simplistic approach of enabling HDMI/LVDS single
+  // display on HDMI/LVDS port. This configuration is applied regardless if
+  // there is a monitor connected. No hot plug, monitor detection support.
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+SetDisplayConfig (
+  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN      DISPLAY_MODE        DisplayMode,
+  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
+  )
+{
+  DISPLAY_INTERFACE_CONTEXT   *pDisplayInterfaceContext;
+  DISPLAY_INTERFACE_INDEX     DisplayInterfaceIndex;
+  UINT32                      DisplayInterfaceOffset[DisplayInterfaceMax];
+  UINT32                      DisplayModeIndex;
+  IPU_INDEX                   IpuIndex;
+  EFI_STATUS                  Status;
+
+  DisplayInterfaceOffset[0] = IPU_DISPLAY_INTERFACE_0_OFFSET;
+  DisplayInterfaceOffset[1] = IPU_DISPLAY_INTERFACE_1_OFFSET;
+  Status = ValidateDisplayConfig (DisplayContextPtr, DisplayMode, DiOrder);
+  if (Status != EFI_SUCCESS) {
+    DisplayContextPtr->DisplayConfig.DisplayMode = UNKNOWN_MODE;
+    ZeroMem (
+      DisplayContextPtr->DisplayConfig.DiOrder,
+      sizeof (DisplayContextPtr->DisplayConfig.DiOrder)
+    );
+    DEBUG ((DEBUG_ERROR, "%a: Unsupported display configuration\n", __FUNCTION__));
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  DisplayContextPtr->DisplayConfig.DisplayMode = DisplayMode;
+  ZeroMem (
+    DisplayContextPtr->DisplayConfig.DiOrder,
+    sizeof (DisplayContextPtr->DisplayConfig.DiOrder)
+  );
+
+  // Assigning display interface in order. Require mode information on IPU
+  // and Display Interface valid combination
+  DisplayModeIndex = 0;
+  for (IpuIndex = IPU1; IpuIndex < IPU_TOTAL; IpuIndex++) {
+    for (DisplayInterfaceIndex = DisplayInterface0;
+         DisplayInterfaceIndex < DisplayInterfaceMax;
+         DisplayInterfaceIndex++)
+    {
+      if (DisplayModeIndex >= (UINT32)DisplayMode) {
+        break;
+      }
+      DisplayModeIndex++;
+
+      DisplayContextPtr->DisplayConfig.DiOrder[DisplayInterfaceIndex] =
+        DiOrder[DisplayInterfaceIndex];
+      pDisplayInterfaceContext =
+        &DisplayContextPtr->DiContext[DiOrder[DisplayInterfaceIndex]];
+      pDisplayInterfaceContext->IpuMmioBasePtr =
+        DisplayContextPtr->IpuMmioBasePtr[IpuIndex];
+      pDisplayInterfaceContext->IpuDiRegsPtr =
+        (IPU_DIx_REGS *)(((UINTN)DisplayContextPtr->IpuMmioBasePtr[IpuIndex]) +
+                                 DisplayInterfaceOffset[DisplayInterfaceIndex]);
+      pDisplayInterfaceContext->CpMemParamBasePtr =
+        (VOID *)(((UINTN)pDisplayInterfaceContext->IpuMmioBasePtr) +
+                         CSP_IPUV3_CPMEM_REGS_OFFSET);
+    }
+  }
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+ApplyDisplayConfig (
+  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN      DISPLAY_MODE        DisplayMode,
+  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
+  )
+{
+  DISPLAY_TIMING              *pCurrentDisplayTiming;
+  DISPLAY_CONFIG              *pDisplayConfig;
+  DISPLAY_INTERFACE_CONTEXT   *pDisplayInterfaceContext;
+  UINT32                      CurrentDisplayInterface;
+  UINT32                      DisplayModeIndex;
+  EFI_STATUS                  Status;
+
+  Status = EFI_SUCCESS;
+  pDisplayConfig = &DisplayContextPtr->DisplayConfig;
+  Status = SetDisplayConfig (DisplayContextPtr, DisplayMode, DiOrder);
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Fail to set display configuration %d\n",
+      __FUNCTION__, DisplayMode));
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  // Setup muxing first before configuring DI and DC
+  Status = SetupDisplayMux (DisplayContextPtr);
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: SetDisplayMux failed \n", __FUNCTION__));
+    goto Exit;
+  }
+
+  for (DisplayModeIndex = 0;
+       DisplayModeIndex < (UINT32)pDisplayConfig->DisplayMode;
+       ++DisplayModeIndex)
+  {
+    CurrentDisplayInterface = pDisplayConfig->DiOrder[DisplayModeIndex];
+    pDisplayInterfaceContext = &DisplayContextPtr->DiContext[CurrentDisplayInterface];
+    pCurrentDisplayTiming = &pDisplayConfig->DisplayTiming[DisplayModeIndex];
+
+    Status = ConfigureDisplayControllerChannel (
+               pDisplayInterfaceContext,
+               CurrentDisplayInterface,
+               DisplayModeIndex,
+               pCurrentDisplayTiming
+             );
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR,
+        "%a:ConfigureDisplayControllerChannel fail display %d index %d\n",
+        __FUNCTION__, CurrentDisplayInterface, DisplayModeIndex));
+      goto Exit;
+    }
+
+    Status = ConfigureDisplayInterface (
+               pDisplayInterfaceContext,
+               DisplayModeIndex,
+               pCurrentDisplayTiming
+             );
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR, "%a: Fail to configure DI\n", __FUNCTION__));
+      goto Exit;
+    }
+
+    switch (CurrentDisplayInterface) {
+    case HdmiDisplay:
+      Status = SetHdmiDisplay (pDisplayInterfaceContext, pCurrentDisplayTiming);
+      if (Status != EFI_SUCCESS) {
+        DEBUG ((DEBUG_ERROR, "%a: Fail to set HDMI timing\n", __FUNCTION__));
+        goto Exit;
+      }
+      break;
+    case Lvds0Display:
+    case Lvds1Display:
+      break;
+    default:
+      Status = EFI_UNSUPPORTED;
+      break;
+    }
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+
+    Status = ConfigureFrameBuffer (
+               pDisplayInterfaceContext,
+               &pDisplayConfig->DisplaySurface[DisplayModeIndex]
+             );
+    if (Status != EFI_SUCCESS) {
+      DEBUG ((DEBUG_ERROR,
+        "%a: Fail to configure frame buffer (%d)\n",
+        __FUNCTION__, DisplayModeIndex));
+      goto Exit;
+    }
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+AllocateFrameBuffer (
+  IN OUT  SURFACE_INFO  *SurfaceInfoPtr
+  )
+{
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "%a: Enter\n", __FUNCTION__));
+  if ((SurfaceInfoPtr->Width == 0) || (SurfaceInfoPtr->Height == 0)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: Frame Buffer AddrP=%Xh\n",
+    __FUNCTION__, FixedPcdGet32 (PcdFrameBufferBase)));
+  DEBUG ((DEBUG_INFO, "%a: Frame Buffer Size=%Xh\n",
+    __FUNCTION__, FixedPcdGet32 (PcdFrameBufferSize)));
+
+  SurfaceInfoPtr->VirtAddrPtr = (VOID *)(UINTN)FixedPcdGet32 (PcdFrameBufferBase);
+  SurfaceInfoPtr->PhyAddr = (UINT32)(SurfaceInfoPtr->VirtAddrPtr);
+  SurfaceInfoPtr->Pitch = SurfaceInfoPtr->Width;
+
+  DEBUG ((DEBUG_INFO,
+    "%a: Allocate FB PhyAddr %x VirtAddr %x\n",
+    __FUNCTION__, SurfaceInfoPtr->PhyAddr, SurfaceInfoPtr->VirtAddrPtr));
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  DEBUG ((DEBUG_INFO, "%a: Exit = %Xh\n",
+    __FUNCTION__, Status));
+  return Status;
+}
+
+EFI_STATUS
+ConfigureFrameBuffer (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  SURFACE_INFO                *FrameBufferPtr
+  )
+{
+  EFI_STATUS  Status;
+
+  // Only support single display for now
+  Status = ConfigureCpmemFrameBuffer (
+             DisplayInterfaceContextPtr,
+             IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE,
+             FrameBufferPtr
+           );
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to configure CPMEM\n", __FUNCTION__));
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+UINT32
+GetColorDepth (
+  IN  PIXEL_FORMAT  PixelFormat
+  )
+{
+  UINT32  BitDepth;
+
+  switch (PixelFormat) {
+  case PIXEL_FORMAT_ARGB32:
+  case PIXEL_FORMAT_BGRA32:
+    BitDepth = 8;
+    break;
+  default:
+    BitDepth = 0;
+    break;
+  }
+
+  return BitDepth;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
new file mode 100644
index 000000000000..cbcea1219743
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
@@ -0,0 +1,175 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _DISPLAY_H_
+#define _DISPLAY_H_
+
+typedef enum {
+  UNKNOWN_MODE,
+  SINGLE_MODE,
+  DUAL_MODE,
+} DISPLAY_MODE;
+
+typedef enum {
+  IPU1,
+#if !defined(CPU_IMX6SDL)
+  IPU2,
+#endif
+  IPU_TOTAL,
+} IPU_INDEX;
+
+typedef enum {
+  DisplayInterface0,
+  DisplayInterface1,
+  DisplayInterfaceMax,
+} DISPLAY_INTERFACE_INDEX;
+
+typedef enum {
+  HdmiDisplay,
+  MipiDisplay,
+  Lvds0Display,
+  Lvds1Display,
+  DisplayTypeMax, // Only 4 display types supported by IPU
+  NoDisplayType = DisplayTypeMax,
+} DISPLAY_INTERFACE_TYPE;
+
+typedef struct _SURFACE_INFO {
+  UINT32 PhyAddr;
+  UINT32 *VirtAddrPtr;
+  UINT32 Width;
+  UINT32 Height;
+  UINT32 Pitch;
+  UINT32 Bpp;
+  PIXEL_FORMAT PixelFormat;
+} SURFACE_INFO, *PSURFACE_INFO;
+
+typedef struct _IPU_DIx_REGS {
+  UINT32 DIxGENERAL;
+  UINT32 DIxBS_CLKGEN0;
+  UINT32 DIxBS_CLKGEN1;
+  UINT32 DIxSW_GEN0_1;
+  UINT32 DIxSW_GEN0_2;
+  UINT32 DIxSW_GEN0_3;
+  UINT32 DIxSW_GEN0_4;
+  UINT32 DIxSW_GEN0_5;
+  UINT32 DIxSW_GEN0_6;
+  UINT32 DIxSW_GEN0_7;
+  UINT32 DIxSW_GEN0_8;
+  UINT32 DIxSW_GEN0_9;
+  UINT32 DIxSW_GEN1_1;
+  UINT32 DIxSW_GEN1_2;
+  UINT32 DIxSW_GEN1_3;
+  UINT32 DIxSW_GEN1_4;
+  UINT32 DIxSW_GEN1_5;
+  UINT32 DIxSW_GEN1_6;
+  UINT32 DIxSW_GEN1_7;
+  UINT32 DIxSW_GEN1_8;
+  UINT32 DIxSW_GEN1_9;
+  UINT32 DIxSYNC_AS_GEN;
+  UINT32 DIxDW_GEN[12];
+  UINT32 DIxDW_SET0[12];
+  UINT32 DIxDW_SET1[12];
+  UINT32 DIxDW_SET2[12];
+  UINT32 DIxDW_SET3[12];
+  UINT32 DIxSTP_REP[4];
+  UINT32 DIxSTP_REP_9;
+  UINT32 DIxSER_CONF;
+  UINT32 DIxSSC;
+  UINT32 DIxPOL;
+  UINT32 DIxAW0;
+  UINT32 DIxAW1;
+  UINT32 DIxSCR_CONF;
+  UINT32 DIxSTAT;
+} IPU_DIx_REGS, *PIPU_DIx_REGS;
+
+typedef struct _DISPLAY_INTERFACE_CONTEXT {
+  DISPLAY_INTERFACE_TYPE displayInterface;
+
+  VOID *MmioBasePtr;
+  VOID *IpuMmioBasePtr;
+  VOID *CpMemParamBasePtr;
+  IPU_DIx_REGS *IpuDiRegsPtr;
+  UINT32 EdidDataSize;
+  UINT8 EdidData[256];
+  DISPLAY_TIMING PreferredTiming;
+} DISPLAY_INTERFACE_CONTEXT, *PDISPLAY_INTERFACE_CONTEXT;
+
+typedef struct _DISPLAY_CONFIG {
+  DISPLAY_MODE DisplayMode;
+  DISPLAY_INTERFACE_TYPE DiOrder[DisplayTypeMax];
+  SURFACE_INFO DisplaySurface[DisplayTypeMax];
+  DISPLAY_TIMING DisplayTiming[DisplayTypeMax];
+  UINT32 OsHandle[DisplayTypeMax];
+} DISPLAY_CONFIG, *PDISPLAY_CONFIG;
+
+typedef struct _DISPLAY_CONTEXT {
+  DISPLAY_CONFIG DisplayConfig;
+  VOID *IoMuxMmioBasePtr;
+  VOID *IpuMmioBasePtr[IPU_TOTAL];
+  DISPLAY_INTERFACE_CONTEXT DiContext[DisplayTypeMax];
+} DISPLAY_CONTEXT, *PDISPLAY_CONTEXT;
+
+extern DISPLAY_TIMING DefaultTiming;
+
+EFI_STATUS
+GetPreferredTiming (
+  IN  UINT8           *EdidDataPtr,
+  IN  UINT32          EdidDataSize,
+  IN  DISPLAY_TIMING  *PreferredTimingPtr
+  );
+
+EFI_STATUS
+InitDisplay (
+  IN  DISPLAY_CONTEXT   **DisplayConfigPPtr
+  );
+
+EFI_STATUS
+ValidateDisplayConfig (
+  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN  DISPLAY_MODE        DisplayMode,
+  IN  DISPLAY_INTERFACE_TYPE   *DiOrder
+  );
+
+EFI_STATUS
+SetDisplayConfig (
+  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN      DISPLAY_MODE        DisplayMode,
+  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
+  );
+
+EFI_STATUS
+ApplyDisplayConfig (
+  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN      DISPLAY_MODE        DisplayMode,
+  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
+  );
+
+EFI_STATUS
+AllocateFrameBuffer (
+  IN OUT  SURFACE_INFO  *SurfaceInfoPtr
+  );
+
+EFI_STATUS
+ConfigureFrameBuffer (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  SURFACE_INFO                *FrameBufferPtr
+  );
+
+UINT32
+GetColorDepth (
+  IN  PIXEL_FORMAT  PixelFormat
+  );
+
+#endif  /* _DISPLAY_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
new file mode 100644
index 000000000000..7a5fc7e3d6c3
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
@@ -0,0 +1,399 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Ipu.h"
+#include "Display.h"
+#include "DisplayController.h"
+#include "DisplayInterface.h"
+
+#ifdef DEBUG
+VOID
+DumpBasicDisplayControllerReg (
+  IN  VOID  *IpuMmioBasePtr
+  )
+{
+  UINT32 Counter;
+  UINT32 Index;
+  UINT32 RegVal;
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ------- DC Register Dump -------\n", __FUNCTION__));
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ## Configuration\n\n", __FUNCTION__));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_WR_CH_CONF_5_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_1_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_WR_CH_CONF_1_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_0_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_0_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_1_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_1_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_2_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_2_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_3_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_3_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF2_0_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF2_0_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_GEN_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_GEN_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ## Bus MAPPING\n\n", __FUNCTION__));
+  {
+    for (Counter = 0, Index = 0; Index < 26; Counter += 4, ++Index) {
+      RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_MAP_CONF_0_OFFSET + Counter);
+      DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_MAP_CONF_%d %x\n",
+        __FUNCTION__, Index, RegVal));
+    }
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ## Channel MicroCode setup\n\n", __FUNCTION__));
+  // Only print out channel 5 as we only support single mode for now
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL0_CH_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL0_CH_5_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL1_CH_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL1_CH_5_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL2_CH_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL2_CH_5_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL3_CH_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL3_CH_5_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL4_CH_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL4_CH_5_OFFSET %x\n",
+    __FUNCTION__, RegVal));
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ## MicroCode\n\n", __FUNCTION__));
+  // There are 256 template, only print out the first 10
+  for (Counter = 0, Index = 0; Index < 10; Counter += 8, ++Index) {
+    DEBUG ((DEBUG_VERBOSE, "%a: (%d)\n", __FUNCTION__, Index));
+    RegVal = IpuRead32 (
+                IpuMmioBasePtr,
+                IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + Counter);
+    DEBUG ((DEBUG_VERBOSE, "%a: - %8x\n", __FUNCTION__, RegVal));
+    RegVal = IpuRead32 (
+                IpuMmioBasePtr,
+                IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + Counter + 4);
+    DEBUG ((DEBUG_VERBOSE, "%a:  %8x -\n", __FUNCTION__, RegVal));
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ---------------------------\n\n", __FUNCTION__));
+}
+#endif /* DEBUG */
+
+EFI_STATUS
+WriteWrodCommand (
+  IN  VOID    *IpuMmioBasePtr,
+  IN  UINT32  MicroCodeAddr,
+  IN  UINT32  Data,
+  IN  UINT32  Mapping,
+  IN  UINT32  WaveForm,
+  IN  UINT32  GlueLogic,
+  IN  UINT32  Sync
+  )
+{
+  UINT32                            MicroCodeAddrOffset;
+  DISPLAY_CONTROLLER_WROD_COMMAND   WrodCommand;
+
+
+  MicroCodeAddrOffset = IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + (MicroCodeAddr * 8);
+  ZeroMem ((VOID *)&WrodCommand, sizeof (WrodCommand));
+  WrodCommand.STOP = 1;
+  WrodCommand.OPCODE = 0x18;
+  WrodCommand.DATA = Data;
+  WrodCommand.MAPPING = Mapping;
+  WrodCommand.WAVEFORM = WaveForm + 1;
+  WrodCommand.GLUELOGIC = GlueLogic;
+  WrodCommand.SYNC = Sync;
+  IpuWrite32 (IpuMmioBasePtr, MicroCodeAddrOffset, WrodCommand.LowWord);
+  IpuWrite32 (IpuMmioBasePtr, MicroCodeAddrOffset + 4, WrodCommand.HighWord);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetDisplayControllerChannelState (
+  IN  VOID *IpuMmioBasePtr,
+  IN  PROG_CHAN_TYP ChannelType
+  )
+{
+  IPU_DC_WR_CH_CONF_5_REG   WrChConfigReg;
+
+  WrChConfigReg.Reg = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET);
+  WrChConfigReg.PROG_CHAN_TYP = ChannelType;
+  IpuWrite32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET, WrChConfigReg.Reg);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConfigureDisplayControllerChannel (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  DISPLAY_INTERFACE_TYPE           DisplayInterface,
+  IN  UINT32                      DisplayIndex,
+  IN  DISPLAY_TIMING              *DisplayTimingPtr
+  )
+{
+  VOID                          *pIpuMmioBase;
+  DC_MAP_CONF_OFFSET_MASK_REG   DcConfOffsetMaskReg;
+  IPUx_DC_MAP_CONF_MAP_REG      DcMapConf0Reg;
+  IPU_DC_RL0_CH_5_REG           DcRl0Ch5Reg;
+  IPU_DC_RL2_CH_5_REG           DcRl2Ch5Reg;
+  IPU_DC_RL4_CH_5_REG           DcRl4Ch5Reg;
+  IPUx_DC_DISP_CONF1_REG        DisplayConfig1Reg;
+  IPUx_IPU_DC_GEN_REG           DisplayControllerGenReg;
+  UINT32                        Mask0;
+  UINT32                        Mask1;
+  UINT32                        Mask2;
+  UINT32                        Offset0;
+  UINT32                        Offset1;
+  UINT32                        Offset2;
+  EFI_STATUS                    Status;
+  IPU_DC_WR_CH_CONF_5_REG       WrChConfigReg;
+
+  pIpuMmioBase = DisplayInterfaceContextPtr->IpuMmioBasePtr;
+  Status = EFI_SUCCESS;
+
+  ZeroMem ((VOID *)&WrChConfigReg, sizeof (WrChConfigReg));
+  WrChConfigReg.PROG_START_TIME = 0;
+  WrChConfigReg.FILED_MODE = 0;
+  WrChConfigReg.CHAN_MASK_DEFAULT = 0; // only used highest priority
+  WrChConfigReg.PROG_CHAN_TYP = 0; // Begin as disable
+  WrChConfigReg.PROG_DISP_ID = DisplayInterface;
+  WrChConfigReg.PROG_DI_ID = DisplayIndex % 2;
+  WrChConfigReg.W_SIZE = 0x02; // 24 Bits
+  WrChConfigReg.Reserved1 = 0;
+  WrChConfigReg.Reserved2 = 0;
+  // Channel 5 is used main primary flow
+  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_CONF_5_OFFSET, WrChConfigReg.Reg);
+  // Start address of memory always 0
+  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_ADDR_5_OFFSET, 0);
+
+  ZeroMem ((VOID *)&WrChConfigReg, sizeof (WrChConfigReg));
+  WrChConfigReg.FILED_MODE = 0;
+  WrChConfigReg.CHAN_MASK_DEFAULT = 0; // only used highest priority
+  WrChConfigReg.PROG_CHAN_TYP = 4; // Enable
+  WrChConfigReg.PROG_DISP_ID = DisplayInterface;
+  WrChConfigReg.PROG_DI_ID = DisplayIndex % 2;
+  WrChConfigReg.W_SIZE = 0x02; // 1 Bits
+  WrChConfigReg.Reserved1 = 0;
+  WrChConfigReg.Reserved2 = 0;
+
+  // Channel 1 is used as sync/async flow
+  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_CONF_1_OFFSET, WrChConfigReg.Reg);
+  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_ADDR_1_OFFSET, 0);
+
+  DisplayConfig1Reg.DISP_TYP = 0x02; // What is byte_enabled
+  DisplayConfig1Reg.ADDR_INCREMENT = 0; // Increase by 1 byte
+  DisplayConfig1Reg.ADDR_BE_L_INC = 0;
+  DisplayConfig1Reg.MCU_ACC_LB_MASK_3 = 0;
+  DisplayConfig1Reg.DISP_RD_VALUE_PTR = 0;
+  IpuWrite32 (pIpuMmioBase, IPU_DC_DISP_CONF1_0_OFFSET, DisplayConfig1Reg.Reg);
+
+  // Set stride
+  IpuWrite32 (pIpuMmioBase, IPU_DC_DISP_CONF2_0_OFFSET, DisplayTimingPtr->VActive);
+
+  // Setup general register. Channel 5 is the main channel.
+  DisplayControllerGenReg.Sync_1_6 = 2; // Sync flow
+  DisplayControllerGenReg.MASK_EN = 0; // Disable masking
+  DisplayControllerGenReg.MASK4CHAN_5 = 0; // Ignore as mask is disabled
+  DisplayControllerGenReg.SYNC_PRIORITY_5 = 1; // Higher sync priority for channel 5
+  DisplayControllerGenReg.SYNC_PRIORITY_1 = 0; // Lower sync priority
+  DisplayControllerGenReg.DC_CH5_TYPE = 0; // Normal mode, sync flow through channel 5
+  DisplayControllerGenReg.DC_BK_EN = 0; // No cursor support
+  DisplayControllerGenReg.DC_BKDIV = 0; // No cursor support
+  IpuWrite32 (pIpuMmioBase, IPU_DC_GEN_OFFSET, DisplayControllerGenReg.Reg);
+
+  // Do not use any user event
+  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE0_0_OFFSET, 0);
+  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE1_0_OFFSET, 0);
+  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE2_0_OFFSET, 0);
+  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE3_0_OFFSET, 0);
+
+  DcMapConf0Reg.MAPPING_PNTR_BYTE0_X = 0;
+  DcMapConf0Reg.MAPPING_PNTR_BYTE1_X = 1;
+  DcMapConf0Reg.MAPPING_PNTR_BYTE2_X = 2;
+  DcMapConf0Reg.MAPPING_PNTR_BYTE0_Y = 3; // Unused
+  DcMapConf0Reg.MAPPING_PNTR_BYTE1_Y = 4; // Unused
+  DcMapConf0Reg.MAPPING_PNTR_BYTE2_Y = 5; // Unused
+  IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_0_OFFSET, DcMapConf0Reg.Reg);
+
+  switch (DisplayInterface) {
+  // PixelFormat RGB24
+  case HdmiDisplay:
+    Mask0 = 0xFF;
+    Mask1 = 0xFF;
+    Mask2 = 0xFF;
+    Offset0 = 7;
+    Offset1 = 15;
+    Offset2 = 23;
+    break;
+  // PixelFormat RGB666
+  case Lvds0Display:
+  case Lvds1Display:
+    Mask0 = 0xFC;
+    Mask1 = 0xFC;
+    Mask2 = 0xFC;
+    Offset0 = 5;
+    Offset1 = 11;
+    Offset2 = 17;
+    break;
+  default:
+    ASSERT (FALSE);
+    Status = EFI_UNSUPPORTED;
+    break;
+  }
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  DcConfOffsetMaskReg.MD_MASK_X = Mask0;
+  DcConfOffsetMaskReg.MD_OFFSET_X = Offset0; // Blue
+  DcConfOffsetMaskReg.MD_MASK_Y = Mask1;
+  DcConfOffsetMaskReg.MD_OFFSET_Y = Offset1; // Green
+  IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_15_OFFSET, DcConfOffsetMaskReg.Reg);
+
+  DcConfOffsetMaskReg.MD_MASK_X = Mask2;
+  DcConfOffsetMaskReg.MD_OFFSET_X = Offset2; // Red
+  DcConfOffsetMaskReg.MD_MASK_Y = 0x00;
+  DcConfOffsetMaskReg.MD_OFFSET_Y = 0; // Unused
+  IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_16_OFFSET, DcConfOffsetMaskReg.Reg);
+
+  // Setup microcode
+  // New line event point to the first microcode (0)
+  ZeroMem ((VOID *)&DcRl0Ch5Reg, sizeof (DcRl0Ch5Reg));
+  DcRl0Ch5Reg.COD_NL_START_CHAN_5 = 0;
+  DcRl0Ch5Reg.COD_NL_PRIORITY_CHAN_5 = 3;
+  IpuWrite32 (pIpuMmioBase, IPU_DC_RL0_CH_5_OFFSET, DcRl0Ch5Reg.Reg);
+
+  // End of line event point to the second microcode (1)
+  ZeroMem ((VOID *)&DcRl2Ch5Reg, sizeof (DcRl2Ch5Reg));
+  DcRl2Ch5Reg.COD_EOL_START_CHAN_5 = 1;
+  DcRl2Ch5Reg.COD_EOL_PRIORITY_CHAN_5 = 2;
+  IpuWrite32 (pIpuMmioBase, IPU_DC_RL2_CH_5_OFFSET, DcRl2Ch5Reg.Reg);
+
+  // New data event point to the first microcode (2)
+  ZeroMem ((VOID *)&DcRl4Ch5Reg, sizeof (DcRl4Ch5Reg));
+  DcRl4Ch5Reg.COD_NEW_DATA_START_CHAN_5 = 2;
+  DcRl4Ch5Reg.COD_NEW_DATA_PRIORITY_CHAN_5 = 1;
+  IpuWrite32 (pIpuMmioBase, IPU_DC_RL4_CH_5_OFFSET, DcRl4Ch5Reg.Reg);
+
+  // MicroCodeAddr
+  // - 0 set for new line event
+  // Data
+  // - Unsused
+  // Map to mapping parameter 0
+  // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0,
+  //   MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field
+  // WaveForm
+  // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform
+  //   register is used, default to first IPUx_DI0_DW_SET0_1)
+  // GlueLogic
+  // - Once the signal is asserted then it remains asserted (high or low
+  //   according to the polarity)
+  // Sync
+  // - Sync with Counter 5
+  WriteWrodCommand (
+    pIpuMmioBase,
+    0,
+    0,
+    1,
+    DwGen0,
+    8,
+    DI_COUNTER_5_ACTIVE_CLOCK
+  );
+
+  // MicroCodeAddr
+  // - 1 set for end of line event
+  // Data
+  // - Unsused
+  // Map to mapping parameter 0
+  // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0,
+  //   MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field
+  // WaveForm
+  // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform
+  //   register is used, default to first IPUx_DI0_DW_SET0_1)
+  // GlueLogic
+  // - Once the signal is negated then it remains negated (high or low
+  //   according to the polarity)
+  // Sync
+  // - Sync with Counter 5
+  WriteWrodCommand (
+    pIpuMmioBase,
+    1,
+    0,
+    1,
+    DwGen0,
+    4,
+    DI_COUNTER_5_ACTIVE_CLOCK
+  );
+
+  // MicroCodeAddr
+  // - 2 set for new data event
+  // Data
+  // - Unsused
+  // Map to mapping parameter 0
+  // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0,
+  //   MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field
+  // WaveForm
+  // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform
+  //   register is used, default to first IPUx_DI0_DW_SET0_1)
+  // GlueLogic
+  // - CS mode No impact on the waveform
+  // Sync
+  // - Sync with channel 5
+  WriteWrodCommand (
+    pIpuMmioBase,
+    2,
+    0,
+    1,
+    DwGen0,
+    8,
+    DI_COUNTER_5_ACTIVE_CLOCK
+  );
+
+  // Turn on channel without anti tearing
+  SetDisplayControllerChannelState (
+    DisplayInterfaceContextPtr->IpuMmioBasePtr,
+    PROG_CHAN_TYP_NORMAL
+  );
+
+#ifdef DEBUG
+  DumpBasicDisplayControllerReg (pIpuMmioBase);
+#endif /* DEBUG */
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
new file mode 100644
index 000000000000..46f0fa66d674
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
@@ -0,0 +1,331 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _DISPLAY_CONTROLLER_H_
+#define _DISPLAY_CONTROLLER_H_
+
+#define IPU_DC_OFFSET 0x00058000
+
+// DC Registers
+#define IPU_DC_READ_CH_CONF_OFFSET              IPU_DC_OFFSET + 0x0000
+#define IPU_DC_READ_CH_ADDR_OFFSET              IPU_DC_OFFSET + 0x0004
+#define IPU_DC_RL0_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0008
+#define IPU_DC_RL1_CH_0_OFFSET                  IPU_DC_OFFSET + 0x000C
+#define IPU_DC_RL2_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0010
+#define IPU_DC_RL3_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0014
+#define IPU_DC_RL4_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0018
+#define IPU_DC_WR_CH_CONF_1_OFFSET              IPU_DC_OFFSET + 0x001C
+#define IPU_DC_WR_CH_ADDR_1_OFFSET              IPU_DC_OFFSET + 0x0020
+#define IPU_DC_RL0_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0024
+#define IPU_DC_RL1_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0028
+#define IPU_DC_RL2_CH_1_OFFSET                  IPU_DC_OFFSET + 0x002C
+#define IPU_DC_RL3_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0030
+#define IPU_DC_RL4_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0034
+#define IPU_DC_WR_CH_CONF_2_OFFSET              IPU_DC_OFFSET + 0x0038
+#define IPU_DC_WR_CH_ADDR_2_OFFSET              IPU_DC_OFFSET + 0x003C
+#define IPU_DC_RL0_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0040
+#define IPU_DC_RL1_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0044
+#define IPU_DC_RL2_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0048
+#define IPU_DC_RL3_CH_2_OFFSET                  IPU_DC_OFFSET + 0x004C
+#define IPU_DC_RL4_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0050
+#define IPU_DC_CMD_CH_CONF_3_OFFSET             IPU_DC_OFFSET + 0x0054
+#define IPU_DC_CMD_CH_CONF_4_OFFSET             IPU_DC_OFFSET + 0x0058
+#define IPU_DC_WR_CH_CONF_5_OFFSET              IPU_DC_OFFSET + 0x005C
+#define IPU_DC_WR_CH_ADDR_5_OFFSET              IPU_DC_OFFSET + 0x0060
+#define IPU_DC_RL0_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0064
+#define IPU_DC_RL1_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0068
+#define IPU_DC_RL2_CH_5_OFFSET                  IPU_DC_OFFSET + 0x006C
+#define IPU_DC_RL3_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0070
+#define IPU_DC_RL4_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0074
+#define IPU_DC_WR_CH_CONF_6_OFFSET              IPU_DC_OFFSET + 0x0078
+#define IPU_DC_WR_CH_ADDR_6_OFFSET              IPU_DC_OFFSET + 0x007C
+#define IPU_DC_RL0_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0080
+#define IPU_DC_RL1_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0084
+#define IPU_DC_RL2_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0088
+#define IPU_DC_RL3_CH_6_OFFSET                  IPU_DC_OFFSET + 0x008C
+#define IPU_DC_RL4_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0090
+#define IPU_DC_WR_CH_CONF1_8_OFFSET             IPU_DC_OFFSET + 0x0094
+#define IPU_DC_WR_CH_CONF2_8_OFFSET             IPU_DC_OFFSET + 0x0098
+#define IPU_DC_RL1_CH_8_OFFSET                  IPU_DC_OFFSET + 0x009C
+#define IPU_DC_RL2_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00A0
+#define IPU_DC_RL3_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00A4
+#define IPU_DC_RL4_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00A8
+#define IPU_DC_RL5_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00AC
+#define IPU_DC_RL6_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00B0
+#define IPU_DC_WR_CH_CONF1_9_OFFSET             IPU_DC_OFFSET + 0x00B4
+#define IPU_DC_WR_CH_CONF2_9_OFFSET             IPU_DC_OFFSET + 0x00B8
+#define IPU_DC_RL1_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00BC
+#define IPU_DC_RL2_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00C0
+#define IPU_DC_RL3_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00C4
+#define IPU_DC_RL4_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00C8
+#define IPU_DC_RL5_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00CC
+#define IPU_DC_RL6_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00D0
+#define IPU_DC_GEN_OFFSET                       IPU_DC_OFFSET + 0x00D4
+#define IPU_DC_DISP_CONF1_0_OFFSET              IPU_DC_OFFSET + 0x00D8
+#define IPU_DC_DISP_CONF1_1_OFFSET              IPU_DC_OFFSET + 0x00DC
+#define IPU_DC_DISP_CONF1_2_OFFSET              IPU_DC_OFFSET + 0x00E0
+#define IPU_DC_DISP_CONF1_3_OFFSET              IPU_DC_OFFSET + 0x00E4
+#define IPU_DC_DISP_CONF2_0_OFFSET              IPU_DC_OFFSET + 0x00E8
+#define IPU_DC_DISP_CONF2_1_OFFSET              IPU_DC_OFFSET + 0x00EC
+#define IPU_DC_DISP_CONF2_2_OFFSET              IPU_DC_OFFSET + 0x00F0
+#define IPU_DC_DISP_CONF2_3_OFFSET              IPU_DC_OFFSET + 0x00F4
+#define IPU_DC_DI0_CONF1_OFFSET                 IPU_DC_OFFSET + 0x00F8
+#define IPU_DC_DI0_CONF2_OFFSET                 IPU_DC_OFFSET + 0x00FC
+#define IPU_DC_DI1_CONF1_OFFSET                 IPU_DC_OFFSET + 0x0100
+#define IPU_DC_DI1_CONF2_OFFSET                 IPU_DC_OFFSET + 0x0104
+#define IPU_DC_MAP_CONF_0_OFFSET                IPU_DC_OFFSET + 0x0108
+#define IPU_DC_MAP_CONF_1_OFFSET                IPU_DC_OFFSET + 0x010C
+#define IPU_DC_MAP_CONF_2_OFFSET                IPU_DC_OFFSET + 0x0110
+#define IPU_DC_MAP_CONF_3_OFFSET                IPU_DC_OFFSET + 0x0114
+#define IPU_DC_MAP_CONF_4_OFFSET                IPU_DC_OFFSET + 0x0118
+#define IPU_DC_MAP_CONF_5_OFFSET                IPU_DC_OFFSET + 0x011C
+#define IPU_DC_MAP_CONF_6_OFFSET                IPU_DC_OFFSET + 0x0120
+#define IPU_DC_MAP_CONF_7_OFFSET                IPU_DC_OFFSET + 0x0124
+#define IPU_DC_MAP_CONF_8_OFFSET                IPU_DC_OFFSET + 0x0128
+#define IPU_DC_MAP_CONF_9_OFFSET                IPU_DC_OFFSET + 0x012C
+#define IPU_DC_MAP_CONF_10_OFFSET               IPU_DC_OFFSET + 0x0130
+#define IPU_DC_MAP_CONF_11_OFFSET               IPU_DC_OFFSET + 0x0134
+#define IPU_DC_MAP_CONF_12_OFFSET               IPU_DC_OFFSET + 0x0138
+#define IPU_DC_MAP_CONF_13_OFFSET               IPU_DC_OFFSET + 0x013C
+#define IPU_DC_MAP_CONF_14_OFFSET               IPU_DC_OFFSET + 0x0140
+#define IPU_DC_MAP_CONF_15_OFFSET               IPU_DC_OFFSET + 0x0144
+#define IPU_DC_MAP_CONF_16_OFFSET               IPU_DC_OFFSET + 0x0148
+#define IPU_DC_MAP_CONF_17_OFFSET               IPU_DC_OFFSET + 0x014C
+#define IPU_DC_MAP_CONF_18_OFFSET               IPU_DC_OFFSET + 0x0150
+#define IPU_DC_MAP_CONF_19_OFFSET               IPU_DC_OFFSET + 0x0154
+#define IPU_DC_MAP_CONF_20_OFFSET               IPU_DC_OFFSET + 0x0158
+#define IPU_DC_MAP_CONF_21_OFFSET               IPU_DC_OFFSET + 0x015C
+#define IPU_DC_MAP_CONF_22_OFFSET               IPU_DC_OFFSET + 0x0160
+#define IPU_DC_MAP_CONF_23_OFFSET               IPU_DC_OFFSET + 0x0164
+#define IPU_DC_MAP_CONF_24_OFFSET               IPU_DC_OFFSET + 0x0168
+#define IPU_DC_MAP_CONF_25_OFFSET               IPU_DC_OFFSET + 0x016C
+#define IPU_DC_MAP_CONF_26_OFFSET               IPU_DC_OFFSET + 0x0170
+#define IPU_DC_UGDE0_0_OFFSET                   IPU_DC_OFFSET + 0x0174
+#define IPU_DC_UGDE0_1_OFFSET                   IPU_DC_OFFSET + 0x0178
+#define IPU_DC_UGDE0_2_OFFSET                   IPU_DC_OFFSET + 0x017C
+#define IPU_DC_UGDE0_3_OFFSET                   IPU_DC_OFFSET + 0x0180
+#define IPU_DC_UGDE1_0_OFFSET                   IPU_DC_OFFSET + 0x0184
+#define IPU_DC_UGDE1_1_OFFSET                   IPU_DC_OFFSET + 0x0188
+#define IPU_DC_UGDE1_2_OFFSET                   IPU_DC_OFFSET + 0x018C
+#define IPU_DC_UGDE1_3_OFFSET                   IPU_DC_OFFSET + 0x0190
+#define IPU_DC_UGDE2_0_OFFSET                   IPU_DC_OFFSET + 0x0194
+#define IPU_DC_UGDE2_1_OFFSET                   IPU_DC_OFFSET + 0x0198
+#define IPU_DC_UGDE2_2_OFFSET                   IPU_DC_OFFSET + 0x019C
+#define IPU_DC_UGDE2_3_OFFSET                   IPU_DC_OFFSET + 0x01A0
+#define IPU_DC_UGDE3_0_OFFSET                   IPU_DC_OFFSET + 0x01A4
+#define IPU_DC_UGDE3_1_OFFSET                   IPU_DC_OFFSET + 0x01A8
+#define IPU_DC_UGDE3_2_OFFSET                   IPU_DC_OFFSET + 0x01AC
+#define IPU_DC_UGDE3_3_OFFSET                   IPU_DC_OFFSET + 0x01B0
+#define IPU_DC_LLA0_OFFSET                      IPU_DC_OFFSET + 0x01B4
+#define IPU_DC_LLA1_OFFSET                      IPU_DC_OFFSET + 0x01B8
+#define IPU_DC_R_LLA0_OFFSET                    IPU_DC_OFFSET + 0x01BC
+#define IPU_DC_R_LLA1_OFFSET                    IPU_DC_OFFSET + 0x01C0
+#define IPU_DC_WR_CH_ADDR_5_ALT_OFFSET          IPU_DC_OFFSET + 0x01C4
+#define IPU_DC_STAT_OFFSET                      IPU_DC_OFFSET + 0x01C8
+
+// Microcode template
+#define IPU_DC_TEMPLATE_REGS_ADDR_OFFSET        0x00180000
+
+typedef enum {
+  DC_CHANNEL_READ = 0,
+  DC_CHANNEL_DC_SYNC_ASYNC = 1,
+  DC_CHANNEL_DC_ASYNC = 2,
+  DC_CHANNEL_DP_MAIN = 5,
+  DC_CHANNEL_DP_SECONDARY = 6,
+} DC_CHANNEL;
+
+#pragma pack(push, 1)
+
+// IPU_DC_WR_CH_CONF_1 0x1C
+// IPU_DC_WR_CH_CONF_5 0x5C
+typedef union {
+  struct {
+    UINT32 W_SIZE : 2;
+    UINT32 PROG_DI_ID : 1;
+    UINT32 PROG_DISP_ID : 2;
+    UINT32 PROG_CHAN_TYP : 3;
+    UINT32 CHAN_MASK_DEFAULT : 1;
+    UINT32 FILED_MODE : 1;
+    UINT32 Reserved1 : 6;
+    UINT32 PROG_START_TIME : 11;
+    UINT32 Reserved2 : 5;
+  };
+  UINT32 Reg;
+} IPU_DC_WR_CH_CONF_1_REG, IPU_DC_WR_CH_CONF_5_REG;
+
+typedef enum {
+  PROG_CHAN_TYP_DISABLED,
+  PROG_CHAN_TYP_RESERVED1,
+  PROG_CHAN_TYP_NORMAL = 4,
+  PROG_CHAN_TYP_NORMAL_ANTI_TEARING,
+  PROG_CHAN_TYP_RESERVED2,
+} PROG_CHAN_TYP;
+
+// IPU_DC_GEN 0xD4
+typedef union {
+  struct {
+    UINT32 Reserved1 : 1;
+    UINT32 Sync_1_6 : 2;
+    UINT32 Reserved2 : 1;
+    UINT32 MASK_EN : 1;
+    UINT32 MASK4CHAN_5 : 1;
+    UINT32 SYNC_PRIORITY_5 : 1;
+    UINT32 SYNC_PRIORITY_1 : 1;
+    UINT32 DC_CH5_TYPE : 1;
+    UINT32 Reserved3 : 7;
+    UINT32 DC_BKDIV : 8;
+    UINT32 DC_BK_EN : 1;
+    UINT32 Reserved4 : 7;
+  };
+  UINT32 Reg;
+} IPUx_IPU_DC_GEN_REG;
+
+// IPU_DC_RL0_CH_5 0x0064
+typedef union {
+  struct {
+    UINT32 COD_NF_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved1 : 4;
+    UINT32 COD_NF_START_CHAN_5 : 8;
+    UINT32 COD_NL_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved2 : 4;
+    UINT32 COD_NL_START_CHAN_5 : 24;
+  };
+  UINT32 Reg;
+} IPU_DC_RL0_CH_5_REG;
+
+// IPU_DC_RL1_CH_5 0x006C
+typedef union {
+  struct {
+    UINT32 COD_EOF_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved1 : 4;
+    UINT32 COD_EOF_START_CHAN_5 : 8;
+    UINT32 COD_NFIELD_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved2 : 4;
+    UINT32 COD_NFIELD_START_CHAN_5 : 24;
+  };
+  UINT32 Reg;
+} IPU_DC_RL1_CH_5_REG;
+
+// IPU_DC_RL2_CH_5 0x0068
+typedef union {
+  struct {
+    UINT32 COD_EOL_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved1 : 4;
+    UINT32 COD_EOL_START_CHAN_5 : 8;
+    UINT32 COD_EOFIELD_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved2 : 4;
+    UINT32 COD_EOFIELD_START_CHAN_5 : 24;
+  };
+  UINT32 Reg;
+} IPU_DC_RL2_CH_5_REG;
+
+// IPU_DC_RL3_CH_5 0x0070
+typedef union {
+  struct {
+    UINT32 COD_NEW_ADDR_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved1 : 4;
+    UINT32 COD_NEW_ADDR_START_CHAN_5 : 8;
+    UINT32 COD_NEW_CHAN_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved2 : 4;
+    UINT32 COD_NEW_CHAN_START_CHAN_5 : 24;
+  };
+  UINT32 Reg;
+} IPU_DC_RL3_CH_5_REG;
+
+// IPU_DC_RL4_CH_5 0x0074
+typedef union {
+  struct {
+    UINT32 COD_NEW_DATA_PRIORITY_CHAN_5 : 4;
+    UINT32 Reserved1 : 4;
+    UINT32 COD_NEW_DATA_START_CHAN_5 : 8;
+    UINT32 Reserved2 : 16;
+  };
+  UINT32 Reg;
+} IPU_DC_RL4_CH_5_REG;
+
+// DC_DISP_CONF1 0xD8 - 0xE4
+typedef union {
+  struct {
+    UINT32 DISP_TYP : 2;
+    UINT32 ADDR_INCREMENT : 2;
+    UINT32 ADDR_BE_L_INC : 2;
+    UINT32 MCU_ACC_LB_MASK_3 : 1;
+    UINT32 DISP_RD_VALUE_PTR : 1;
+    UINT32 Reserved : 24;
+  };
+  UINT32 Reg;
+} IPUx_DC_DISP_CONF1_REG;
+
+// DC_MAP_CONF_MAP_OFFSET 0x0108 - 0x0140
+typedef union {
+  struct {
+    UINT32 MAPPING_PNTR_BYTE0_X : 5;
+    UINT32 MAPPING_PNTR_BYTE1_X : 5;
+    UINT32 MAPPING_PNTR_BYTE2_X : 5;
+    UINT32 Reserved1 : 1;
+    UINT32 MAPPING_PNTR_BYTE0_Y : 5;
+    UINT32 MAPPING_PNTR_BYTE1_Y : 5;
+    UINT32 MAPPING_PNTR_BYTE2_Y : 5;
+    UINT32 Reserved2 : 1;
+  };
+  UINT32 Reg;
+} IPUx_DC_MAP_CONF_MAP_REG;
+
+// DC_MAP_CONF_OFFSET_MASK_OFFSET 0x0144 - 0x0170
+typedef union {
+  struct {
+    UINT32 MD_MASK_X : 8;
+    UINT32 MD_OFFSET_X : 5;
+    UINT32 Reserved1 : 3;
+    UINT32 MD_MASK_Y : 8;
+    UINT32 MD_OFFSET_Y : 5;
+    UINT32 Reserved2 : 3;
+  };
+  UINT32 Reg;
+} DC_MAP_CONF_OFFSET_MASK_REG;
+
+typedef union {
+  struct {
+    UINT32 SYNC : 4;
+    UINT32 GLUELOGIC : 7;
+    UINT32 WAVEFORM : 4;
+    UINT32 MAPPING : 5;
+    UINT32 DATA : 16;
+    UINT32 OPCODE : 5;
+    UINT32 STOP : 1;
+    UINT32 Unused : 22;
+  };
+  struct     {
+    UINT32 LowWord;
+    UINT32 HighWord;
+  };
+} DISPLAY_CONTROLLER_WROD_COMMAND;
+
+#pragma pack(pop)
+
+EFI_STATUS
+SetDisplayControllerChannelState (
+  IN  VOID *IpuMmioBasePtr,
+  IN  PROG_CHAN_TYP ChannelType
+  );
+
+EFI_STATUS
+ConfigureDisplayControllerChannel (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  DISPLAY_INTERFACE_TYPE           DisplayInterface,
+  IN  UINT32                      DisplayIndex,
+  IN  DISPLAY_TIMING              *DisplayTimingPtr
+  );
+
+#endif  /* _DISPLAY_CONTROLLER_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
new file mode 100644
index 000000000000..b36d03239652
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
@@ -0,0 +1,458 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Ipu.h"
+#include "Display.h"
+#include "DisplayInterface.h"
+
+#ifdef DEBUG
+VOID
+DumpBasicDisplayInterfaceReg (
+  IN  VOID          *IpuMmioBasePtr,
+  IN  IPU_DIx_REGS  *IpuDiRegsPtr
+  )
+{
+  UINT32 index, setNumber, regVal;
+  UINT32 printTotalGen = 8; // Limit printing (max 12)
+
+  DEBUG ((DEBUG_VERBOSE, "%a: ------- DI Register Dump -------\n", __FUNCTION__));
+  // Print out generator value for D0
+  DEBUG ((DEBUG_VERBOSE, "%a: ## Wave Gen\n", __FUNCTION__));
+  for (index = 0; index < printTotalGen; ++index) {
+    regVal = READ_WAVE_GEN (IpuDiRegsPtr, index);
+    DEBUG ((DEBUG_VERBOSE, "%a: DI0_DW_GEN_%d 0x%08x\n",
+      __FUNCTION__, index, regVal));
+  }
+  // Print out generator value for D0
+  DEBUG ((DEBUG_VERBOSE, "%a: ## Wave Set\n", __FUNCTION__));
+  for (index = 0; index < printTotalGen; ++index) {
+    for (setNumber = 0; setNumber < 4; ++setNumber) {
+      regVal = READ_WAVE_SET (IpuDiRegsPtr, index, setNumber);
+      DEBUG ((DEBUG_VERBOSE, "%a: DI0_DW_SET%d_%d 0x%08x\n",
+        __FUNCTION__, setNumber, index, regVal));
+    }
+  }
+
+  regVal = IpuRead32 (IpuMmioBasePtr, IPU_IPU_PM_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_IPU_PM_OFFSET %x\n",
+    __FUNCTION__, regVal));
+
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_BS_CLKGEN0_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_BS_CLKGEN0_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_BS_CLKGEN1_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_BS_CLKGEN1_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SCR_CONF_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SCR_CONF_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_1_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_1_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_1_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_1_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_2_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_2_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_2_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_2_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_3_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_3_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_3_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_3_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_4_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_4_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_4_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_4_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_5_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_5_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_5_OFFSET %x\n",
+    __FUNCTION__, regVal));
+
+  for (index = 0; index < 5; ++index) {
+    regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_STP_REP_OFFSET +  (index * 0x4));
+    DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_STP_%d_REP_OFFSET %x\n",
+      __FUNCTION__, index + 1, regVal));
+  }
+
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SYNC_AS_GEN_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SYNC_AS_GEN_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_GENERAL_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_GENERAL_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_POL_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_POL_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  regVal = DiRead32 (IpuDiRegsPtr, IPU_IPU_DISP_GEN_OFFSET);
+  DEBUG ((DEBUG_VERBOSE, "%a: IPU_IPU_DISP_GEN_OFFSET %x\n",
+    __FUNCTION__, regVal));
+  DEBUG ((DEBUG_VERBOSE, "%a: ------------------------------\n\n", __FUNCTION__));
+}
+#endif /* DEBUG */
+
+VOID
+ConfigureSyncWave (
+  IN  VOID          *IpuMmioBasePtr,
+  IN  IPU_DIx_REGS  *IpuDiRegsPtr,
+  IN  UINT32        CounterIndex,
+  IN  UINT32        RunValue,
+  IN  UINT32        RunResolution,
+  IN  UINT32        OffsetValue,
+  IN  UINT32        OffsetResolution,
+  IN  UINT32        CounterPolarityGenEn,
+  IN  UINT32        CounterAutoReload,
+  IN  UINT32        CounterClearSelect,
+  IN  UINT32        CounterDown,
+  IN  UINT32        CounterPolarityTriggerSelect,
+  IN  UINT32        CounterPolarityClearSelect,
+  IN  UINT32        CounterUp,
+  IN  UINT32        StepRepeat
+  )
+{
+  IPUx_DIx_SW_GEN0_x_REG  DiSwGen0Reg;
+  IPUx_DIx_SW_GEN1_x_REG  DiSwGen1Reg;
+  UINT32                  StepIndex;
+  IPUx_DIx_STP_REP_REG    StepRepeatReg;
+
+  ZeroMem ((VOID *)&DiSwGen0Reg, sizeof (DiSwGen0Reg));
+  DiSwGen0Reg.dix_offset_resolution = OffsetResolution;
+  DiSwGen0Reg.dix_offset_value = OffsetValue;
+  DiSwGen0Reg.dix_run_resolution = RunResolution;
+  DiSwGen0Reg.dix_run_value_m1 = RunValue;
+  DiWrite32 (
+    IpuDiRegsPtr,
+    IPU_DIx_SW_GEN0_1_OFFSET + ((CounterIndex - 1) * 0x04),
+    DiSwGen0Reg.Reg
+  );
+
+  ZeroMem ((VOID *)&DiSwGen1Reg, sizeof (DiSwGen1Reg));
+  DiSwGen1Reg.dix_cnt_up = CounterUp;
+  DiSwGen1Reg.dix_cnt_polarity_clr_sel = CounterPolarityClearSelect;
+  DiSwGen1Reg.dix_cnt_polarity_trigger_sel = CounterPolarityTriggerSelect;
+  DiSwGen1Reg.dix_cnt_down = CounterDown;
+  DiSwGen1Reg.dix_cnt_clr_sel = CounterClearSelect;
+  DiSwGen1Reg.dix_cnt_auto_reload = CounterAutoReload;
+  DiSwGen1Reg.dix_cnt_polarity_gen_en = CounterPolarityGenEn;
+  DiWrite32 (
+    IpuDiRegsPtr,
+    IPU_DIx_SW_GEN1_1_OFFSET + ((CounterIndex - 1) * 0x04),
+    DiSwGen1Reg.Reg
+  );
+
+  StepIndex = (CounterIndex - 1) / 2;
+  StepRepeatReg.Reg = IpuRead32 (
+                        IpuMmioBasePtr,
+                        IPU_DI0_STP_REP_OFFSET + (StepIndex * 0x4)
+                      );
+
+  if (CounterIndex % 2) {
+    StepRepeatReg.dix_step_repeat_2i_minus_1 = StepRepeat;
+  } else {
+    StepRepeatReg.dix_step_repeat_2i = StepRepeat;
+  }
+  IpuWrite32 (
+    IpuMmioBasePtr,
+    IPU_DI0_STP_REP_OFFSET + (StepIndex * 0x4),
+    StepRepeatReg.Reg
+  );
+}
+
+EFI_STATUS
+ConfigureDisplayInterface (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  UINT32                      DisplayIndex,
+  IN  DISPLAY_TIMING              *DisplayTimingPtr
+  )
+{
+  IPU_DIx_REGS              *pIpuDiRegs;
+  VOID                      *pIpuMmioBase;
+  UINT32                    BaseDiv;
+  UINT32                    DispGenReg;
+  UINT64                    DisplayInterfaceFrequency;
+  IPUx_DIx_DW_GEN_REG       DixDwGenReg;
+  IPUx_DIx_DW_SET_REG       DixDwSetReg;
+  IPUx_DIx_GENERAL_REG      DixGeneralReg;
+  IPUx_DIx_POL_REG          DixPolReg;
+  IPUx_DIx_SYNC_AS_GEN_REG  DixSyncAsGenReg;
+  UINT32                    HorizontalLength;
+  EFI_STATUS                Status;
+  UINT32                    VerticalLength;
+
+  DisplayInterfaceFrequency = DisplayTimingPtr->PixelClock;
+  HorizontalLength = DisplayTimingPtr->HActive + DisplayTimingPtr->HBlank;
+  VerticalLength = DisplayTimingPtr->VActive + DisplayTimingPtr->VBlank;
+  pIpuMmioBase = DisplayInterfaceContextPtr->IpuMmioBasePtr;
+  pIpuDiRegs = DisplayInterfaceContextPtr->IpuDiRegsPtr;
+  Status = EFI_SUCCESS;
+
+  Status = ImxSetPll5ReferenceRate (DisplayTimingPtr->PixelClock);
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to setup PLL5=%r\n", __FUNCTION__, Status));
+    goto Exit;
+  }
+
+  // Setup base timer (fundamental timer). The base timer should already
+  // setup to match the pixel clock frequency.
+  // Shift 4 as the bottom 4 bits are fractional
+  BaseDiv = (UINT32) ((DisplayInterfaceFrequency << 4) / DisplayTimingPtr->PixelClock);
+  DiWrite32 (pIpuDiRegs, IPU_DIx_BS_CLKGEN0_OFFSET, BaseDiv);
+
+  // Up is always set to 0. Down is half of the pixel clock period where
+  // the first bit is fraction
+  BaseDiv >>= 4;
+
+  DiWrite32 (pIpuDiRegs, IPU_DIx_BS_CLKGEN1_OFFSET, BaseDiv << 16);
+  // Calculate divisor, again this would usually be 1.
+  BaseDiv = (UINT32) (DisplayInterfaceFrequency / DisplayTimingPtr->PixelClock);
+
+  // Set up wave, there 12 wave quartet, for now default to the first.
+  // Each wave quartet has 4 set register
+  // Set 0 is just a blank signal where up and down is set to 0
+  ZeroMem ((VOID *)&DixDwSetReg, sizeof (DixDwSetReg));
+  DixDwSetReg.dix_data_cnt_upx_i = 0;
+  DixDwSetReg.dix_data_cnt_downx_i = 0;
+  WRITE_WAVE_SET (
+    pIpuDiRegs,
+    DwGen0,
+    DwSet0,
+    DixDwSetReg.Reg
+  );
+
+  // Set 3 is setup to match pixel clock
+  ZeroMem ((VOID *)&DixDwSetReg, sizeof (DixDwSetReg));
+  DixDwSetReg.dix_data_cnt_upx_i = 0;
+  DixDwSetReg.dix_data_cnt_downx_i = BaseDiv * 2;
+  WRITE_WAVE_SET (
+    pIpuDiRegs,
+    DwGen0,
+    DwSet3,
+    DixDwSetReg.Reg
+  );
+
+  // All pins blank signal except pin 15
+  ZeroMem ((VOID *)&DixDwGenReg, sizeof (DixDwGenReg));
+  DixDwGenReg.dix_pt_0_i = DwSet0;
+  DixDwGenReg.dix_pt_1_i = DwSet0;
+  DixDwGenReg.dix_pt_2_i = DwSet0;
+  DixDwGenReg.dix_pt_3_i = DwSet0;
+  DixDwGenReg.dix_pt_4_i = DwSet3;
+  DixDwGenReg.dix_pt_5_i = DwSet0;
+  DixDwGenReg.dix_pt_6_i = DwSet0;
+  DixDwGenReg.dix_cst_i = DwSet0;
+  // Reuse the base divisor to determine extra IPU cycles.
+  DixDwGenReg.dix_componnent_size_i = BaseDiv - 1;
+  DixDwGenReg.dix_access_size_i = BaseDiv - 1;
+  WRITE_WAVE_GEN (pIpuDiRegs, DwGen0, DixDwGenReg.Reg);
+
+  // Spec mention this as number of display rows but display only works
+  // properly if this is setup as vertical total
+  DiWrite32 (pIpuDiRegs, IPU_DIx_SCR_CONF_OFFSET, VerticalLength - 1);
+
+  // Internal HSYNC
+  ConfigureSyncWave (
+    pIpuMmioBase,
+    pIpuDiRegs,
+    DI_COUNTER_1_INTERNAL_HSYNC, // CounterIndex
+    HorizontalLength - 1,   // Runvalue
+    DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution
+    0,            // OffsetValue
+    0,            // OffsetResolution
+    0,            // CounterPolarityGenEn
+    1,            // CounterAutoReload
+    DI_COUNTER_DISABLED, // CounterClearSelect
+    0,            // CountDown
+    0,            // CounterPolarityTriggerSelect
+    0,            // CounterPolarityClearSelect
+    0,            // CounterUp
+    0             // StepRepeat
+  );
+
+  // Output HSYNC
+  ConfigureSyncWave (
+    pIpuMmioBase,
+    pIpuDiRegs,
+    DI_COUNTER_2_OUTPUT_HSYNC, // CounterIndex
+    HorizontalLength - 1,   // Runvalue
+    DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution
+    0,            // OffsetValue
+    DI_COUNTER_0_DISPLAY_CLOCK + 1, // OffsetResolution - Display clock
+    1,            // CounterPolarityGenEn
+    1,            // CounterAutoReload
+    DI_COUNTER_DISABLED, // CounterClearSelect
+    DisplayTimingPtr->HSync * 2,    // CountDown
+    1,            // CounterPolarityTriggerSelect
+    0,            // CounterPolarityClearSelect
+    0,            // CounterUp
+    0             // StepRepeat
+  );
+
+  // Output VSYNC
+  ConfigureSyncWave (
+    pIpuMmioBase,
+    pIpuDiRegs,
+    DI_COUNTER_3_OUTPUT_VSYNC, // CounterIndex
+    VerticalLength - 1,   // Runvalue
+    DI_COUNTER_1_INTERNAL_HSYNC + 1, // RunResolution - Counter 1
+    0,            // OffsetValue
+    0,            // OffsetResolution
+    1,            // CounterPolarityGenEn
+    1,            // CounterAutoReload
+    DI_COUNTER_DISABLED, // CounterClearSelect
+    DisplayTimingPtr->VSync * 2,    // CountDown
+    2,            // CounterPolarityTriggerSelect
+    0,            // CounterPolarityClearSelect
+    0,            // CounterUp
+    0             // StepRepeat
+  );
+
+  // Active lines
+  ConfigureSyncWave (
+    pIpuMmioBase,
+    pIpuDiRegs,
+    DI_COUNTER_4_ACTIVE_LINE,  // CounterIndex
+    0,            // Runvalue
+    DI_COUNTER_2_OUTPUT_HSYNC + 1, // RunResolution - Counter 2
+    DisplayTimingPtr->VSync + DisplayTimingPtr->VSyncOffset, // Offset
+    DI_COUNTER_2_OUTPUT_HSYNC + 1,// OffsetResolution - Counter 2
+    0,            // CounterPolarityGenEn
+    0,            // CounterAutoReload
+    DI_COUNTER_3_OUTPUT_VSYNC + 1, // CounterClearSelect - Counter 3
+    0,            // CountDown
+    0,            // CounterPolarityTriggerSelect
+    0,            // CounterPolarityClearSelect
+    0,            // CounterUp
+    DisplayTimingPtr->VActive // StepRepeat repeat for total VActive
+  );
+
+  // Active clock
+  ConfigureSyncWave (
+    pIpuMmioBase,
+    pIpuDiRegs,
+    DI_COUNTER_5_ACTIVE_CLOCK, // CounterIndex
+    0,            // Runvalue
+    DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution - Display clock
+    DisplayTimingPtr->HSync + DisplayTimingPtr->HSyncOffset, // Offset
+    DI_COUNTER_0_DISPLAY_CLOCK + 1, // OffsetResolution - Display clock
+    0,            // CounterPolarityGenEn
+    0,            // CounterAutoReload
+    DI_COUNTER_4_ACTIVE_LINE + 1, // CounterClearSelect - Counter 4
+    0,            // CountDown
+    0,            // CounterPolarityTriggerSelect
+    0,            // CounterPolarityClearSelect
+    0,            // CounterUp
+    DisplayTimingPtr->HActive // StepRepeat
+  );
+
+  ZeroMem ((VOID *)&DixSyncAsGenReg, sizeof (DixSyncAsGenReg));
+  // VSYNC is setup as counter 3 above, 0 index based
+  DixSyncAsGenReg.dix_vsync_sel = 3 - 1;
+  // Number of row DI prepares next frame data.
+  DixSyncAsGenReg.dix_sync_start = 2;
+  DiWrite32 (pIpuDiRegs, IPU_DIx_SYNC_AS_GEN_OFFSET, DixSyncAsGenReg.Reg);
+
+  // Setup general register
+  ZeroMem ((VOID *)&DixGeneralReg, sizeof (DixGeneralReg));
+  // Counter 1 as display line
+  DixGeneralReg.dix_disp_y_sel = DI_COUNTER_1_INTERNAL_HSYNC - 1;
+  // Stop at the next edge of the display clock
+  DixGeneralReg.DIx_CLOCK_STOP_MODE = 0;
+  // The display's clock is stopped after the next VSYNC
+  DixGeneralReg.DIx_DISP_CLOCK_INIT = 0;
+  // IPP_PIN_2 is coming from counter #2
+  DixGeneralReg.dix_mask_sel = 0;
+  // External clock - for not the video PLL
+  DixGeneralReg.dix_vsync_ext = 1;
+  // External clock - for not the video PLL
+  DixGeneralReg.dix_clk_ext = 1;
+  // 4 cycle watch dog based on BSP
+  DixGeneralReg.DIx_WATCHDOG_MODE = 0;
+  // default sync to counter 0
+  DixGeneralReg.dix_sync_count_sel = DI_COUNTER_1_INTERNAL_HSYNC - 1;
+  // In the event of error drive the last component
+  DixGeneralReg.dix_err_treatment = 0;
+  // An internal VSYNC signal asserted 2 lines before the DI's VSYNC
+  DixGeneralReg.dix_erm_vsync_sel = 0;
+
+  switch (DisplayInterfaceContextPtr->displayInterface) {
+  case HdmiDisplay:
+    // Zero for HDMI display
+    DixGeneralReg.dix_polarity_disp_clk = 0;
+    DixGeneralReg.dix_polarity_cs1 = 0;
+    DixGeneralReg.dix_polarity_cs0 = 0;
+    DixGeneralReg.dix_polarity_i_1 = 0;
+    break;
+  default:
+    Status = EFI_UNSUPPORTED;
+    DEBUG ((DEBUG_ERROR, "%a: Unsupported display interface %d\n",
+      __FUNCTION__, DisplayInterfaceContextPtr->displayInterface));
+    break;
+  }
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+  DiWrite32 (pIpuDiRegs, IPU_DIx_GENERAL_OFFSET, DixGeneralReg.Reg);
+
+  ZeroMem ((VOID *)&DixPolReg, sizeof (DixPolReg));
+  // CS0
+  DixPolReg.DIx_CS0_DATA_POLARITY = 1;
+  DixPolReg.dix_cs0_polarity = 0x7F;
+  // CS1
+  DixPolReg.DIx_CS1_DATA_POLARITY = 1;
+  DixPolReg.dix_cs1_polarity = 0x7F;
+  // DRDY
+  DixPolReg.DIx_DRDY_DATA_POLARITY = 0;
+  DixPolReg.dix_drdy_polarity = 0x7F;
+  // Wait
+  DixPolReg.DIx_WAIT_POLARITY = 0;
+  // CS0 byte enable polarity
+  DixPolReg.DIx_CS0_BYTE_EN_POLARITY = 0;
+  // CS1 byte enable polarity
+  DixPolReg.DIx_CS1_BYTE_EN_POLARITY = 0;
+  DiWrite32 (pIpuDiRegs, IPU_DIx_POL_OFFSET, DixPolReg.Reg);
+
+  DispGenReg = IpuRead32 (pIpuMmioBase, IPU_IPU_DISP_GEN_OFFSET);
+  DispGenReg &= ~(0x0F << 18);
+  DispGenReg |= (2 << 18);
+  IpuWrite32 (pIpuMmioBase, IPU_IPU_DISP_GEN_OFFSET, DispGenReg);
+
+#ifdef DEBUG
+  DumpBasicDisplayInterfaceReg (pIpuMmioBase, pIpuDiRegs);
+#endif /* DEBUG */
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
new file mode 100644
index 000000000000..786ef1fff5f0
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
@@ -0,0 +1,195 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _DISPLAY_INTERFACE_H_
+#define _DISPLAY_INTERFACE_H_
+
+#define READ_WAVE_GEN(IPU_BASE, GEN_INDEX) \
+    DiRead32(IPU_BASE, IPU_DIx_DW_GEN_OFFSET + (GEN_INDEX * 0x4))
+
+#define WRITE_WAVE_GEN(IPU_BASE, GEN_INDEX, VALUE) \
+    DiWrite32(IPU_BASE, IPU_DIx_DW_GEN_OFFSET + (GEN_INDEX * 0x4), VALUE)
+
+#define READ_WAVE_SET(IPU_BASE, GEN_INDEX, SET_NUMBER) \
+    DiRead32(IPU_BASE, IPU_DIx_DW_SET0_OFFSET + (SET_NUMBER * 0x30) + (GEN_INDEX * 0x4))
+
+#define WRITE_WAVE_SET(IPU_BASE, GEN_INDEX, SET_NUMBER, VALUE) \
+    DiWrite32(IPU_BASE, IPU_DIx_DW_SET0_OFFSET + (SET_NUMBER * 0x30) + (GEN_INDEX * 0x4), VALUE)
+
+#define DI_COUNTER_DISABLED 0
+#define DI_COUNTER_0_DISPLAY_CLOCK 0
+#define DI_COUNTER_1_INTERNAL_HSYNC 1
+#define DI_COUNTER_2_OUTPUT_HSYNC 2
+#define DI_COUNTER_3_OUTPUT_VSYNC 3
+#define DI_COUNTER_4_ACTIVE_LINE 4
+#define DI_COUNTER_5_ACTIVE_CLOCK 5
+
+typedef enum {
+  DwGen0,
+  DwGen1,
+  DwGen2,
+  DwGen3,
+  DwGen4,
+  DwGen5,
+  DwGen6,
+  DwGen7,
+  DwGen8,
+  DwGen9,
+  DwGen10,
+  DwGen11,
+  DwGenMax
+} DW_GEN;
+
+typedef enum {
+  DwSet0,
+  DwSet1,
+  DwSet2,
+  DwSet3,
+  DwSetMax
+} DW_SET;
+
+#pragma pack(push, 1)
+
+// IPUx_DIx_GENERAL
+typedef union {
+  struct {
+    UINT32 dix_polarity_i_1 : 8;
+    UINT32 dix_polarity_cs0 : 1;
+    UINT32 dix_polarity_cs1 : 1;
+    UINT32 dix_erm_vsync_sel : 1;
+    UINT32 dix_err_treatment : 1;
+    UINT32 dix_sync_count_sel : 4;
+    UINT32 Reserved : 1;
+    UINT32 dix_polarity_disp_clk : 1;
+    UINT32 DIx_WATCHDOG_MODE : 2;
+    UINT32 dix_clk_ext : 1;
+    UINT32 dix_vsync_ext : 1;
+    UINT32 dix_mask_sel : 1;
+    UINT32 DIx_DISP_CLOCK_INIT : 1;
+    UINT32 DIx_CLOCK_STOP_MODE : 4;
+    UINT32 dix_disp_y_sel : 3;
+    UINT32 dix_pin8_pin15_sel : 1;
+  };
+  UINT32 Reg;
+} IPUx_DIx_GENERAL_REG;
+
+// IPUx_DIx_SYNC_AS_GEN
+typedef union {
+  struct {
+    UINT32 dix_sync_start : 12;
+    UINT32 Reserved1 : 1;
+    UINT32 dix_vsync_sel : 3;
+    UINT32 Reserved2 : 12;
+    UINT32 di0_sync_start_en : 1;
+    UINT32 Reserved3 : 3;
+  };
+  UINT32 Reg;
+} IPUx_DIx_SYNC_AS_GEN_REG;
+
+// IPUx_DIx_DW_SET
+typedef union {
+  struct {
+    UINT32 dix_data_cnt_upx_i : 9;
+    UINT32 Reserved1 : 7;
+    UINT32 dix_data_cnt_downx_i : 9;
+    UINT32 Reserved2 : 7;
+  };
+  UINT32 Reg;
+} IPUx_DIx_DW_SET_REG;
+
+// IPUx_DIx_DW_GEN
+typedef union {
+  struct {
+    UINT32 dix_pt_0_i : 2;  // Pin 11
+    UINT32 dix_pt_1_i : 2;  // Pin 12
+    UINT32 dix_pt_2_i : 2;  // Pin 13
+    UINT32 dix_pt_3_i : 2;  // Pin 14
+    UINT32 dix_pt_4_i : 2;  // Pin 15
+    UINT32 dix_pt_5_i : 2;  // Pin 16
+    UINT32 dix_pt_6_i : 2;  // Pin 17
+    UINT32 dix_cst_i : 2;   // Chip Select
+    UINT32 dix_componnent_size_i : 8;
+    UINT32 dix_access_size_i : 8;
+  };
+  UINT32 Reg;
+} IPUx_DIx_DW_GEN_REG;
+
+
+// IPUx_DIx_SW_GEN0_x_REG
+typedef union {
+  struct {
+    UINT32 dix_offset_resolution : 3;
+    UINT32 dix_offset_value : 12;
+    UINT32 Reserved1: 1;
+    UINT32 dix_run_resolution : 3;
+    UINT32 dix_run_value_m1 : 12;
+    UINT32 Reserved2 : 1;
+  };
+  UINT32 Reg;
+} IPUx_DIx_SW_GEN0_x_REG;
+
+// IPUx_DIx_SW_GEN1_x_REG
+typedef union {
+  struct {
+    UINT32 dix_cnt_up : 9;
+    UINT32 dix_cnt_polarity_clr_sel : 3;
+    UINT32 dix_cnt_polarity_trigger_sel : 3;
+    UINT32 Reserved1 : 1;
+    UINT32 dix_cnt_down: 9;
+    UINT32 dix_cnt_clr_sel : 3;
+    UINT32 dix_cnt_auto_reload : 1;
+    UINT32 dix_cnt_polarity_gen_en : 2;
+    UINT32 Reserved2 : 1;
+  };
+  UINT32 Reg;
+} IPUx_DIx_SW_GEN1_x_REG;
+
+// IPUx_DIx_STP_REP
+typedef union {
+  struct {
+    UINT32 dix_step_repeat_2i_minus_1 : 12;
+    UINT32 Reserved1 : 4;
+    UINT32 dix_step_repeat_2i : 12;
+    UINT32 Reserved2 : 4;
+  };
+  UINT32 Reg;
+} IPUx_DIx_STP_REP_REG;
+
+// IPUx_DIx_POL
+typedef union {
+  struct {
+    UINT32 dix_drdy_polarity : 7;
+    UINT32 DIx_DRDY_DATA_POLARITY : 1;
+    UINT32 dix_cs0_polarity : 7;
+    UINT32 DIx_CS0_DATA_POLARITY : 1;
+    UINT32 dix_cs1_polarity : 7;
+    UINT32 DIx_CS1_DATA_POLARITY : 1;
+    UINT32 DIx_CS0_BYTE_EN_POLARITY : 1;
+    UINT32 DIx_CS1_BYTE_EN_POLARITY : 1;
+    UINT32 DIx_WAIT_POLARITY : 1;
+    UINT32 Reserved : 5;
+  };
+  UINT32 Reg;
+} IPUx_DIx_POL_REG;
+
+#pragma pack(pop)
+
+EFI_STATUS
+ConfigureDisplayInterface (
+  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
+  IN  UINT32                      DisplayIndex,
+  IN  DISPLAY_TIMING              *DisplayTimingPtr
+  );
+
+#endif  /* _DISPLAY_INTERFACE_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
new file mode 100644
index 000000000000..cc6557a58138
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
@@ -0,0 +1,96 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "Edid.h"
+#include "Ddc.h"
+
+EFI_STATUS
+ReadEdid (
+  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
+  IN  UINT8               *EdidDataPtr,
+  OUT UINT32              *EdidDataSizePtr
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = Imx6DdcRead (
+             DisplayContextPtr,
+             DisplayInterface,
+             EDID_I2C_ADDRESS,
+             0,
+             EDID_MIN_SIZE,
+             EdidDataPtr
+           );
+  if (Status != EFI_SUCCESS) {
+    goto Exit;
+  }
+
+  Status = ValidateEdidData (
+             EdidDataPtr
+           );
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_WARN, "%a: Invalid EDID data\n", __FUNCTION__));
+    goto Exit;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: EDID initialized\n", __FUNCTION__));
+
+  *EdidDataSizePtr = EDID_MIN_SIZE;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+GetEdidPreferredTiming (
+  IN  UINT8           *EdidDataPtr,
+  IN  UINT32          EdidDataSizePtr,
+  OUT DISPLAY_TIMING  *PreferredTiming
+  )
+{
+  DETAILED_TIMING_DESCRIPTOR  *pEdidPreferredTiming;
+  EFI_STATUS                  Status;
+
+  if (EdidDataSizePtr < EDID_MIN_SIZE) {
+    DEBUG ((DEBUG_WARN, "%a: Insufficient EDID data\n", __FUNCTION__));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  pEdidPreferredTiming = (DETAILED_TIMING_DESCRIPTOR *)&EdidDataPtr[EDID_DTD_1_OFFSET];
+  Status = ConvertDTDToDisplayTiming (pEdidPreferredTiming, PreferredTiming);
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: Conversion to display timing failed\n",
+      __FUNCTION__));
+    goto Exit;
+  }
+
+Exit:
+
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
new file mode 100644
index 000000000000..df714f284deb
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
@@ -0,0 +1,33 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _EDID_H_
+#define _EDID_H_
+
+EFI_STATUS
+ReadEdid (
+  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
+  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
+  IN  UINT8               *EdidDataPtr,
+  OUT UINT32              *EdidDataSizePtr
+  );
+
+EFI_STATUS
+GetEdidPreferredTiming (
+  IN  UINT8           *EdidDataPtr,
+  IN  UINT32          EdidDataSizePtr,
+  OUT DISPLAY_TIMING  *PreferredTiming
+  );
+
+#endif  /* _EDID_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
new file mode 100644
index 000000000000..2e990a6b14fb
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
@@ -0,0 +1,475 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EdidDiscovered.h>
+#include <Protocol/EdidActive.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "GopDxe.h"
+#include "Hdmi.h"
+#include "Lvds.h"
+
+#define PIXEL_BYTES 4
+
+typedef struct {
+  VENDOR_DEVICE_PATH Mmc;
+  EFI_DEVICE_PATH End;
+} VID_DEVICE_PATH;
+
+DISPLAY_TIMING CONST FullHDTiming = {
+  148500000,  // Full 1080p HD PixelClock
+  1920,       // HActive
+  280,        // HBlank
+  1080,       // VActive
+  45,         // VBlank
+  44,         // HSync
+  5,          // VSync
+  88,         // HSyncOffset;
+  4,          // VSyncOffset;
+  1920,       // HImageSize
+  1080,       // VImageSize
+  0,          // HBorder
+  0,          // VBorder
+  30,         // EdidFlags
+  0,          // Flags
+  1,          // PixelRepetition
+  32,         // Bpp
+  PIXEL_FORMAT_BGRA32,       // PixelFormat
+};
+
+EFI_STATUS
+EFIAPI
+VidGopQueryMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL           *This,
+  IN UINT32                                 ModeNumber,
+  OUT UINTN                                 *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
+  );
+
+EFI_STATUS
+VidGopSetMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
+  IN UINT32                         ModeNumber
+  );
+
+EFI_STATUS
+VidGopBlt (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer,
+  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
+  IN UINTN                              SourceX,
+  IN UINTN                              SourceY,
+  IN UINTN                              DestinationX,
+  IN UINTN                              DestinationY,
+  IN UINTN                              Width,
+  IN UINTN                              Height,
+  IN UINTN                              Delta
+  );
+
+STATIC VID_DEVICE_PATH VidDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8)sizeof (VENDOR_DEVICE_PATH),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8),
+      }
+    },
+    {
+      0xa6b94ebe,
+      0x5ba3,
+      0x44b0,
+      { 0x95, 0x92, 0xdc, 0x04, 0x5e, 0xb8, 0xf8, 0x9e }
+    }
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      sizeof (EFI_DEVICE_PATH_PROTOCOL),
+      0
+    }
+  }
+};
+
+STATIC EFI_GRAPHICS_OUTPUT_MODE_INFORMATION VidGopModeInfo;
+STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE VidGopMode;
+
+STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL VidGop = {
+  VidGopQueryMode, // QueryMode
+  VidGopSetMode,   // SetMode
+  VidGopBlt,       // Blt
+  &VidGopMode    // Mode
+};
+
+EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered = {
+  0,
+  NULL
+};
+
+EFI_EDID_ACTIVE_PROTOCOL EdidActive = {
+  0,
+  NULL
+};
+
+DISPLAY_CONTEXT *DisplayContextPtr;
+
+DISPLAY_INTERFACE_TYPE DisplayDevice;
+
+EFI_STATUS
+GopDxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  DISPLAY_INTERFACE_TYPE  DisplayInterfaceOrder[DisplayTypeMax];
+  UINT32                  i;
+  UINT32                  RequestedDisplayMemorySize;
+  UINT32                  ReservedDisplayMemorySize;
+  EFI_STATUS              Status;
+
+  DEBUG ((DEBUG_INFO, "%a: Enter \n", __FUNCTION__));
+
+  for (i = 0; i < DisplayTypeMax; i++) {
+    DisplayInterfaceOrder[i] = NoDisplayType;
+  }
+  ReservedDisplayMemorySize = FixedPcdGet32 (PcdFrameBufferSize);
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    DisplayDevice = Lvds0Display;
+  } else {
+    DisplayDevice = HdmiDisplay;
+  }
+
+  Status = InitDisplay (&DisplayContextPtr);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Fail to init display, Status=%r\n", __FUNCTION__,
+      Status));
+    goto Exit;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: - Allocate frame buffer\n", __FUNCTION__));
+  // To allocate frame buffer dynamically, there isn`t a built in graphic memory
+  // manager for UEFI, so we are allocating frame buffer manually. Currently only
+  // support single display, so allocate single(1) frame buffer
+  // Allocate frame buffer
+  DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width =
+    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.HActive;
+  DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height =
+    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.VActive;
+  DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp =
+    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.Bpp;
+  DisplayContextPtr->DisplayConfig.DisplaySurface[0].PixelFormat =
+    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.PixelFormat;
+
+  // iMX6 UEFI reserves display memory for fullHD buffer size.
+  // PcdFrameBufferSize=800000h or 8388608 bytes - 1920x1080x4 bytes
+  // to prevent larger displays overrun our reserved memory size,
+  // cap display resolution to fullHD
+  // NOTE: Displays which do not have support for 1920x1080 mode may
+  // have poor or missing picture
+  RequestedDisplayMemorySize =
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width *
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height *
+    (DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp / 8);
+
+  DEBUG ((DEBUG_INFO, "%a: Display Memory: Needed=%d, Available=%d\n",
+    __FUNCTION__, RequestedDisplayMemorySize, ReservedDisplayMemorySize));
+
+  if (RequestedDisplayMemorySize > ReservedDisplayMemorySize) {
+    DEBUG ((DEBUG_INFO,
+      "%a: WARNING. Need more video memory than reserved by %d bytes\n",
+      __FUNCTION__, RequestedDisplayMemorySize - ReservedDisplayMemorySize));
+    DEBUG ((DEBUG_ERROR,
+      "%a: - display resolution too big. Cap to HD 1080p\n",
+      __FUNCTION__));
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width = FullHDTiming.HActive;
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height =
+      FullHDTiming.VActive;
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp = FullHDTiming.Bpp;
+    CopyMem (
+      &DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming,
+      &FullHDTiming,
+      sizeof (DISPLAY_TIMING)
+    );
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: - allocating frame buffer... \n",
+    __FUNCTION__));
+  Status = AllocateFrameBuffer (&DisplayContextPtr->DisplayConfig.DisplaySurface[0]);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate fb, Status=%r\n",
+      __FUNCTION__, Status));
+    goto Exit;
+  };
+
+  DEBUG ((DEBUG_INFO, "%a: - Initialize the frame buffer to black\n",
+    __FUNCTION__));
+  // Initialize the frame buffer to black
+  SetMem32 (
+    (VOID *)DisplayContextPtr->DisplayConfig.DisplaySurface[0].PhyAddr,
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width *
+    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height * 4,
+    0xFF000000
+  );
+
+  DEBUG ((DEBUG_INFO, "%a: - set display configuration to single HDMI\n",
+    __FUNCTION__));
+  // Set the display configuration to single HDMI/LVDS mode
+  DisplayInterfaceOrder[0] = DisplayDevice;
+  DisplayContextPtr->DisplayConfig.DisplayTiming[0] =
+    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming;
+
+  Status = ApplyDisplayConfig (
+              DisplayContextPtr,
+              SINGLE_MODE,
+              DisplayInterfaceOrder
+            );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to set display. Exit Status=%r\n",
+      __FUNCTION__, Status));
+    goto Exit;
+  }
+
+  VidGopModeInfo.Version = 0;
+  VidGopModeInfo.HorizontalResolution =
+    DisplayContextPtr->DisplayConfig.DisplayTiming[0].HActive;
+  VidGopModeInfo.VerticalResolution =
+    DisplayContextPtr->DisplayConfig.DisplayTiming[0].VActive;
+  VidGopModeInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+  ZeroMem (
+    &VidGopModeInfo.PixelInformation,
+    sizeof (VidGopModeInfo.PixelInformation)
+  );
+
+  VidGopModeInfo.PixelsPerScanLine = VidGopModeInfo.HorizontalResolution;
+  VidGopMode.MaxMode = 1;
+  VidGopMode.Mode = 0;
+  VidGopMode.Info = &VidGopModeInfo;
+  VidGopMode.SizeOfInfo = sizeof (VidGopModeInfo);
+  VidGopMode.FrameBufferBase =
+    (EFI_PHYSICAL_ADDRESS) DisplayContextPtr->DisplayConfig.DisplaySurface[0].PhyAddr;
+  VidGopMode.FrameBufferSize =
+    VidGopModeInfo.HorizontalResolution *
+    VidGopModeInfo.VerticalResolution *
+    (DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp / 8);
+  DisplayContextPtr->DisplayConfig.OsHandle[0] = (UINT32)&ImageHandle;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  &VidGop,
+                  &gEfiDevicePathProtocolGuid,
+                  &VidDevicePath,
+                  NULL
+                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to install protocol, Status=%x\n",
+      __FUNCTION__, Status));
+    goto Exit;
+  }
+
+Exit:
+  DEBUG ((DEBUG_INFO, "%a: Exit = %Xh\n",
+    __FUNCTION__, Status));
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+VidGopQueryMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+  IN  UINT32 ModeNumber,
+  OUT UINTN *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+  )
+{
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *OutputMode;
+  EFI_STATUS                            Status;
+
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    DisplayDevice = Lvds0Display;
+  } else {
+    DisplayDevice = HdmiDisplay;
+  }
+
+  EdidDiscovered.SizeOfEdid = DisplayContextPtr->DiContext[DisplayDevice].EdidDataSize;
+  EdidDiscovered.Edid = DisplayContextPtr->DiContext[DisplayDevice].EdidData;
+  EdidActive.SizeOfEdid = DisplayContextPtr->DiContext[DisplayDevice].EdidDataSize;
+  EdidActive.Edid = DisplayContextPtr->DiContext[DisplayDevice].EdidData;
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  (EFI_HANDLE)DisplayContextPtr->DisplayConfig.OsHandle[0],
+                  &gEfiEdidDiscoveredProtocolGuid,
+                  &EdidDiscovered,
+                  &gEfiEdidActiveProtocolGuid,
+                  &EdidActive,
+                  NULL
+                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to install EDID protocols Status=%r\n",
+      __FUNCTION__, Status));
+  }
+
+  if (ModeNumber != 0) {
+    DEBUG ((DEBUG_ERROR, "%a: Saw request to query mode %d\n",
+      __FUNCTION__, ModeNumber));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  OutputMode = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)
+    AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+  if (OutputMode == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  OutputMode->Version = 0;
+  OutputMode->HorizontalResolution = VidGopModeInfo.HorizontalResolution;
+  OutputMode->VerticalResolution = VidGopModeInfo.VerticalResolution;
+  OutputMode->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+  OutputMode->PixelsPerScanLine = VidGopModeInfo.HorizontalResolution;
+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+  *Info = OutputMode;
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+VidGopSetMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
+  IN UINT32                         ModeNumber
+  )
+{
+  EFI_STATUS  Status;
+
+  if (ModeNumber != 0) {
+    DEBUG ((DEBUG_ERROR, "%a: Saw request to set mode to %d\n",
+      __FUNCTION__, ModeNumber));
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+VidGopBlt (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer, OPTIONAL
+  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
+  IN UINTN                              SourceX,
+  IN UINTN                              SourceY,
+  IN UINTN                              DestinationX,
+  IN UINTN                              DestinationY,
+  IN UINTN                              Width,
+  IN UINTN                              Height,
+  IN UINTN                              Delta OPTIONAL
+  )
+{
+  UINT32  *FrameBuffer;
+  UINT32  BufferOffset;
+  UINT32  BufferWidth;
+  UINT32  FrameOffset;
+  UINT32  FrameWidth;
+  UINT32  i;
+
+  FrameBuffer = (UINT32 *)((UINTN)VidGopMode.FrameBufferBase);
+  FrameWidth = VidGopModeInfo.HorizontalResolution;
+  if (Delta == 0) {
+    BufferWidth = Width;
+  } else {
+    BufferWidth = Delta / PIXEL_BYTES;
+  }
+
+  if (BltOperation == EfiBltVideoFill) {
+    FrameOffset = FrameWidth * DestinationY + DestinationX;
+    for (i = DestinationY; i < DestinationY + Height; i++) {
+      SetMem32 (
+        FrameBuffer + FrameOffset,
+        Width * PIXEL_BYTES,
+        *(UINT32 *)BltBuffer
+      );
+      FrameOffset += FrameWidth;
+    }
+  } else if (BltOperation == EfiBltVideoToBltBuffer) {
+    FrameOffset = FrameWidth * SourceY + SourceX;
+    BufferOffset = BufferWidth * DestinationY + DestinationX;
+    for (i = SourceY; i < SourceY + Height; i++) {
+      CopyMem (
+        BltBuffer + BufferOffset,
+        FrameBuffer + FrameOffset,
+        Width * PIXEL_BYTES
+      );
+      FrameOffset += FrameWidth;
+      BufferOffset += BufferWidth;
+    }
+  } else if (BltOperation == EfiBltBufferToVideo) {
+    FrameOffset = FrameWidth * DestinationY + DestinationX;
+    BufferOffset = BufferWidth * SourceY + SourceX;
+    for (i = SourceY; i < SourceY + Height; i++) {
+      CopyMem (
+        FrameBuffer + FrameOffset,
+        BltBuffer + BufferOffset,
+        Width * PIXEL_BYTES
+      );
+      FrameOffset += FrameWidth;
+      BufferOffset += BufferWidth;
+    }
+  } else if (BltOperation == EfiBltVideoToVideo) {
+    FrameOffset = FrameWidth * DestinationY + DestinationX;
+    BufferOffset = FrameWidth * SourceY + SourceX;
+    for (i = SourceY; i < SourceY + Height; i++) {
+      CopyMem (
+        FrameBuffer + FrameOffset,
+        FrameBuffer + BufferOffset,
+        Width * PIXEL_BYTES
+      );
+      FrameOffset += FrameWidth;
+      BufferOffset += FrameWidth;
+    }
+  } else {
+    DEBUG ((DEBUG_ERROR, "%a: Not implemented %d\n",
+      __FUNCTION__, BltOperation));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
new file mode 100644
index 000000000000..b8622283238f
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
@@ -0,0 +1,20 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _GOP_DXE_H_
+#define _GOP_DXE_H_
+
+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
+
+#endif  /* _GOP_DXE_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
new file mode 100644
index 000000000000..9dbe00ae1ab1
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
@@ -0,0 +1,70 @@
+#/** @file
+#
+#  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = GopDxe
+  FILE_GUID                      = E68088EF-D1A4-4336-C1DB-4D3A204730A6
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = GopDxeInitialize
+
+[Sources.common]
+  CPMem.c
+  Ddc.c
+  Display.c
+  DisplayController.c
+  DisplayInterface.c
+  Edid.c
+  GopDxe.c
+  Hdmi.c
+  IoMux.c
+  Lvds.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  iMX6ClkPwrLib
+  iMXDisplayLib
+  IoLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Protocols]
+  gEfiDevicePathProtocolGuid                    # Produced
+  gEfiDevicePathToTextProtocolGuid
+  gEfiEdidActiveProtocolGuid                    # Produced
+  gEfiEdidDiscoveredProtocolGuid                # Produced
+  gEfiGraphicsOutputProtocolGuid                # Produced
+
+[Pcd]
+  giMX6TokenSpaceGuid.PcdFrameBufferBase
+  giMX6TokenSpaceGuid.PcdFrameBufferSize
+  giMX6TokenSpaceGuid.PcdLvdsEnable
+
+[Depex]
+  gEfiCpuArchProtocolGuid AND gEfiTimerArchProtocolGuid
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
new file mode 100644
index 000000000000..fa8fb3ed4aea
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
@@ -0,0 +1,761 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "GopDxe.h"
+#include "Hdmi.h"
+#include "Edid.h"
+
+PLL_MPLL_CONFIG PllMpllGenericConfigSetting[] = {
+  {  13500000, 2,  8, {{3, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  13500000, 2, 10, {{1, 4, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  13500000, 2, 12, {{2, 4, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, },
+  {  13500000, 2, 16, {{3, 1, 3, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
+  {  13500000, 4,  8, {{3, 1, 3, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
+  {  13500000, 4, 10, {{1, 5, 3, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
+  {  13500000, 4, 12, {{2, 5, 3, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 0, 0,}}, },
+  {  13500000, 4, 16, {{3, 2, 3, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, },
+  {  18000000, 3,  8, {{2, 1, 3, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
+  {  18000000, 3, 16, {{2, 2, 3, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, },
+  {  24175000, 1,  8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  24175000, 1, 10, {{1, 0, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  24175000, 1, 12, {{2, 0, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, },
+  {  24175000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  27000000, 1,  8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  27000000, 1, 10, {{1, 0, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  27000000, 1, 12, {{2, 0, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, },
+  {  27000000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 5, 4, 0,}}, {{1, 0, 0,}}, },
+  {  27000000, 2,  8, {{3, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  27000000, 2, 10, {{1, 1, 3, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
+  {  27000000, 2, 12, {{2, 1, 3, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 0, 0,}}, },
+  {  27000000, 2, 16, {{3, 1, 2, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
+  {  27000000, 4,  8, {{3, 1, 2, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
+  {  27000000, 4, 10, {{1, 2, 3, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, },
+  {  27000000, 4, 12, {{2, 2, 3, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 0, 0,}}, },
+  {  27000000, 4, 16, {{3, 2, 2, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 1, 0,}}, },
+  {  36000000, 1,  8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
+  {  36000000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  50350000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  50350000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  50350000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  50350000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  50350000, 2,  8, {{3, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  50350000, 2, 10, {{1, 1, 2, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
+  {  50350000, 2, 12, {{2, 1, 2, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 1, 0,}}, },
+  {  50350000, 2, 16, {{3, 1, 1, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 2, 0,}}, },
+  {  54000000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  54000000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  54000000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  54000000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  54000000, 2,  8, {{3, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  54000000, 2, 10, {{1, 1, 2, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
+  {  54000000, 2, 12, {{2, 1, 2, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 1, 0,}}, },
+  {  54000000, 2, 16, {{3, 1, 1, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 2, 0,}}, },
+  {  58400000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
+  {  58400000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  58400000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  58400000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  72000000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  72000000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  72000000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  72000000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  {  74250000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
+  {  74250000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{2, 2, 0,}}, },
+  {  74250000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  {  74250000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  { 108000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  { 108000000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  { 108000000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  { 108000000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
+  { 118800000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  { 118800000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
+  { 118800000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  { 118800000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
+  { 144000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  { 144000000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, },
+  { 144000000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
+  { 144000000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{3, 3, 0,}}, },
+  { 148500000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  { 148500000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, },
+  { 148500000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
+  { 148500000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{3, 3, 0,}}, },
+  { 216000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+  { 216000000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, },
+  { 216000000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
+  // Fallback
+  {  65000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
+};
+
+BOOLEAN
+HdmiPhyPollI2cDone (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  UINT32                      Timeout
+  )
+{
+  HDMI_IH_I2CMPHY_STAT0_REG   I2cmphyStat0Reg;
+  BOOLEAN                     WaitResult;
+
+  WaitResult = FALSE;
+  for (; Timeout > 0; Timeout--) {
+    I2cmphyStat0Reg.Reg = MmioRead8 (
+                            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                            HDMI_IH_I2CMPHY_STAT0
+                          );
+    if (I2cmphyStat0Reg.i2cmphydone) {
+      WaitResult = TRUE;
+      break;
+    }
+    gBS->Stall (1);
+  }
+
+#if DEBUG
+  if ((Timeout == 0) || (I2cmphyStat0Reg.i2cmphyerror == 1)) {
+    DEBUG ((DEBUG_ERROR, "%a: HDMI I2C failed value %x time out %d\n",
+      __FUNCTION__, I2cmphyStat0Reg.Reg, Timeout));
+  }
+#endif
+
+  return WaitResult;
+}
+
+BOOLEAN
+HdmiPhyI2cRead (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  UINT8                       Addr,
+  OUT UINT16                      *DataPtr
+  )
+{
+  UINT16                            Data0;
+  UINT16                            Data1;
+  HDMI_PHY_I2CM_OPERATION_ADDR_REG  I2cmOperationReg;
+  HDMI_IH_I2CMPHY_STAT0_REG         I2cmphyStat0Reg;
+  BOOLEAN                           ReadStatus;
+
+  I2cmphyStat0Reg.i2cmphyerror = 1;
+  I2cmphyStat0Reg.i2cmphydone = 1;
+  I2cmphyStat0Reg.reserved = 0;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CMPHY_STAT0,
+    I2cmphyStat0Reg.Reg
+  );
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_ADDRESS_ADDR,
+    Addr
+  );
+
+  I2cmOperationReg.Reg = MmioRead8 (
+                           (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                           HDMI_PHY_I2CM_OPERATION_ADDR
+                         );
+  I2cmOperationReg.read = 1;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_OPERATION_ADDR,
+    I2cmOperationReg.Reg
+  );
+
+  ReadStatus = HdmiPhyPollI2cDone (HdmiDisplayContextPtr, 1000);
+  if (!ReadStatus) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to read I2c HDMI Phy\n", __FUNCTION__));
+    goto Exit;
+  }
+
+  Data0 = MmioRead8 (
+            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+            HDMI_PHY_I2CM_DATAI_0_ADDR
+          );
+  Data1 = MmioRead8 (
+            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+            HDMI_PHY_I2CM_DATAI_1_ADDR
+          );
+  *DataPtr = Data0 | (Data1 <<  8);
+
+Exit:
+  return ReadStatus;
+}
+
+BOOLEAN
+HdmiPhyI2cWrite (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  UINT8                       Addr,
+  IN  UINT16                      Data
+  )
+{
+  UINT8                             Data0;
+  UINT8                             Data1;
+  HDMI_PHY_I2CM_OPERATION_ADDR_REG  I2cmOperationReg;
+  HDMI_IH_I2CMPHY_STAT0_REG         I2cmphyStat0Reg;
+
+  Data0 = (Data & 0x00FF);
+  Data1 = (Data >>  8);
+  I2cmphyStat0Reg.i2cmphyerror = 1;
+  I2cmphyStat0Reg.i2cmphydone = 1;
+  I2cmphyStat0Reg.reserved = 1;
+  I2cmOperationReg.read = 0;
+  I2cmOperationReg.reserved0 = 0;
+  I2cmOperationReg.write = 0;
+  I2cmOperationReg.reserved1 = 0;
+
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CMPHY_STAT0,
+    I2cmphyStat0Reg.Reg
+  );
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_ADDRESS_ADDR,
+    Addr
+  );
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_DATAO_0_ADDR,
+    Data0
+  );
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_DATAO_1_ADDR,
+    Data1
+  );
+
+  I2cmOperationReg.read = 0;
+  I2cmOperationReg.write = 1;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_OPERATION_ADDR,
+    I2cmOperationReg.Reg
+  );
+  return HdmiPhyPollI2cDone (HdmiDisplayContextPtr, 1000);
+}
+
+BOOLEAN
+GetGenericConfigSetting (
+  IN  DISPLAY_TIMING    *DisplayTimingPtr,
+  OUT PLL_MPLL_CONFIG   **ConfigGenericSettingPPtr
+  )
+{
+  UINT32    ColorDepth;
+  BOOLEAN   FoundConfig;
+  UINT32    SettingIndex;
+
+  FoundConfig = FALSE;
+  ColorDepth = GetColorDepth (DisplayTimingPtr->PixelFormat);
+
+  for (SettingIndex = 0;
+       SettingIndex < ARRAYSIZE (PllMpllGenericConfigSetting);
+       ++SettingIndex)
+  {
+    if ((DisplayTimingPtr->PixelClock ==
+         PllMpllGenericConfigSetting[SettingIndex].PixelClock) &&
+        (DisplayTimingPtr->PixelRepetition ==
+         PllMpllGenericConfigSetting[SettingIndex].PixelRepetition) &&
+        (ColorDepth == PllMpllGenericConfigSetting[SettingIndex].ColorDepth))
+    {
+      FoundConfig = TRUE;
+      *ConfigGenericSettingPPtr = &PllMpllGenericConfigSetting[SettingIndex];
+      break;
+    }
+  }
+
+  // Use the fallback value the last index if no configuration is found
+  if (FoundConfig == FALSE) {
+    *ConfigGenericSettingPPtr =
+      &PllMpllGenericConfigSetting[ARRAYSIZE (PllMpllGenericConfigSetting)];
+    FoundConfig = TRUE;
+  }
+
+  return FoundConfig;
+}
+
+EFI_STATUS
+InitHdmi (
+  IN  DISPLAY_CONTEXT   *DisplayContextPtr
+  )
+{
+  DISPLAY_INTERFACE_CONTEXT   *pHdmiDisplayContext;
+  EFI_STATUS                  Status;
+
+  pHdmiDisplayContext = &DisplayContextPtr->DiContext[HdmiDisplay];
+  Status = EFI_SUCCESS;
+  ZeroMem (pHdmiDisplayContext, sizeof (*pHdmiDisplayContext));
+
+  pHdmiDisplayContext->MmioBasePtr = (VOID *)HDMI_BASE;
+  if (pHdmiDisplayContext->MmioBasePtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to map HDMI register\n", __FUNCTION__));
+    goto Exit;
+  }
+
+  // Setup HDMI DDC muxing
+  MmioWrite32 ((UINT32)IOMUXC_SW_MUX_CTL_PAD_KEY_COL3, 0x00000012);
+  MmioWrite32 ((UINT32)IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3, 0x00000012);
+  MmioWrite32 ((UINT32)IOMUXC_HDMI_II2C_CLKIN_SELECT_INPUT, 0x00000001);
+  MmioWrite32 ((UINT32)IOMUXC_HDMI_II2C_DATAIN_SELECT_INPUT, 0x00000001);
+  SetHdmiPower (pHdmiDisplayContext, TRUE);
+
+  // Mask all HDMI PHY interrupt
+  MmioWrite8 (
+    (UINT32)pHdmiDisplayContext->MmioBasePtr + HDMI_PHY_MASK0,
+    0xFF
+  );
+
+  Status = ReadEdid (
+             DisplayContextPtr,
+             HdmiDisplay,
+             pHdmiDisplayContext->EdidData,
+             &pHdmiDisplayContext->EdidDataSize
+           );
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_WARN, "%a: Fail to read HDMI EDID data\n", __FUNCTION__));
+    Status = EFI_SUCCESS;
+  }
+
+  Status = GetPreferredTiming (
+             pHdmiDisplayContext->EdidData,
+             pHdmiDisplayContext->EdidDataSize,
+             &pHdmiDisplayContext->PreferredTiming
+           );
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to retrieve HDMI preferred timing\n",
+      __FUNCTION__));
+    goto Exit;
+  }
+
+  if ((pHdmiDisplayContext->PreferredTiming.HActive == 1920) &&
+      (pHdmiDisplayContext->PreferredTiming.VActive == 1080))
+  {
+    pHdmiDisplayContext->PreferredTiming.HBlank -= 6;
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+SetHdmiPower (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  BOOLEAN                     PowerState
+  )
+{
+  HDMI_PHY_CONF0_REG  CurrentHdmiPhyConf0Reg;
+
+  CurrentHdmiPhyConf0Reg.Reg = MmioRead8 (
+                                 (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                                 HDMI_PHY_CONF0
+                               );
+  if (PowerState) {
+    // Setup PHY
+    CurrentHdmiPhyConf0Reg.PDZ = 1;
+    CurrentHdmiPhyConf0Reg.ENTMDS = 1;
+    CurrentHdmiPhyConf0Reg.gen2_pddq = 1;
+    CurrentHdmiPhyConf0Reg.gen2_txpwron = 1;
+    CurrentHdmiPhyConf0Reg.seldataenpol = 1;
+    CurrentHdmiPhyConf0Reg.seldipif = 0;
+  } else {
+    // Just power down PHY for shutdown
+    CurrentHdmiPhyConf0Reg.PDZ = 0;
+  }
+
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0,
+    CurrentHdmiPhyConf0Reg.Reg
+  );
+  gBS->Stall (3);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetHdmiPhy (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  DISPLAY_TIMING              *Timings
+  )
+{
+  PLL_MPLL_CONFIG           *pPllMpllConfig;
+  HDMI_PHY_CONF0_REG        CurrentHdmiPhyConf0Reg;
+  HDMI_FC_AUDSCONF_REG      FcAudsconfReg;
+  HDMI_MC_HEACPHY_RST_REG   HeacphyRstReg;
+  HDMI_MC_CLKDIS_REG        McClkdisReg;
+  HDMI_MC_PHYRSTZ_REG       PhyRstzReg;
+  HDMI_PHY_STAT0_REG        PhyStat0Reg;
+  BOOLEAN                   PhyStatus;
+  UINT32                    RetryCount;
+  EFI_STATUS                Status;
+
+  // Disable Audio
+  FcAudsconfReg.Reg = MmioRead8 (
+                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                        HDMI_FC_AUDSCONF
+                      );
+  FcAudsconfReg.aud_packet_layout = 0;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_FC_AUDSCONF,
+    FcAudsconfReg.Reg
+  );
+
+  // Minimum PCLK period / frequency (pixel repetition) : 74 ns / 13.5 MHz
+  // Minimum PCLK period / frequency (no pixel repetition) : 39.7 ns / 24.175 MHz
+  if (Timings->PixelClock < 13500000) {
+    DEBUG ((DEBUG_ERROR, "%a: Unsupported pixel clock %d\n",
+      __FUNCTION__, Timings->PixelClock));
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  if (GetGenericConfigSetting (Timings, &pPllMpllConfig) == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: No compatible generic config found\n",
+      __FUNCTION__));
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  // Color Space Converter : Not used in UEFI
+  McClkdisReg.Reg = MmioRead8 (
+                      (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                      HDMI_MC_CLKDIS
+                    );
+  // Disable CEC, color converter, audio & pixel repitition
+  McClkdisReg.cecclk_disable = 1;
+  McClkdisReg.cscclk_disable = 1;
+  McClkdisReg.audclk_disable = 1;
+  McClkdisReg.prepclk_disable = 1;
+  McClkdisReg.hdcpclk_disable = 1;
+  McClkdisReg.tmdsclk_disable = 0;
+  McClkdisReg.pixelclk_disable = 0;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_CLKDIS,
+    McClkdisReg.Reg
+  );
+
+  // Power down the PHY
+  // To set the HDMI_PHY in Power-down mode, set the TX_PWRON signal to 1'b0
+  // and the PDDQ signal to 1'b1. To power up the HDMI 3D Tx PHY and place it
+  // in Active mode, set TX_PWRON to 1'b1 and PDDQ to 1'b0. Any configuration
+  // programmed on the HDMI_PHY must be done in Power-down mode.
+  CurrentHdmiPhyConf0Reg.Reg = MmioRead8 (
+                                 (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                                 HDMI_PHY_CONF0
+                               );
+  CurrentHdmiPhyConf0Reg.gen2_txpwron = 0;
+  CurrentHdmiPhyConf0Reg.gen2_pddq = 1;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0,
+    CurrentHdmiPhyConf0Reg.Reg
+  );
+
+  // Let's reset the PHY to a well defined state based on spec.
+  // The PHY_RESET signal is used to place the digital section of the IP in
+  // a well - defined state
+  PhyRstzReg.Reg = MmioRead8 (
+                     (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                     HDMI_MC_PHYRSTZ
+                   );
+  PhyRstzReg.phyrstz = 1;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_PHYRSTZ,
+    PhyRstzReg.Reg
+  );
+  PhyRstzReg.phyrstz = 0;
+  gBS->Stall (10);
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_PHYRSTZ,
+    PhyRstzReg.Reg
+  );
+
+  HeacphyRstReg.Reg = MmioRead8 (
+                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                        HDMI_MC_HEACPHY_RST
+                      );
+  HeacphyRstReg.heacphyrst = 1;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_HEACPHY_RST,
+    HeacphyRstReg.Reg
+  );
+
+  // Program clock
+  // PLL / MPLL Operation
+  // The PLL / MPLL can be configured in Coherent mode or NonCoherent mode (default).
+  //  In Coherent mode, the TMDS clock is the MPLL feedback clock, which is
+  //  coherent with the MPLL's high-speed output clock, because both clocks are
+  //  shaped by the MPLL response.
+  //  In NonCoherent mode, the TMDS clock is the MPLL reference clock, which is
+  //  not coherent with the MPLL's high-speed output clock.
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_CPCE_CTRL,
+                pPllMpllConfig->HdmiPhyCpceCtrl.Reg
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CPCE_CTRL %x\n",
+      __FUNCTION__, pPllMpllConfig->HdmiPhyCpceCtrl.Reg));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_CURRCTRL,
+                pPllMpllConfig->HdmiPhyCurrctrl.Reg
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CURRCTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  };
+
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_GMPCTRL,
+                pPllMpllConfig->HdmiPhyGmpctrl.Reg
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_GMPCTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Maintaining the order of phy register writes
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_PLLPHBYCTRL,
+                0x0000
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_PLLPHBYCTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Coherent mode
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_MSM_CTRL,
+                0x0006
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_MSM_CTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Resistance value 133.33 ohm
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_TXTERM,
+                0x0005
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_TXTERM\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Enable clock symbol
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_CKSYMTXCTRL,
+                0x8009
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CKSYMTXCTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_VLEVCTRL,
+                0x0210
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_VLEVCTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  // Enable override
+  PhyStatus = HdmiPhyI2cWrite (
+                HdmiDisplayContextPtr,
+                HDMI_PHY_CKCALCTRL,
+                0x8000
+              );
+  if (PhyStatus == FALSE) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CKCALCTRL\n",
+      __FUNCTION__));
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  CurrentHdmiPhyConf0Reg.gen2_txpwron = 1;
+  CurrentHdmiPhyConf0Reg.gen2_pddq = 0;
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0,
+    CurrentHdmiPhyConf0Reg.Reg
+  );
+
+  Status = EFI_DEVICE_ERROR;
+  for (RetryCount = 5; RetryCount > 0; RetryCount--) {
+    PhyStat0Reg.Reg = MmioRead8 (
+                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                        HDMI_PHY_STAT0
+                      );
+    if (!PhyStat0Reg.TX_PHY_LOCK) {
+      Status = EFI_SUCCESS;
+      break;
+    }
+    gBS->Stall (1000);
+  }
+
+  if (RetryCount == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: TX PHY remain unlock\n", __FUNCTION__));
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+SetHdmiDisplay (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  DISPLAY_TIMING              *Timings
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = SetHdmiPhy (HdmiDisplayContextPtr, Timings);
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: SetHdmiPhy failed\n", __FUNCTION__));
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+VOID
+SetDdcSpeed (
+  IN  DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr,
+  IN  DDC_MODE                  Mode
+  )
+{
+  MmioWrite8 ((UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_DIV, Mode);
+}
+
+EFI_STATUS
+HdmiDdcRead (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  UINT8                       SlaveAddress,
+  IN  UINT8                       RegisterAddress,
+  IN  UINT32                      ReadSize,
+  IN  DDC_MODE                    DDCMode,
+  IN  UINT8                       *DataReadPtr
+  )
+{
+  UINT8       *pCurrentDataRead;
+  UINT32      AddrCount;
+  UINT8       I2cmIntStatus;
+  UINT32      I2cRetryCount;
+  EFI_STATUS  Status;
+
+  pCurrentDataRead = DataReadPtr;
+  Status = EFI_SUCCESS;
+
+  // Setup EDID transaction and loop through all byte request
+  SetDdcSpeed (HdmiDisplayContextPtr, DDCMode);
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0,
+    I2C_MASTER_ERROR | I2C_MASTER_DONE
+  );
+  MmioWrite8 (
+    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_SLAVE,
+    SlaveAddress
+  );
+
+  for (AddrCount = 0; AddrCount < ReadSize; ++AddrCount) {
+    I2cRetryCount = 1000;
+
+    MmioWrite8 (
+      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_ADDRESS,
+      (UINT8) ( RegisterAddress + AddrCount)
+    );
+    MmioWrite8 (
+      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_SEGADDR,
+      0x00
+    );
+    MmioWrite8 (
+      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_OPERATION,
+      DDC_READ_OPERATION
+    );
+
+    // Poll for completion
+    I2cmIntStatus = MmioRead8 (
+                      (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                      HDMI_IH_I2CM_STAT0
+                    );
+    for (I2cRetryCount = 1000; I2cRetryCount > 0; I2cRetryCount--) {
+      I2cmIntStatus = MmioRead8 (
+                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                        HDMI_IH_I2CM_STAT0
+                      );
+      if (I2cmIntStatus != 0) {
+        break;
+      }
+    }
+
+    if (I2cRetryCount == 0) {
+      Status = EFI_DEVICE_ERROR;
+      DEBUG ((DEBUG_ERROR, "%a: Timeout waiting for interrupt 0x%02x\n",
+        __FUNCTION__, I2cmIntStatus));
+      goto Exit;
+    }
+
+    if ((I2cmIntStatus & I2C_MASTER_DONE) &&
+        !(I2cmIntStatus & I2C_MASTER_ERROR))
+    {
+      *pCurrentDataRead = MmioRead8 (
+                            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
+                            HDMI_I2CM_DATAI
+                          );
+      pCurrentDataRead++;
+      MmioWrite8 (
+        (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0,
+        I2C_MASTER_ERROR | I2C_MASTER_DONE
+      );
+    } else {
+      Status = EFI_DEVICE_ERROR;
+      DEBUG ((DEBUG_ERROR, "%a: Failed to read with DDC 0x%02x\n",
+        __FUNCTION__, I2cmIntStatus));
+      goto Exit;
+    }
+
+    MmioWrite8 (
+      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0,
+      I2C_MASTER_ERROR | I2C_MASTER_DONE
+    );
+  }
+
+Exit:
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
new file mode 100644
index 000000000000..e1b7372bc2e9
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
@@ -0,0 +1,529 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _HDMI_H_
+#define _HDMI_H_
+
+// HDMI Register Base Address
+#define HDMI_BASE 0x00120000
+
+// Interrupt Register Offset
+#define HDMI_IH_FC_STAT0                0x0100
+#define HDMI_IH_FC_STAT1                0x0101
+#define HDMI_IH_FC_STAT2                0x0102
+#define HDMI_IH_AS_STAT0                0x0103
+#define HDMI_IH_PHY_STAT0               0x0104
+#define HDMI_IH_I2CM_STAT0              0x0105
+#define HDMI_IH_CEC_STAT0               0x0106
+#define HDMI_IH_VP_STAT0                0x0107
+#define HDMI_IH_I2CMPHY_STAT0           0x0108
+#define HDMI_IH_AHBDMAAUD_STAT0         0x0180
+#define HDMI_IH_MUTE_FC_STAT1           0x0181
+#define HDMI_IH_MUTE_FC_STAT2           0x0182
+#define HDMI_IH_MUTE_AS_STAT0           0x0183
+#define HDMI_IH_MUTE_PHY_STAT0          0x0184
+#define HDMI_IH_MUTE_I2CM_STAT0         0x0185
+#define HDMI_IH_MUTE_CEC_STAT0          0x0186
+#define HDMI_IH_MUTE_VP_STAT0           0x0187
+#define HDMI_IH_MUTE_I2CMPHY_STAT0      0x0188
+#define HDMI_IH_MUTE_AHBDMAAUD_STAT0    0x0189
+#define HDMI_IH_MUTE                    0x01FF
+#define HDMI_FC_INVIDCONF               0x1000
+#define HDMI_FC_INHACTV0                0x1001
+#define HDMI_FC_INHACTV1                0x1002
+#define HDMI_FC_INHBLANK0               0x1003
+#define HDMI_FC_INHBLANK1               0x1004
+#define HDMI_FC_INVACTV0                0x1005
+#define HDMI_FC_INVACTV1                0x1006
+#define HDMI_FC_INVBLANK                0x1007
+#define HDMI_FC_HSYNCINDELAY0           0x1008
+#define HDMI_FC_HSYNCINDELAY1           0x1009
+#define HDMI_FC_HSYNCINWIDTH0           0x100A
+#define HDMI_FC_HSYNCINWIDTH1           0x100B
+#define HDMI_FC_VSYNCINDELAY            0x100C
+#define HDMI_FC_VSYNCINWIDTH            0x100D
+#define HDMI_FC_INFREQ0                 0x100E
+#define HDMI_FC_INFREQ1                 0x100F
+#define HDMI_FC_INFREQ2                 0x1010
+#define HDMI_FC_CTRLDUR                 0x1011
+#define HDMI_FC_EXCTRLDUR               0x1012
+#define HDMI_FC_EXCTRLSPAC              0x1013
+#define HDMI_FC_CH0PREAM                0x1014
+#define HDMI_FC_CH1PREAM                0x1015
+#define HDMI_FC_CH2PREAM                0x1016
+#define HDMI_FC_AVICONF3                0x1017
+#define HDMI_FC_GCP                     0x1018
+#define HDMI_FC_AVICONF0                0x1019
+#define HDMI_FC_AVICONF1                0x101A
+#define HDMI_FC_AVICONF2                0x101B
+#define HDMI_FC_AVIVID                  0x101C
+#define HDMI_FC_AVIETB0                 0x101D
+#define HDMI_FC_AVIETB1                 0x101E
+#define HDMI_FC_AVISBB0                 0x101F
+#define HDMI_FC_AVISBB1                 0x1020
+#define HDMI_FC_AVIELB0                 0x1021
+#define HDMI_FC_AVIELB1                 0x1022
+#define HDMI_FC_AVISRB0                 0x1023
+#define HDMI_FC_AVISRB1                 0x1024
+#define HDMI_FC_AUDICONF0               0x1025
+#define HDMI_FC_AUDICONF1               0x1026
+#define HDMI_FC_AUDICONF2               0x1027
+#define HDMI_FC_AUDICONF3               0x1028
+#define HDMI_FC_VSDIEEEID0              0x1029
+#define HDMI_FC_VSDSIZE                 0x102A
+#define HDMI_FC_VSDIEEEID1              0x1030
+#define HDMI_FC_VSDIEEEID2              0x1031
+#define HDMI_FC_VSDPAYLOAD0             0x1032
+#define HDMI_FC_VSDPAYLOAD1             0x1033
+#define HDMI_FC_VSDPAYLOAD2             0x1034
+#define HDMI_FC_VSDPAYLOAD3             0x1035
+#define HDMI_FC_VSDPAYLOAD4             0x1036
+#define HDMI_FC_VSDPAYLOAD5             0x1037
+#define HDMI_FC_VSDPAYLOAD6             0x1038
+#define HDMI_FC_VSDPAYLOAD7             0x1039
+#define HDMI_FC_VSDPAYLOAD8             0x103A
+#define HDMI_FC_VSDPAYLOAD9             0x103B
+#define HDMI_FC_VSDPAYLOAD10            0x103C
+#define HDMI_FC_VSDPAYLOAD11            0x103D
+#define HDMI_FC_VSDPAYLOAD12            0x103E
+#define HDMI_FC_VSDPAYLOAD13            0x103F
+#define HDMI_FC_VSDPAYLOAD14            0x1040
+#define HDMI_FC_VSDPAYLOAD15            0x1041
+#define HDMI_FC_VSDPAYLOAD16            0x1042
+#define HDMI_FC_VSDPAYLOAD17            0x1043
+#define HDMI_FC_VSDPAYLOAD18            0x1044
+#define HDMI_FC_VSDPAYLOAD19            0x1045
+#define HDMI_FC_VSDPAYLOAD20            0x1046
+#define HDMI_FC_VSDPAYLOAD21            0x1047
+#define HDMI_FC_VSDPAYLOAD22            0x1048
+#define HDMI_FC_VSDPAYLOAD23            0x1049
+#define HDMI_FC_SPDVENDORNAME0          0x104A
+#define HDMI_FC_SPDVENDORNAME1          0x104B
+#define HDMI_FC_SPDVENDORNAME2          0x104C
+#define HDMI_FC_SPDVENDORNAME3          0x104D
+#define HDMI_FC_SPDVENDORNAME4          0x104E
+#define HDMI_FC_SPDVENDORNAME5          0x104F
+#define HDMI_FC_SPDVENDORNAME6          0x1050
+#define HDMI_FC_SPDVENDORNAME7          0x1051
+#define HDMI_FC_SDPPRODUCTNAME0         0x1052
+#define HDMI_FC_SDPPRODUCTNAME1         0x1053
+#define HDMI_FC_SDPPRODUCTNAME2         0x1054
+#define HDMI_FC_SDPPRODUCTNAME3         0x1055
+#define HDMI_FC_SDPPRODUCTNAME4         0x1056
+#define HDMI_FC_SDPPRODUCTNAME5         0x1057
+#define HDMI_FC_SDPPRODUCTNAME6         0x1058
+#define HDMI_FC_SDPPRODUCTNAME7         0x1059
+#define HDMI_FC_SDPPRODUCTNAME8         0x105A
+#define HDMI_FC_SDPPRODUCTNAME9         0x105B
+#define HDMI_FC_SDPPRODUCTNAME10        0x105C
+#define HDMI_FC_SDPPRODUCTNAME11        0x105D
+#define HDMI_FC_SDPPRODUCTNAME12        0x105E
+#define HDMI_FC_SDPPRODUCTNAME13        0x105F
+#define HDMI_FC_SDPPRODUCTNAME14        0x1060
+#define HDMI_FC_SPDPRODUCTNAME15        0x1061
+#define HDMI_FC_SPDDEVICEINF            0x1062
+#define HDMI_FC_AUDSCONF                0x1063
+#define HDMI_FC_AUDSSTAT                0x1064
+#define HDMI_FC_AUDSV                   0x1065
+#define HDMI_FC_AUDSU                   0x1066
+#define HDMI_FC_AUDSCHNLS0              0x1067
+#define HDMI_FC_AUDSCHNLS1              0x1068
+#define HDMI_FC_AUDSCHNLS2              0x1069
+#define HDMI_FC_AUDSCHNLS3              0x106A
+#define HDMI_FC_AUDSCHNLS4              0x106B
+#define HDMI_FC_AUDSCHNLS5              0x106C
+#define HDMI_FC_AUDSCHNLS6              0x106D
+#define HDMI_FC_AUDSCHNLS7              0x106E
+#define HDMI_FC_AUDSCHNLS8              0x106F
+#define HDMI_FC_DATACH0FILL             0x1070
+#define HDMI_FC_DATACH1FILL             0x1071
+#define HDMI_FC_DATACH2FILL             0x1072
+#define HDMI_FC_CTRLQHIGH               0x1073
+#define HDMI_FC_CTRLQLOW                0x1074
+#define HDMI_FC_ACP0                    0x1075
+#define HDMI_FC_ACP28                   0x1076
+#define HDMI_FC_ACP27                   0x1077
+#define HDMI_FC_ACP26                   0x1078
+#define HDMI_FC_ACP25                   0x1079
+#define HDMI_FC_ACP24                   0x107A
+#define HDMI_FC_ACP23                   0x107B
+#define HDMI_FC_ACP22                   0x107C
+#define HDMI_FC_ACP21                   0x107D
+#define HDMI_FC_ACP20                   0x107E
+#define HDMI_FC_ACP19                   0x107F
+#define HDMI_FC_ACP18                   0x1080
+#define HDMI_FC_ACP17                   0x1081
+#define HDMI_FC_ACP16                   0x1082
+#define HDMI_FC_ACP15                   0x1083
+#define HDMI_FC_ACP14                   0x1084
+#define HDMI_FC_ACP13                   0x1085
+#define HDMI_FC_ACP12                   0x1086
+#define HDMI_FC_ACP11                   0x1087
+#define HDMI_FC_ACP10                   0x1088
+#define HDMI_FC_ACP9                    0x1089
+#define HDMI_FC_ACP8                    0x108A
+#define HDMI_FC_ACP7                    0x108B
+#define HDMI_FC_ACP6                    0x108C
+#define HDMI_FC_ACP5                    0x108D
+#define HDMI_FC_ACP4                    0x108E
+#define HDMI_FC_ACP3                    0x108F
+#define HDMI_FC_ACP2                    0x1090
+#define HDMI_FC_ACP1                    0x1091
+#define HDMI_FC_ISCR1_0                 0x1092
+#define HDMI_FC_ISCR1_16                0x1093
+#define HDMI_FC_ISCR1_15                0x1094
+#define HDMI_FC_ISCR1_14                0x1095
+#define HDMI_FC_ISCR1_13                0x1096
+#define HDMI_FC_ISCR1_12                0x1097
+#define HDMI_FC_ISCR1_11                0x1098
+#define HDMI_FC_ISCR1_10                0x1099
+#define HDMI_FC_ISCR1_9                 0x109A
+#define HDMI_FC_ISCR1_8                 0x109B
+#define HDMI_FC_ISCR1_7                 0x109C
+#define HDMI_FC_ISCR1_6                 0x109D
+#define HDMI_FC_ISCR1_5                 0x109E
+#define HDMI_FC_ISCR1_4                 0x109F
+#define HDMI_FC_ISCR1_3                 0x10A0
+#define HDMI_FC_ISCR1_2                 0x10A1
+#define HDMI_FC_ISCR1_1                 0x10A2
+#define HDMI_FC_ISCR2_15                0x10A3
+#define HDMI_FC_ISCR2_14                0x10A4
+#define HDMI_FC_ISCR2_13                0x10A5
+#define HDMI_FC_ISCR2_12                0x10A6
+#define HDMI_FC_ISCR2_11                0x10A7
+#define HDMI_FC_ISCR2_10                0x10A8
+#define HDMI_FC_ISCR2_9                 0x10A9
+#define HDMI_FC_ISCR2_8                 0x10AA
+#define HDMI_FC_ISCR2_7                 0x10AB
+#define HDMI_FC_ISCR2_6                 0x10AC
+#define HDMI_FC_ISCR2_5                 0x10AD
+#define HDMI_FC_ISCR2_4                 0x10AE
+#define HDMI_FC_ISCR2_3                 0x10AF
+#define HDMI_FC_ISCR2_2                 0x10B0
+#define HDMI_FC_ISCR2_1                 0x10B1
+#define HDMI_FC_ISCR2_0                 0x10B2
+#define HDMI_FC_DATAUTO0                0x10B3
+#define HDMI_FC_DATAUTO1                0x10B4
+#define HDMI_FC_DATAUTO2                0x10B5
+#define HDMI_FC_DATMAN                  0x10B6
+#define HDMI_FC_DATAUTO3                0x10B7
+#define HDMI_FC_RDRB0                   0x10B8
+#define HDMI_FC_RDRB1                   0x10B9
+#define HDMI_FC_RDRB2                   0x10BA
+#define HDMI_FC_RDRB3                   0x10BB
+#define HDMI_FC_RDRB4                   0x10BC
+#define HDMI_FC_RDRB5                   0x10BD
+#define HDMI_FC_RDRB6                   0x10BE
+#define HDMI_FC_RDRB7                   0x10BF
+#define HDMI_FC_STAT0                   0x10D0
+#define HDMI_FC_INT0                    0x10D1
+#define HDMI_FC_MASK0                   0x10D2
+#define HDMI_FC_POL0                    0x10D3
+#define HDMI_FC_STAT1                   0x10D4
+#define HDMI_FC_INT1                    0x10D5
+#define HDMI_FC_MASK1                   0x10D6
+#define HDMI_FC_POL1                    0x10D7
+#define HDMI_FC_STAT2                   0x10D8
+#define HDMI_FC_INT2                    0x10D9
+#define HDMI_FC_MASK2                   0x10DA
+#define HDMI_FC_POL2                    0x10DB
+#define HDMI_FC_PRCONF                  0x10E0
+
+// HDMI PHY Register Offset
+#define HDMI_PHY_CONF0                      0x3000
+#define HDMI_PHY_TST0                       0x3001
+#define HDMI_PHY_TST1                       0x3002
+#define HDMI_PHY_TST2                       0x3003
+#define HDMI_PHY_STAT0                      0x3004
+#define HDMI_PHY_INT0                       0x3005
+#define HDMI_PHY_MASK0                      0x3006
+#define HDMI_PHY_POL0                       0x3007
+#define HDMI_PHY_I2CM_SLAVE_ADDR            0x3020
+#define HDMI_PHY_I2CM_ADDRESS_ADDR          0x3021
+#define HDMI_PHY_I2CM_DATAO_1_ADDR          0x3022
+#define HDMI_PHY_I2CM_DATAO_0_ADDR          0x3023
+#define HDMI_PHY_I2CM_DATAI_1_ADDR          0x3024
+#define HDMI_PHY_I2CM_DATAI_0_ADDR          0x3025
+#define HDMI_PHY_I2CM_OPERATION_ADDR        0x3026
+#define HDMI_PHY_I2CM_INT_ADDR              0x3027
+#define HDMI_PHY_I2CM_CTLINT_ADDR           0x3028
+#define HDMI_PHY_I2CM_DIV_ADDR              0x3029
+#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR         0x302a
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR    0x302b
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR    0x302c
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR    0x302d
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR    0x302e
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR    0x302f
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR    0x3030
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR    0x3031
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR    0x3032
+
+// Main Controller Registers
+#define HDMI_MC_CLKDIS          0x4001
+#define HDMI_MC_SWRSTZ          0x4002
+#define HDMI_MC_OPCTRL          0x4003
+#define HDMI_MC_FLOWCTRL        0x4004
+#define HDMI_MC_PHYRSTZ         0x4005
+#define HDMI_MC_LOCKONCLOCK     0x4006
+#define HDMI_MC_HEACPHY_RST     0x4007
+
+// HDMI_PHY absolute address
+#define HDMI_PHY_PWRCTRL        0x00
+#define HDMI_PHY_SERDIVCTRL     0x01
+#define HDMI_PHY_SERCKCTRL      0x02
+#define HDMI_PHY_SERCKKILLCTRL  0x03
+#define HDMI_PHY_TXRESCTRL      0x04
+#define HDMI_PHY_CKCALCTRL      0x05
+#define HDMI_PHY_CPCE_CTRL      0x06
+#define HDMI_PHY_TXCLKMEASCTRL  0x07
+#define HDMI_PHY_TXMEASCTRL     0x08
+#define HDMI_PHY_CKSYMTXCTRL    0x09
+#define HDMI_PHY_CMPSEQCTRL     0x0A
+#define HDMI_PHY_CMPPWRCTRL     0x0B
+#define HDMI_PHY_CMPMODECTRL    0x0C
+#define HDMI_PHY_MEASCTRL       0x0D
+#define HDMI_PHY_VLEVCTRL       0x0E
+#define HDMI_PHY_D2ACTRL        0x0F
+#define HDMI_PHY_CURRCTRL       0x10
+#define HDMI_PHY_DRVANACTRL     0x11
+#define HDMI_PHY_PLLMEASCTRL    0x12
+#define HDMI_PHY_PLLPHBYCTRL    0x13
+#define HDMI_PHY_GRP_CTRL       0x14
+#define HDMI_PHY_GMPCTRL        0x15
+#define HDMI_PHY_MPLLMEASCTRL   0x16
+#define HDMI_PHY_MSM_CTRL       0x17
+#define HDMI_PHY_SCRPB_STATUS   0x18
+#define HDMI_PHY_TXTERM         0x19
+#define HDMI_PHY_PTRPT_ENBL     0x1A
+#define HDMI_PHY_PATTERNGEN     0x1B
+#define HDMI_PHY_SDCAP_MODE     0x1C
+#define HDMI_PHY_SCOPEMODE      0x1D
+#define HDMI_PHY_DIGTXMODE      0x1E
+#define HDMI_PHY_STR_STATUS     0x1F
+#define HDMI_PHY_SCOPECNT0      0x20
+#define HDMI_PHY_SCOPECNT1      0x21
+#define HDMI_PHY_SCOPECNT2      0x22
+#define HDMI_PHY_SCOPECNTCLK    0x23
+#define HDMI_PHY_SCOPESAMPLE    0x24
+#define HDMI_PHY_SCOPECNTMSB01  0x25
+#define HDMI_PHY_SCOPECNTMSB2CK 0x26
+
+// HDMI DDC offset
+#define HDMI_I2CM_SLAVE                 0x7E00
+#define HDMI_I2CM_ADDRESS               0x7E01
+#define HDMI_I2CM_DATAO                 0x7E02
+#define HDMI_I2CM_DATAI                 0x7E03
+#define HDMI_I2CM_OPERATION             0x7E04
+#define HDMI_I2CM_INT                   0x7E05
+#define HDMI_I2CM_CTLINT                0x7E06
+#define HDMI_I2CM_DIV                   0x7E07
+#define HDMI_I2CM_SEGADDR               0x7E08
+#define HDMI_I2CM_SOFTRSTZ              0x7E09
+#define HDMI_I2CM_SEGPTR                0x7E0A
+#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR    0x7E0B
+#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR    0x7E0C
+#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR    0x7E0D
+#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR    0x7E0E
+#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR    0x7E0F
+#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR    0x7E10
+#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR    0x7E11
+#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR    0x7E12
+
+// DDC Interrupt status
+#define I2C_MASTER_ERROR                0x01
+#define I2C_MASTER_DONE                 0x02
+
+// HDMI bit configuration
+typedef enum {
+  DDC_READ_OPERATION = 0x01,
+  DDC_READ_EXT_OPERATION = 0x02,
+  DDC_WRITE_OPERATION = 0x10,
+} DDC_OPERATION;
+
+typedef enum {
+  HDMI_DDC_STANDARD_MODE = 0x00,
+  HDMI_DDC_FAST_MODE = 0x04,
+} DDC_MODE;
+
+#pragma pack(push, 1)
+
+// HDMI_PHY_CONF0 0x0100
+typedef union {
+  struct {
+    UINT8 seldipif : 1;
+    UINT8 seldataenpol : 1;
+    UINT8 gen2_enhpdrxsense : 1;
+    UINT8 gen2_txpwron : 1;
+    UINT8 gen2_pddq : 1;
+    UINT8 sparectrl : 1;
+    UINT8 ENTMDS : 1;
+    UINT8 PDZ : 1;
+  };
+  UINT8 Reg;
+}  HDMI_PHY_CONF0_REG;
+
+// HDMI_IH_I2CMPHY_STAT0 0x0108
+typedef union {
+  struct {
+    UINT8 i2cmphyerror : 1;
+    UINT8 i2cmphydone : 1;
+    UINT8 reserved : 6;
+  };
+  UINT8 Reg;
+}  HDMI_IH_I2CMPHY_STAT0_REG;
+
+// HDMI_FC_AUDSCONF 0x01063
+typedef union {
+  struct {
+    UINT8 aud_packet_layout : 1;
+    UINT8 reserved : 4;
+    UINT8 aud_packet_sampfit : 4;
+  };
+  UINT8 Reg;
+}  HDMI_FC_AUDSCONF_REG;
+
+// HDMI_PHY_STAT0 0x3004
+typedef union {
+  struct {
+    UINT8 TX_PHY_LOCK : 1;
+    UINT8 HPD : 1;
+    UINT8 reserved : 2;
+    UINT8 RX_SENSE0 : 1;
+    UINT8 RX_SENSE1 : 1;
+    UINT8 RX_SENSE2 : 1;
+    UINT8 RX_SENSE3 : 1;
+  };
+  UINT8 Reg;
+}  HDMI_PHY_STAT0_REG;
+
+// HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
+typedef union {
+  struct {
+    UINT8 read : 1;
+    UINT8 reserved0 : 3;
+    UINT8 write : 1;
+    UINT8 reserved1 : 3;
+  };
+  UINT8 Reg;
+}  HDMI_PHY_I2CM_OPERATION_ADDR_REG;
+
+// HDMI_MC_CLKDIS 0x4001
+typedef union {
+  struct {
+    UINT8 pixelclk_disable : 1;
+    UINT8 tmdsclk_disable : 1;
+    UINT8 prepclk_disable : 1;
+    UINT8 audclk_disable : 1;
+    UINT8 cscclk_disable : 1;
+    UINT8 cecclk_disable : 1;
+    UINT8 hdcpclk_disable : 1;
+    UINT8 reserved : 1;
+  };
+  UINT8 Reg;
+} HDMI_MC_CLKDIS_REG;
+
+// HDMI_MC_PHYRSTZ 0x4005
+typedef union {
+  struct {
+    UINT8 phyrstz : 1;
+    UINT8 reserved : 7;
+  };
+  UINT8 Reg;
+}  HDMI_MC_PHYRSTZ_REG;
+
+// HDMI_MC_HEACPHY_RST 0x4007
+typedef union {
+  struct {
+    UINT8 heacphyrst : 1;
+    UINT8 reserved : 7;
+  };
+  UINT8 Reg;
+}  HDMI_MC_HEACPHY_RST_REG;
+
+// HDMI PHY : HDMI_PHY_CPCE_CTRL 0x06
+typedef union {
+  struct {
+    UINT16 clr_dpth : 2;
+    UINT16 pixel_rep : 3;
+    UINT16 pll_n_cntrl : 2;
+    UINT16 mpll_n_cntrl : 2;
+    UINT16 ck_edgerate : 2;
+    UINT16 tx_edgerate : 2;
+    UINT16 prep_div : 2;
+    UINT16 reserved : 1;
+  };
+  UINT16 Reg;
+}  HDMI_PHY_CPCE_CTRL_REG;
+
+// HDMI PHY : HDMI_PHY_CURRCTRL 0x10
+typedef union {
+  struct {
+    UINT16 pll_int_cntrl : 3;
+    UINT16 pll_prop_cntrl : 3;
+    UINT16 mpll_int_cntrl : 3;
+    UINT16 mpll_prop_cntrl : 3;
+    UINT16 reserved : 4;
+  };
+  UINT16 Reg;
+}  HDMI_PHY_CURRCTRL_REG;
+
+// HDMI PHY : HDMI_PHY_GMPCTRL 0x15
+typedef union {
+  struct {
+    UINT16 mpll_gmp_cntrl : 2;
+    UINT16 pll_gmp_cntrl : 2;
+    UINT16 reserved : 12;
+  };
+  UINT16 Reg;
+}  HDMI_PHY_GMPCTRL_REG;
+
+#pragma pack(pop)
+
+typedef struct _PLL_MPLL_CONFIG {
+  UINT32 PixelClock;
+  UINT8 PixelRepetition;
+  UINT8 ColorDepth;
+  HDMI_PHY_CPCE_CTRL_REG HdmiPhyCpceCtrl;
+  HDMI_PHY_CURRCTRL_REG HdmiPhyCurrctrl;
+  HDMI_PHY_GMPCTRL_REG HdmiPhyGmpctrl;
+} PLL_MPLL_CONFIG, *PPLL_MPLL_CONFIG;
+
+EFI_STATUS
+InitHdmi (
+  IN  DISPLAY_CONTEXT   *DisplayContextPtr
+  );
+
+EFI_STATUS
+SetHdmiPower (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  BOOLEAN                     PowerState
+  );
+
+EFI_STATUS
+SetHdmiDisplay (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  DISPLAY_TIMING              *Timings
+  );
+
+EFI_STATUS
+HdmiDdcRead (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  UINT8                       SlaveAddress,
+  IN  UINT8                       RegisterAddress,
+  IN  UINT32                      ReadSize,
+  IN  DDC_MODE                    DDCMode,
+  IN  UINT8                       *DataReadPtr
+  );
+
+#endif  /* _HDMI_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
new file mode 100644
index 000000000000..b82fbd2125f5
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
@@ -0,0 +1,88 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "IoMux.h"
+
+EFI_STATUS
+SetupDisplayMux (
+  IN  DISPLAY_CONTEXT   *DisplayContextPtr
+  )
+{
+  DISPLAY_INTERFACE_TYPE              *pDisplayInterfaceType;
+  volatile IMX_IOMUXC_GPR_REGISTERS   *pIomuxcGprReg;
+  UINT32                              DisplayInterfaceIndex;
+  DISPLAY_MODE                        DisplayMode;
+  UINT32                              Gpr3Reg;
+  UINT32                              SourceMask;
+  UINT32                              SourceValue;
+  EFI_STATUS                          Status;
+
+  pIomuxcGprReg = DisplayContextPtr->IoMuxMmioBasePtr;
+  DisplayMode = DisplayContextPtr->DisplayConfig.DisplayMode;
+  pDisplayInterfaceType = DisplayContextPtr->DisplayConfig.DiOrder;
+  Status = EFI_SUCCESS;
+
+  Gpr3Reg = MmioRead32 ((UINT32)&pIomuxcGprReg->GPR3);
+  Gpr3Reg &= ~(HDMI_MUX_CTL_MASK | MIPI_MUX_CTL_MASK |
+               LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
+  MmioWrite32 ((UINT32)&pIomuxcGprReg->GPR3, Gpr3Reg);
+
+  for (DisplayInterfaceIndex = 0; DisplayInterfaceIndex < (UINT32)DisplayMode; ++DisplayInterfaceIndex) {
+    Gpr3Reg = MmioRead32 ((UINT32)&pIomuxcGprReg->GPR3);
+    switch (pDisplayInterfaceType[DisplayInterfaceIndex]) {
+    case HdmiDisplay:
+      SourceMask = HDMI_MUX_CTL_MASK;
+      SourceValue = DisplayInterfaceIndex << HDMI_MUX_CTL_OFFSET;
+      break;
+    case MipiDisplay:
+      SourceMask = MIPI_MUX_CTL_MASK;
+      SourceValue = DisplayInterfaceIndex << MIPI_MUX_CTL_OFFSET;
+      break;
+    case Lvds0Display:
+      SourceMask = LVDS0_MUX_CTL_MASK;
+      SourceValue = DisplayInterfaceIndex << LVDS0_MUX_CTL_OFFSET;
+      break;
+    case Lvds1Display:
+      SourceMask = LVDS1_MUX_CTL_MASK;
+      SourceValue = DisplayInterfaceIndex << LVDS1_MUX_CTL_OFFSET;
+      break;
+    default:
+      Status = EFI_UNSUPPORTED;
+      break;
+    }
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    Gpr3Reg &= ~SourceMask;
+    Gpr3Reg |= SourceValue;
+    MmioWrite32 ((UINT32)&pIomuxcGprReg->GPR3, Gpr3Reg);
+  }
+
+  return Status;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
new file mode 100644
index 000000000000..4946ab293ae5
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
@@ -0,0 +1,32 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IO_MUX_H_
+#define _IO_MUX_H_
+
+#define HDMI_MUX_CTL_OFFSET         2
+#define HDMI_MUX_CTL_MASK           0x000C
+#define MIPI_MUX_CTL_OFFSET         4
+#define MIPI_MUX_CTL_MASK           0x0030
+#define LVDS0_MUX_CTL_OFFSET        6
+#define LVDS0_MUX_CTL_MASK          0x00C0
+#define LVDS1_MUX_CTL_OFFSET        8
+#define LVDS1_MUX_CTL_MASK          0x0300
+
+EFI_STATUS
+SetupDisplayMux (
+  IN  DISPLAY_CONTEXT   *DisplayContextPtr
+  );
+
+#endif  /* _IO_MUX_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
new file mode 100644
index 000000000000..00d20c881b67
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
@@ -0,0 +1,236 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IPU_H_
+#define _IPU_H_
+
+#define IPU1_BASE      0x02600000
+#define IPU2_BASE      0x02A00000
+
+#define IpuRead32(IPU_BASE, OFFSET) \
+            MmioRead32((UINT32)((UINT8 *)IPU_BASE + OFFSET))
+
+#define IpuWrite32(IPU_BASE, OFFSET, VALUE) \
+            MmioWrite32((UINT32)((UINT8 *)IPU_BASE + OFFSET), VALUE)
+
+#define DiRead32(DI_BASE, OFFSET) \
+            MmioRead32((UINT32)((UINT8 *)DI_BASE + OFFSET))
+
+#define DiWrite32(DI_BASE, OFFSET, VALUE) \
+            MmioWrite32((UINT32)((UINT8 *)DI_BASE + OFFSET), VALUE)
+
+// IPU Registers
+#define IPU_IPU_CONF_OFFSET                     0x00000000
+#define IPU_SISG_CTRL0_OFFSET                   0x00000004
+#define IPU_SISG_CTRL1_OFFSET                   0x00000008
+#define IPU_SISG_SET_OFFSET                     0x0000000C
+#define IPU_SISG_CLR_OFFSET                     0x00000024
+#define IPU_IPU_INT_CTRL_1_OFFSET               0x0000003C
+#define IPU_IPU_INT_CTRL_2_OFFSET               0x00000040
+#define IPU_IPU_INT_CTRL_3_OFFSET               0x00000044
+#define IPU_IPU_INT_CTRL_4_OFFSET               0x00000048
+#define IPU_IPU_INT_CTRL_5_OFFSET               0x0000004C
+#define IPU_IPU_INT_CTRL_6_OFFSET               0x00000050
+#define IPU_IPU_INT_CTRL_7_OFFSET               0x00000054
+#define IPU_IPU_INT_CTRL_8_OFFSET               0x00000058
+#define IPU_IPU_INT_CTRL_9_OFFSET               0x0000005C
+#define IPU_IPU_INT_CTRL_10_OFFSET              0x00000060
+#define IPU_IPU_INT_CTRL_11_OFFSET              0x00000064
+#define IPU_IPU_INT_CTRL_12_OFFSET              0x00000068
+#define IPU_IPU_INT_CTRL_13_OFFSET              0x0000006C
+#define IPU_IPU_INT_CTRL_14_OFFSET              0x00000070
+#define IPU_IPU_INT_CTRL_15_OFFSET              0x00000074
+#define IPU_IPU_SDMA_EVENT_1_OFFSET             0x00000078
+#define IPU_IPU_SDMA_EVENT_2_OFFSET             0x0000007C
+#define IPU_IPU_SDMA_EVENT_3_OFFSET             0x00000080
+#define IPU_IPU_SDMA_EVENT_4_OFFSET             0x00000084
+#define IPU_IPU_SDMA_EVENT_7_OFFSET             0x00000088
+#define IPU_IPU_SDMA_EVENT_8_OFFSET             0x0000008C
+#define IPU_IPU_SDMA_EVENT_11_OFFSET            0x00000090
+#define IPU_IPU_SDMA_EVENT_12_OFFSET            0x00000094
+#define IPU_IPU_SDMA_EVENT_13_OFFSET            0x00000098
+#define IPU_IPU_SDMA_EVENT_14_OFFSET            0x0000009C
+#define IPU_IPU_SRM_PRI1_OFFSET                 0x000000A0
+#define IPU_IPU_SRM_PRI2_OFFSET                 0x000000A4
+#define IPU_IPU_FS_PROC_FLOW1_OFFSET            0x000000A8
+#define IPU_IPU_FS_PROC_FLOW2_OFFSET            0x000000AC
+#define IPU_IPU_FS_PROC_FLOW3_OFFSET            0x000000B0
+#define IPU_IPU_FS_DISP_FLOW1_OFFSET            0x000000B4
+#define IPU_IPU_FS_DISP_FLOW2_OFFSET            0x000000B8
+#define IPU_IPU_SKIP_OFFSET                     0x000000BC
+#define IPU_IPU_DISP_ALT_CONF_OFFSET            0x000000C0
+#define IPU_IPU_DISP_GEN_OFFSET                 0x000000C4
+#define IPU_IPU_DISP_ALT1_OFFSET                0x000000C8
+#define IPU_IPU_DISP_ALT2_OFFSET                0x000000CC
+#define IPU_IPU_DISP_ALT3_OFFSET                0x000000D0
+#define IPU_IPU_DISP_ALT4_OFFSET                0x000000D4
+#define IPU_IPU_SNOOP_OFFSET                    0x000000D8
+#define IPU_IPU_MEM_RST_OFFSET                  0x000000DC
+#define IPU_IPU_PM_OFFSET                       0x000000E0
+#define IPU_IPU_GPR_OFFSET                      0x000000E4
+#define IPU_IPU_INT_STAT_1_OFFSET               0x000000E8
+#define IPU_IPU_INT_STAT_2_OFFSET               0x000000EC
+#define IPU_IPU_INT_STAT_3_OFFSET               0x000000F0
+#define IPU_IPU_INT_STAT_4_OFFSET               0x000000F4
+#define IPU_IPU_INT_STAT_5_OFFSET               0x000000F8
+#define IPU_IPU_INT_STAT_6_OFFSET               0x000000FC
+#define IPU_IPU_INT_STAT_7_OFFSET               0x00000100
+#define IPU_IPU_INT_STAT_8_OFFSET               0x00000104
+#define IPU_IPU_INT_STAT_9_OFFSET               0x00000108
+#define IPU_IPU_INT_STAT_10_OFFSET              0x0000010C
+#define IPU_IPU_INT_STAT_11_OFFSET              0x00000110
+#define IPU_IPU_INT_STAT_12_OFFSET              0x00000114
+#define IPU_IPU_INT_STAT_13_OFFSET              0x00000118
+#define IPU_IPU_INT_STAT_14_OFFSET              0x0000011C
+#define IPU_IPU_INT_STAT_15_OFFSET              0x00000120
+#define IPU_IPU_CUR_BUF_0_OFFSET                0x00000124
+#define IPU_IPU_CUR_BUF_1_OFFSET                0x00000128
+#define IPU_IPU_ALT_CUR_BUF_0_OFFSET            0x0000012C
+#define IPU_IPU_ALT_CUR_BUF_1_OFFSET            0x00000130
+#define IPU_IPU_SRM_STAT_OFFSET                 0x00000134
+#define IPU_IPU_PROC_TASKS_STAT_OFFSET          0x00000138
+#define IPU_IPU_DISP_TASKS_STAT_OFFSET          0x0000013C
+#define IPU_IPU_CH_BUF0_RDY0_OFFSET             0x00000140
+#define IPU_IPU_CH_BUF0_RDY1_OFFSET             0x00000144
+#define IPU_IPU_CH_BUF1_RDY0_OFFSET             0x00000148
+#define IPU_IPU_CH_BUF1_RDY1_OFFSET             0x0000014C
+#define IPU_IPU_CH_DB_MODE_SEL0_OFFSET          0x00000150
+#define IPU_IPU_CH_DB_MODE_SEL1_OFFSET          0x00000154
+#define IPU_IPU_ALT_CH_BUF0_RDY0_OFFSET         0x00000158
+#define IPU_IPU_ALT_CH_BUF0_RDY1_OFFSET         0x0000015C
+#define IPU_IPU_ALT_CH_BUF1_RDY0_OFFSET         0x00000160
+#define IPU_IPU_ALT_CH_BUF1_RDY1_OFFSET         0x00000164
+#define IPU_IPU_ALT_CH_DB_MODE_SEL0_OFFSET      0x00000168
+#define IPU_IPU_ALT_CH_DB_MODE_SEL1_OFFSET      0x0000016C
+#define CSP_IPUV3_CPMEM_REGS_OFFSET             0x00100000
+
+// IPU DIx Registers
+#define IPU_DIx_GENERAL_OFFSET                  0x00000000
+#define IPU_DIx_BS_CLKGEN0_OFFSET               0x00000004
+#define IPU_DIx_BS_CLKGEN1_OFFSET               0x00000008
+#define IPU_DIx_SW_GEN0_1_OFFSET                0x0000000C
+#define IPU_DIx_SW_GEN0_2_OFFSET                0x00000010
+#define IPU_DIx_SW_GEN0_3_OFFSET                0x00000014
+#define IPU_DIx_SW_GEN0_4_OFFSET                0x00000018
+#define IPU_DIx_SW_GEN0_5_OFFSET                0x0000001C
+#define IPU_DIx_SW_GEN0_6_OFFSET                0x00000020
+#define IPU_DIx_SW_GEN0_7_OFFSET                0x00000024
+#define IPU_DIx_SW_GEN0_8_OFFSET                0x00000028
+#define IPU_DIx_SW_GEN0_9_OFFSET                0x0000002C
+#define IPU_DIx_SW_GEN1_1_OFFSET                0x00000030
+#define IPU_DIx_SW_GEN1_2_OFFSET                0x00000034
+#define IPU_DIx_SW_GEN1_3_OFFSET                0x00000038
+#define IPU_DIx_SW_GEN1_4_OFFSET                0x0000003C
+#define IPU_DIx_SW_GEN1_5_OFFSET                0x00000040
+#define IPU_DIx_SW_GEN1_6_OFFSET                0x00000044
+#define IPU_DIx_SW_GEN1_7_OFFSET                0x00000048
+#define IPU_DIx_SW_GEN1_8_OFFSET                0x0000004C
+#define IPU_DIx_SW_GEN1_9_OFFSET                0x00000050
+#define IPU_DIx_SYNC_AS_GEN_OFFSET              0x00000054
+#define IPU_DIx_DW_GEN_OFFSET                   0x00000058
+#define IPU_DIx_DW_SET0_OFFSET                  0x00000088
+#define IPU_DIx_DW_SET1_OFFSET                  0x000000B8
+#define IPU_DIx_DW_SET2_OFFSET                  0x000000E8
+#define IPU_DIx_DW_SET3_OFFSET                  0x00000118
+#define IPU_DIx_STP_REP_OFFSET                  0x00000148
+#define IPU_DIx_STP_REP_9_OFFSET                0x00000158
+#define IPU_DIx_SER_CONF_OFFSET                 0x0000015C
+#define IPU_DIx_SSC_OFFSET                      0x00000160
+#define IPU_DIx_POL_OFFSET                      0x00000164
+#define IPU_DIx_AW0_OFFSET                      0x00000168
+#define IPU_DIx_AW1_OFFSET                      0x0000016C
+#define IPU_DIx_SCR_CONF_OFFSET                 0x00000170
+#define IPU_DIx_STAT_OFFSET                     0x00000174
+
+// IPU IDMAC Registers
+#define IPU_IDMAC_LOCK_EN_1                     0x00008024
+#define IPU_IDMAC_LOCK_EN_2                     0x00008028
+
+// IPU DisplayInterface0 Registers
+#define IPU_DISPLAY_INTERFACE_0_OFFSET          0x00040000
+#define IPU_DI0_BS_CLKGEN0_OFFSET               0x00040004
+#define IPU_DI0_BS_CLKGEN1_OFFSET               0x00040008
+#define IPU_DI0_SW_GEN0_1_OFFSET                0x0004000C
+#define IPU_DI0_SW_GEN0_2_OFFSET                0x00040010
+#define IPU_DI0_SW_GEN0_3_OFFSET                0x00040014
+#define IPU_DI0_SW_GEN0_4_OFFSET                0x00040018
+#define IPU_DI0_SW_GEN0_5_OFFSET                0x0004001C
+#define IPU_DI0_SW_GEN0_6_OFFSET                0x00040020
+#define IPU_DI0_SW_GEN0_7_OFFSET                0x00040024
+#define IPU_DI0_SW_GEN0_8_OFFSET                0x00040028
+#define IPU_DI0_SW_GEN0_9_OFFSET                0x0004002C
+#define IPU_DI0_SW_GEN1_1_OFFSET                0x00040030
+#define IPU_DI0_SW_GEN1_2_OFFSET                0x00040034
+#define IPU_DI0_SW_GEN1_3_OFFSET                0x00040038
+#define IPU_DI0_SW_GEN1_4_OFFSET                0x0004003C
+#define IPU_DI0_SW_GEN1_5_OFFSET                0x00040040
+#define IPU_DI0_SW_GEN1_6_OFFSET                0x00040044
+#define IPU_DI0_SW_GEN1_7_OFFSET                0x00040048
+#define IPU_DI0_SW_GEN1_8_OFFSET                0x0004004C
+#define IPU_DI0_SW_GEN1_9_OFFSET                0x00040050
+#define IPU_DI0_SYNC_AS_GEN_OFFSET              0x00040054
+#define IPU_DI0_DW_GEN_OFFSET                   0x00040058
+#define IPU_DI0_DW_SET0_OFFSET                  0x00040088
+#define IPU_DI0_DW_SET1_OFFSET                  0x000400B8
+#define IPU_DI0_DW_SET2_OFFSET                  0x000400E8
+#define IPU_DI0_DW_SET3_OFFSET                  0x00040118
+#define IPU_DI0_STP_REP_OFFSET                  0x00040148
+#define IPU_DI0_STP_REP_9_OFFSET                0x00040158
+#define IPU_DI0_SER_CONF_OFFSET                 0x0004015C
+#define IPU_DI0_SSC_OFFSET                      0x00040160
+#define IPU_DI0_POL_OFFSET                      0x00040164
+#define IPU_DI0_AW0_OFFSET                      0x00040168
+#define IPU_DI0_AW1_OFFSET                      0x0004016C
+#define IPU_DI0_SCR_CONF_OFFSET                 0x00040170
+#define IPU_DI0_STAT_OFFSET                     0x00040174
+
+// IPU DisplayInterface1 Registers
+#define IPU_DISPLAY_INTERFACE_1_OFFSET          0x00048000
+#define IPU_DI1_BS_CLKGEN0_OFFSET               0x00048004
+#define IPU_DI1_BS_CLKGEN1_OFFSET               0x00048008
+#define IPU_DI1_SW_GEN0_1_OFFSET                0x0004800C
+#define IPU_DI1_SW_GEN0_2_OFFSET                0x00048010
+#define IPU_DI1_SW_GEN0_3_OFFSET                0x00048014
+#define IPU_DI1_SW_GEN0_4_OFFSET                0x00048018
+#define IPU_DI1_SW_GEN0_5_OFFSET                0x0004801C
+#define IPU_DI1_SW_GEN0_6_OFFSET                0x00048020
+#define IPU_DI1_SW_GEN0_7_OFFSET                0x00048024
+#define IPU_DI1_SW_GEN0_8_OFFSET                0x00048028
+#define IPU_DI1_SW_GEN0_9_OFFSET                0x0004802C
+#define IPU_DI1_SW_GEN1_1_OFFSET                0x00048030
+#define IPU_DI1_SW_GEN1_2_OFFSET                0x00048034
+#define IPU_DI1_SW_GEN1_3_OFFSET                0x00048038
+#define IPU_DI1_SW_GEN1_4_OFFSET                0x0004803C
+#define IPU_DI1_SW_GEN1_5_OFFSET                0x00048040
+#define IPU_DI1_SW_GEN1_6_OFFSET                0x00048044
+#define IPU_DI1_SW_GEN1_7_OFFSET                0x00048048
+#define IPU_DI1_SW_GEN1_8_OFFSET                0x0004804C
+#define IPU_DI1_SW_GEN1_9_OFFSET                0x00048050
+#define IPU_DI1_SYNC_AS_GEN_OFFSET              0x00048054
+#define IPU_DI1_DW_GEN_OFFSET                   0x00048058
+#define IPU_DI1_DW_SET0_OFFSET                  0x00048088
+#define IPU_DI1_DW_SET1_OFFSET                  0x000480B8
+#define IPU_DI1_DW_SET2_OFFSET                  0x000480E8
+#define IPU_DI1_DW_SET3_OFFSET                  0x00048118
+#define IPU_DI1_STP_REP_OFFSET                  0x00048148
+#define IPU_DI1_STP_REP_9_OFFSET                0x00048158
+#define IPU_DI1_SER_CONF_OFFSET                 0x0004815C
+#define IPU_DI1_SSC_OFFSET                      0x00048160
+#define IPU_DI1_POL_OFFSET                      0x00048164
+#define IPU_DI1_AW0_OFFSET                      0x00048168
+#define IPU_DI1_AW1_OFFSET                      0x0004816C
+#define IPU_DI1_SCR_CONF_OFFSET                 0x00048170
+#define IPU_DI1_STAT_OFFSET                     0x00048174
+
+#endif  /* _IPU_H_ */
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
new file mode 100644
index 000000000000..e6eb3b31bb07
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
@@ -0,0 +1,93 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMXDisplay.h>
+
+#include "Display.h"
+#include "Lvds.h"
+#include "Edid.h"
+
+EFI_STATUS
+InitLvds (
+  IN  DISPLAY_CONTEXT   *DisplayContextPtr
+  )
+{
+  DISPLAY_INTERFACE_CONTEXT   *pLvdsDisplayContext;
+  EFI_STATUS                  Status;
+  LDB_CTRL_REG                LdbCtrlReg;
+
+  Status = EFI_SUCCESS;
+  pLvdsDisplayContext = &DisplayContextPtr->DiContext[Lvds0Display];
+  ZeroMem (pLvdsDisplayContext, sizeof (*pLvdsDisplayContext));
+
+  pLvdsDisplayContext->MmioBasePtr = (VOID *)LDB_BASE;
+  if (pLvdsDisplayContext->MmioBasePtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to map LDB register\n", __FUNCTION__));
+    goto Exit;
+  }
+
+  // LVDS CH1 enabled, routed to DisplayInterface0; ipu_di01_vsync_active_low
+  LdbCtrlReg.Reg = MmioRead32 ((UINT32)pLvdsDisplayContext->MmioBasePtr + LDB_CTRL);
+  LdbCtrlReg.ch0_mode = 1;
+  LdbCtrlReg.ch1_mode = 1;
+  LdbCtrlReg.di0_vs_polarity = 1;
+  LdbCtrlReg.di1_vs_polarity = 1;
+  MmioWrite32 ((UINT32)pLvdsDisplayContext->MmioBasePtr + LDB_CTRL, LdbCtrlReg.Reg);
+
+  // No EDID available
+  pLvdsDisplayContext->EdidDataSize = 0;
+
+  Status = GetPreferredTiming (
+             pLvdsDisplayContext->EdidData,
+             pLvdsDisplayContext->EdidDataSize,
+             &pLvdsDisplayContext->PreferredTiming
+           );
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to retrieve LVDS preferred timing\n",
+      __FUNCTION__));
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+EFI_STATUS
+SetLvdsPower (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  BOOLEAN                     PowerState
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+SetLvdsDisplay (
+  IN  DISPLAY_INTERFACE_CONTEXT   *pLvdsDisplayContext,
+  IN  DISPLAY_TIMING              *Timings
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
new file mode 100644
index 000000000000..b45201fb45fc
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
@@ -0,0 +1,67 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _LVDS_H_
+#define _LVDS_H_
+
+// LDB Register Base Address
+#define LDB_BASE 0x020E0008
+
+// LDB Control Register offset
+#define LDB_CTRL    0
+
+#pragma pack(push, 1)
+
+// LDB_CTRL_REG
+typedef union {
+  struct {
+    UINT32 ch0_mode : 2;
+    UINT32 ch1_mode : 2;
+    UINT32 split_mode_en : 1;
+    UINT32 data_width_ch0 : 1;
+    UINT32 bit_mapping_ch0 : 1;
+    UINT32 data_width_ch1 : 1;
+    UINT32 bit_mapping_ch1 : 1;
+    UINT32 di0_vs_polarity : 1;
+    UINT32 di1_vs_polarity : 1;
+    UINT32 Reserved11_15 : 5;
+    UINT32 lvds_clk_shift : 3;
+    UINT32 Reserved19 : 1;
+    UINT32 counter_reset_val : 2;
+    UINT32 Reserved22_31 : 10;
+  };
+  UINT32 Reg;
+}  LDB_CTRL_REG;
+
+#pragma pack(pop)
+
+EFI_STATUS
+InitLvds (
+  IN  DISPLAY_CONTEXT   *DisplayContextPtr
+  );
+
+EFI_STATUS
+SetLvdsPower (
+  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
+  IN  BOOLEAN                     PowerState
+  );
+
+EFI_STATUS
+SetLvdsDisplay (
+  IN  DISPLAY_INTERFACE_CONTEXT   *LvdsDisplayContextPtr,
+  IN  DISPLAY_TIMING              *Timings
+  );
+
+#endif  /* _LVDS_H_ */
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 24/27] Silicon/NXP: Add i.MX6 common dsc and fdf files
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (22 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-14 23:36   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 25/27] Platform/Solidrun: Add Hummingboard Peripheral Initialization Chris Co
                   ` (3 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds the common dsc and fdf definitions for NXP i.MX6 platforms.
Platform dsc definitions will define $(BOARD_NAME), $(IMX_FAMILY),
$(IMX_CHIP_TYPE), $(DRAM_SIZE), and $(BOARD_DIR) to indicate
i.MX SoC family and board-specific configurations.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc | 897 ++++++++++++++++++++
 Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc | 287 +++++++
 Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc | 148 ++++
 3 files changed, 1332 insertions(+)

diff --git a/Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc b/Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
new file mode 100644
index 000000000000..743a022c2b4a
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
@@ -0,0 +1,897 @@
+#
+# iMX6 Quad and Dual SOM platforms common description
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+################################################################################
+#
+# [Defines] Section
+#
+################################################################################
+[Defines]
+  PLATFORM_NAME                  = iMX6
+  PLATFORM_GUID                  = F01954EE-8AC4-45BC-80E5-511EAE64C38C
+  PLATFORM_VERSION               = 0.1
+  DSC_SPECIFICATION              = 0x00010019
+  OUTPUT_DIRECTORY               = Build/$(BOARD_NAME)
+  SUPPORTED_ARCHITECTURES        = ARM
+  BUILD_TARGETS                  = DEBUG|RELEASE
+  SKUID_IDENTIFIER               = DEFAULT
+
+!include Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
+
+################################################################################
+#
+# [BuildOptions] Section
+#
+################################################################################
+[BuildOptions]
+  GCC:*_*_*_CC_FLAGS = -D$(BOARD_NAME) -DCPU_$(IMX_FAMILY) -DSOCTYPE_$(IMX_CHIP_TYPE) -Wno-unused-local-typedefs
+  GCC:*_*_*_OBJCOPY_PATH = noop
+  GCC:*_*_*_SYMRENAME_PATH = noop
+  *_*_*_ASL_PATH == asl.exe
+  *_*_*_ASL_FLAGS == /MsftInternal
+  *_*_*_ASL_OUTFLAGS == /Fo=
+
+# CPU_* compiler flag is used to select constants for iMX6.h
+
+[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLICATION]
+  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
+
+[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+  GCC:*_*_ARM_DLINK_FLAGS = -z common-page-size=0x1000
+
+################################################################################
+#
+# [LibraryClasses] Sections
+#
+# When parsing the DSC file, the precedence rules will followed.
+#  1. If a Library Class Instance (INF) is specified in the EDK II [Components] section
+#     (INF files <LibraryClasses> sub-section,) then it will be used.
+#  2. If not specified in the [Components] section, then the Library Class Instance that is
+#     defined in the [LibraryClasses.$(ARCH).$(MODULE_TYPE)] section will be used.
+#  3. If not specified in the [LibraryClasses.$(ARCH).$(MODULE_TYPE)] section, then
+#     the Library Class Instance that is defined in the
+#     [LibraryClasses.Common.$(MODULE_TYPE)] section will be used.
+#  4. If not specified in the [LibraryClasses.Common.$(MODULE_TYPE)] section, then
+#     the Library Class Instance that is defined in the [LibraryClasses.$(ARCH)] section
+#     will be used.
+#  5. If not specified in the [LibraryClasses.$(ARCH)] section, then the Library Class
+#     Instance that is defined in the [LibraryClasses] Section or
+#     [LibraryClasses.Common] section will be used.
+#  6. It is an error if it has not been specified in one of the above sections
+#
+################################################################################
+
+[LibraryClasses.common]
+  #
+  # CPU and Timing
+  #
+  ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
+  ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+  ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
+  CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
+  ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+  RealTimeClockLib|Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
+  DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
+  CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf
+  TimerLib|Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
+
+  #
+  # Memory
+  #
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+  DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+
+  #
+  # Platform
+  #
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+  PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
+  ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
+  EfiResetSystemLib|ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf
+
+  #
+  # Peripherals
+  #
+  UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+  NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+
+  #
+  # UEFI Services and Runtime
+  #
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+
+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+
+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+
+  #
+  # Human Interface Infrastructure (HII)
+  #
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+
+  #
+  # BDS
+  #
+  BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+  PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+  FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
+  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+
+  #
+  # Shell
+  #
+  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+
+  #
+  # Serial, Console and Debugging
+  #
+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+  SerialPortLib|Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+
+  # Enable debug prints in both release and debug builds
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+  #
+  # The Standard IO window in the debugger will show load and unload events for symbols.
+  #
+!if $(CONFIG_DUMP_SYMBOL_INFO) == TRUE
+  PeCoffExtraActionLib|Platform/Microsoft/Library/LauterbachPeCoffExtraActionLib/LauterbachPeCoffExtraActionLib.inf
+!else
+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+!endif
+
+  #
+  # Display
+  #
+  iMXDisplayLib|Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
+
+  #
+  # Security
+  #
+  TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+  Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
+  Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
+
+  #
+  # iMX6 Specifics
+  #
+  iMXIoMuxLib|Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
+!if $(IMX_FAMILY) == IMX6SX
+  iMX6ClkPwrLib|Silicon/NXP/iMX6Pkg/Library/iMX6SxClkPwrLib/iMX6SxClkPwrLib.inf
+!else
+  iMX6ClkPwrLib|Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
+!endif
+  iMX6UsbPhyLib|Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
+
+[LibraryClasses.ARM]
+  #
+  # It is not possible to prevent the ARM compiler for generic intrinsic functions.
+  # This library provides the instrinsic functions generate by a given compiler.
+  # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
+  #
+  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+  NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+
+[LibraryClasses.common.SEC]
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
+  ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf
+  ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
+  ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
+  HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
+  LzmaDecompressLib|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+  MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf
+  MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+  PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
+  PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
+  PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
+  DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLibBase.inf
+
+[LibraryClasses.common.PEI_CORE]
+  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+  ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
+  ArmGicArchLib|ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+  DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf
+  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+  ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
+
+!if $(CONFIG_OPTEE) == TRUE
+  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
+  Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+!endif
+
+[LibraryClasses.common.UEFI_APPLICATION]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
+
+!if $(CONFIG_OPTEE) == TRUE
+  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+!endif
+
+[LibraryClasses.common.UEFI_DRIVER]
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+
+!if $(CONFIG_OPTEE) == TRUE
+!if $(CONFIG_MEASURED_BOOT) == TRUE
+  TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+!endif
+!endif
+
+################################################################################
+#
+# PCD Sections
+#
+################################################################################
+
+########################
+#
+# ArmPkg PCDs
+#
+########################
+[PcdsFeatureFlag.common]
+  #
+  # Use the Vector Table location in CpuDxe. We will not copy the Vector Table at
+  # PcdCpuVectorBaseAddress
+  #
+  gArmTokenSpaceGuid.PcdRelocateVectorTable|FALSE
+
+[PcdsFixedAtBuild.common]
+  gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE
+  gArmTokenSpaceGuid.PcdVFPEnabled|1
+
+  #
+  # ARM General Interrupt Controller settings
+  #
+  gArmTokenSpaceGuid.PcdGicDistributorBase|0x00A01000
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x00A00100
+  gArmTokenSpaceGuid.PcdArmPrimaryCore|0x000
+
+  #
+  # ARM L2x0 PCDs
+  #
+  #gArmTokenSpaceGuid.PcdL2x0ControllerBase|0x00A02000
+
+  #
+  # GPT Timer Frequency
+  # Set to 1KHz, which equals to 1us resolution
+  #
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|1000000
+
+########################
+#
+# ArmPlatformPkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+  # Size of the region used by UEFI in permanent memory (Reserved 16MB)
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x01000000
+
+!if $(IMX_FAMILY) == IMX6SX
+  #
+  # Refer to the detailed memory map at OpteeClientPkg PCDs section below
+  #
+  giMX6TokenSpaceGuid.PcdMemoryStartAddress|0x80000000
+  gArmTokenSpaceGuid.PcdSystemMemoryBase|0x829D4000
+  !if $(DRAM_SIZE) == DRAM_512MB
+  #
+  # Board DDR starts at 0x80000000 and ends 0x9FFF0000 (512MB)
+  # SystemMemorySize is 0x9FFF0000 - PcdSystemMemoryBase
+  #
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x9FFF0000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x1D61C000
+  !elseif $(DRAM_SIZE) == DRAM_1GB
+  #
+  # Board DDR starts at 0x80000000 and ends 0xBFFF0000 (1GB)
+  # SystemMemorySize is 0xBFFF0000 - PcdSystemMemoryBase
+  #
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0xBFFF0000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x3D61C000
+  !else
+  #
+  # Board DDR starts at 0x80000000 and ends 0xFFFF0000 (2GB)
+  # SystemMemorySize is 0xFFFF0000 - PcdSystemMemoryBase
+  #
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0xFFFF0000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x7D61C000
+  !endif
+!else
+  giMX6TokenSpaceGuid.PcdMemoryStartAddress|0x10000000
+  gArmTokenSpaceGuid.PcdSystemMemoryBase|0x12A00000
+
+  !if $(DRAM_SIZE) == DRAM_512MB
+  #
+  # Board DDR starts at 0x10000000 and ends 0x2FFF0000 (512MB)
+  # SystemMemorySize is 0x2FFF0000 - PcdSystemMemoryBase
+  #
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x2FFF0000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x1D5F0000
+  !elseif $(DRAM_SIZE) == DRAM_1GB
+  #
+  # Board DDR starts at 0x10000000 and ends 0x4FFF0000 (1GB)
+  # SystemMemorySize is 0x4FFF0000 - PcdSystemMemoryBase
+  #
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x4FFF0000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x3D5F0000
+  !else
+  #
+  # Board DDR starts at 0x10000000 and ends 0x8FFF0000 (2GB)
+  # SystemMemorySize is 0x8FFF0000 - PcdSystemMemoryBase
+  #
+  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x8FFF0000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x7D5F0000
+  !endif
+!endif
+
+!if $(CONFIG_MPCORE) == TRUE
+  !if (($(IMX_CHIP_TYPE) == QUAD) || ($(IMX_CHIP_TYPE) == QUADPLUS))
+  gArmPlatformTokenSpaceGuid.PcdCoreCount|4
+  !elseif (($(IMX_CHIP_TYPE) == DUAL) || ($(IMX_CHIP_TYPE) == DUALLITE))
+  gArmPlatformTokenSpaceGuid.PcdCoreCount|2
+  !else
+  gArmPlatformTokenSpaceGuid.PcdCoreCount|1
+  !endif
+!else
+  gArmPlatformTokenSpaceGuid.PcdCoreCount|1
+!endif
+
+########################
+#
+# MdePkg PCDs
+#
+########################
+[PcdsFeatureFlag.common]
+  gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
+
+[PcdsFixedAtBuild.common]
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000
+  gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000
+  gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF
+  gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0
+  gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320
+  gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|1
+
+  #
+  # DEBUG_ASSERT_ENABLED       0x01
+  # DEBUG_PRINT_ENABLED        0x02
+  # DEBUG_CODE_ENABLED         0x04
+  # CLEAR_MEMORY_ENABLED       0x08
+  # ASSERT_BREAKPOINT_ENABLED  0x10
+  # ASSERT_DEADLOOP_ENABLED    0x20
+  #
+  !if $(TARGET) == RELEASE
+    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x23
+  !else
+    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f
+  !endif
+
+  #
+  # Debug Flags as defined in DebugLib.h
+  #
+  # DEBUG_INIT      0x00000001  // Initialization
+  # DEBUG_WARN      0x00000002  // Warnings
+  # DEBUG_LOAD      0x00000004  // Load events
+  # DEBUG_FS        0x00000008  // EFI File system
+  # DEBUG_POOL      0x00000010  // Alloc & Free (pool)
+  # DEBUG_PAGE      0x00000020  // Alloc & Free (page)
+  # DEBUG_INFO      0x00000040  // Informational debug messages
+  # DEBUG_DISPATCH  0x00000080  // PEI/DXE/SMM Dispatchers
+  # DEBUG_VARIABLE  0x00000100  // Variable
+  # DEBUG_BM        0x00000400  // Boot Manager
+  # DEBUG_BLKIO     0x00001000  // BlkIo Driver
+  # DEBUG_NET       0x00004000  // Network Io Driver
+  # DEBUG_UNDI      0x00010000  // UNDI Driver
+  # DEBUG_LOADFILE  0x00020000  // LoadFile
+  # DEBUG_TEEC      0x00040000  // TEE Client Tracings
+  # DEBUG_EVENT     0x00080000  // Event messages
+  # DEBUG_GCD       0x00100000  // Global Coherency Database changes
+  # DEBUG_CACHE     0x00200000  // Memory range cachability changes
+  # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
+  #                             // significantly impact boot performance
+  # DEBUG_ERROR     0x80000000  // Error
+  #
+  # By default only enable init, error, warning and load debug prints to minimize
+  # debug messages. Use "0x8FEF4DCF" for detailed debugging purposes.
+  #
+!if $(TARGET) == RELEASE
+  #
+  # In release builds enable error, warning, and load (base and entry point)
+  #
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel| 0x80000006
+!else
+  #
+  # In debug builds enable error, cache, info, load, warn, and init
+  #
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel| 0x80000047
+!endif
+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
+
+########################
+#
+# MdeModulePkg PCDs
+#
+########################
+[PcdsFeatureFlag.common]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE
+
+  ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe.
+  #  It could be set FALSE to save size.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+
+[PcdsFixedAtBuild.common]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+  gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4
+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+  # GUID of the UI app
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+[PcdsPatchableInModule]
+  # Console Resolution
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|1920
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|1080
+
+########################
+#
+# EmbeddedPkg PCDs
+#
+########################
+[PcdsFeatureFlag.common]
+  gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE
+
+[PcdsFixedAtBuild.common]
+  #
+  # Optional feature to help prevent EFI memory map fragments
+  # Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob
+  # Values are in EFI Pages (4K). DXE Core will make sure that
+  # at least this much of each type of memory can be allocated
+  # from a single memory range. This way you only end up with
+  # maximum of two fragements for each type in the memory map
+  # (the memory used, and the free memory that was prereserved
+  # but not used).
+  #
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|3000
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0
+
+  #
+  # Timer Configuration
+  #
+  # The timer period is configured in units of 100ns. We configure it for 10ms
+  # timer ticks which will be used mainly by DXE Core to keep track of system
+  # time and hence keep track of all events.
+  #
+  gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000
+
+########################
+#
+# IntelFrameworkModulePkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+  # GUID of the UEFI Shell
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }
+
+########################
+#
+# OpteeClientPkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+!if $(IMX_FAMILY) == IMX6SX
+  #
+  # Reserved for TPM2 ACPI
+  # 0x82000000 - 0x82002FFF
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0x82000000
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0x3000
+
+  #
+  # iMX Plaform Memory Layout
+  #
+  # +-------------------+===> (0x80000000) PcdTrustZonePrivateMemoryBase (OPTEE image base address)
+  # | TZ Private Memory |  ^
+  # | (OPTEE)           |  |  (0x01E00000) PcdTrustZonePrivateMemorySize 30MB
+  # |                   |  v
+  # +-------------------+===> (0x81E00000) PcdTrustZoneSharedMemoryBase (includes mobj bookkeeping page)
+  # | TZ Shared Memory  |  ^
+  # |                   |  |  (0x00200000) PcdTrustZoneSharedMemorySize 2MB
+  # |                   |  v
+  # +-------------------|===> (0x82000000) PcdTpm2AcpiBufferBase
+  # | TPM2 Control Area |  ^
+  # |                   |  |  (0x00003000) PcdTpm2AcpiBufferSize 12KB
+  # |                   |  v
+  # +-------------------+===> (0x82003000) PcdGlobalDataBaseAddress
+  # | Global Data       |  ^
+  # |                   |  |  (0x00001000) PcdGlobalDataSize 4KB
+  # |                   |  v
+  # +-------------------+===> (0x82004000) PcdFdBaseAddress (UEFI Load Address)
+  # | UEFI              |  ^
+  # |                   |  |  (0x001D0000) PcdFdSize 1856KB
+  # |                   |  v
+  # +-------------------+===> (0x821D4000) PcdFrameBufferBase
+  # | FrameBuffer       |  ^
+  # |                   |  |  (0x00800000) PcdFrameBufferSize 8MB
+  # |                   |  v
+  # +-------------------+===> (0x829D4000) PcdSystemMemoryBase
+  # | Operating System  |  ^
+  # | Memory            |  |
+  # |                   |  |
+  # |                   |  v
+  # +------------------ +===>
+
+  DEFINE GLOBAL_DATA_BASE_ADDRESS = 0x82003000
+
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0x80000000
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|0x01E00000
+
+  #
+  # TrustZone shared memory (2Mb)
+  # This memory is managed by the normal world but shared with the OpTEE OS.
+  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
+  #    CFG_SHMEM_START & CFG_SHMEM_SIZE
+  # NOTE: The first page of the SHMEM is owned by OPTEE for mobj bookkeeping
+  # and we should not touch it. We will skip the first 4K of SHMEM and take that
+  # into account for SHMEM size in PcdTrustZoneSharedMemorySize.
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0x81E00000
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0x00200000
+
+  giMX6TokenSpaceGuid.PcdFrameBufferBase|0x821D4000
+
+!else
+  #
+  # Reserved for TPM2 ACPI
+  # 0x10814000 - 0x10816FFF
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0x10814000
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0x3000
+
+  #
+  # iMX Plaform Memory Layout
+  #
+  # +-------------------+===> (0x10000000) PcdFrameBufferBase (DDR Start Address)
+  # |Frame Buffer       |  ^
+  # |                   |  |  (0x00800000) PcdFrameBufferSize 8MB
+  # |                   |  v
+  # +-------------------+===
+  # |                   |     Gap
+  # +-------------------|===> (0x10814000) PcdTpm2AcpiBufferBase
+  # |TPM2 Control Area  |  ^
+  # |                   |  |  (0x3000) 12KB
+  # |                   |  v
+  # +-------------------+===> (0x10817000) PcdGlobalDataBaseAddress
+  # | Global Data       |  ^
+  # |                   |  |  (0x1000) PcdGlobalDataSize 4KB
+  # |                   |  v
+  # +-------------------+===
+  # | Gap               |
+  # +-------------------+===> (0x10820000) UEFI Load Address
+  # | UEFI              |  ^
+  # |                   |  |  (0x1D0000) 1920KB
+  # |                   |  v
+  # +-------------------+===> (0x10A00000) PcdTrustZonePrivateMemoryBase (OPTEE image base address)
+  # | TZ Private Memory |  ^
+  # | (OPTEE)           |  |  (0x1E00000) 30MB
+  # |                   |  v
+  # +-------------------+===> (0x12800000) PcdTrustZoneSharedMemoryBase (includes mobj bookkeeping page)
+  # | TZ Shared Memory  |  ^
+  # |                   |  |  (0x200000) 2MB
+  # |                   |  v
+  # +-------------------+===> (0x12A00000) PcdSystemMemoryBase
+  # | Operating System  |  ^
+  # | Memory            |  |  (0x3D5F0000) 982MB for 1GB DRAM OR
+  # |                   |  |  (0x7D5F0000) 2005MB for 2GB DRAM
+  # |                   |  v
+  # +------------------ +===
+  #
+  # Reserved for Optee private memory (31M)
+  # 0x10A00000 - 0x127FFFFF
+  #
+  # TrustZone private memory (?Mb OPTEE + ?Mb PSCI)
+  # 0x8E000000 - 8FEFFFFF
+  # This memory is managed privately by the OpTEE OS.
+  #    CFG_DDR_TEETZ_RESERVED_START & CFG_DDR_TEETZ_RESERVED_START
+  #
+
+  DEFINE GLOBAL_DATA_BASE_ADDRESS = 0x10817000
+
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0x10A00000
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|0x01E00000
+
+  #
+  # TrustZone shared memory (2Mb)
+  # 0x12800000 - 0x129FFFFF
+  # This memory is managed by the normal world but shared with the OpTEE OS.
+  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
+  #    CFG_SHMEM_START & CFG_SHMEM_SIZE
+  # NOTE: The first page of the SHMEM is owned by OPTEE for mobj bookkeeping
+  # and we should not touch it. We will skip the first 4K of SHMEM and take that
+  # into account for SHMEM size in PcdTrustZoneSharedMemorySize.
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0x12800000
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0x00200000
+
+  giMX6TokenSpaceGuid.PcdFrameBufferBase|0x10000000
+
+!endif
+########################
+#
+# SecurityPkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+  #
+  # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
+  #
+  gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04
+  gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04
+  gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
+
+  #
+  # PcdTpmInstanceGuid tells the Tcg2 Driver which TPM version is being used.
+  # The below GUID is TPMv2 GUID.
+  #
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{ 0x5a, 0xf2, 0x6b, 0x28, 0xc3, 0xc2, 0x8c, 0x40, 0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17 }
+
+  ## Sets the default Physical Presence flags that are consumed by the PP TrEE library.
+  #
+  # Options are defined in TrEEPhysicalPresenceData.h
+  # Current setting:
+  #   TREE_FLAG_NO_PPI_CLEAR
+  #
+  #gEfiSecurityPkgTokenSpaceGuid.PcdPPDefaultTrEEFlags|0x02
+
+  ## Indicates whether or not the Tcg2Dxe should measure CRTM instead of PEI.
+  # TRUE means the Tcg2Dxe will measure CRTM.
+  #
+  #gEfiSecurityPkgTokenSpaceGuid.PcdLateMeasureCRTM|TRUE
+
+[PcdsDynamicExDefault.common.DEFAULT]
+  gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap|0x0
+
+########################
+#
+# MsPkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+
+  #
+  # SD first FAT partition device path:
+  # VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,03000000)/SD(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)
+  #
+  # eMMC first FAT partition device path:
+  # VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,04000000)/eMMC(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)
+  #
+  # Use the SDCard first fat partition for logging and misc storage.
+  #
+  gMsPkgTokenSpaceGuid.PcdStorageMediaPartitionDevicePath|L"VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,03000000)/SD(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)"
+
+!if $(CONFIG_SECURE_BOOT) == TRUE
+  gMsPkgTokenSpaceGuid.PcdSecureBootEnable|TRUE
+!else
+  gMsPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE
+!endif
+
+########################
+#
+# iMXPlatformPkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+
+  # Global data area
+  giMXPlatformTokenSpaceGuid.PcdGlobalDataBaseAddress|$(GLOBAL_DATA_BASE_ADDRESS)
+  giMXPlatformTokenSpaceGuid.PcdGlobalDataSize|0x1000
+
+################################################################################
+#
+# [Components] Section
+#
+################################################################################
+[Components.common]
+
+  #
+  # SEC (PrePi)
+  #
+  ArmPlatformPkg/PrePi/PeiMPCore.inf
+
+  #
+  # DXE Core
+  #
+  MdeModulePkg/Core/Dxe/DxeMain.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+  }
+  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  }
+
+  #
+  # DXE required Architectural Protocols as defined by UEFI 2.6 specs
+  #
+  # BDS Arch Protocol
+  # CPU Arch Protocol
+  # Metronome Arch Protocol
+  # Real Time Clock Arch Protocol
+  # Reset Arch Protocol
+  # Runtime Arch Protocol
+  # Security Arch Protocol
+  # Timer Arch Protocol
+  # Variable Arch Protocol
+  # Variable Write Arch Protocol
+  # EFI Capsule Arch Protocol
+  # Watchdog Timer Arch Protocol
+  #
+
+  ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+  EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+  EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+  EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+      NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+  }
+  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+  ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+
+  #
+  # Serial Console
+  #
+  MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+  EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+
+  #
+  # Filesystem Stack
+  #
+  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+  FatPkg/EnhancedFatDxe/Fat.inf
+  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
+  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
+
+  # PCIe support
+  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
+
+  #
+  # Generic Bds (Not Intel's)
+  #
+  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+  MdeModulePkg/Application/UiApp/UiApp.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+      NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+      NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+  }
+
+  #
+  # Shell
+  #
+  ShellPkg/Application/Shell/Shell.inf {
+    <LibraryClasses>
+      ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+      BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+      HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+      NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+      PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+
+    <PcdsFixedAtBuild>
+      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+      gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+  }
+
+MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+
+#
+# Boilerplate for compiling UEFI applications and UEFI drivers with the
+# standard library.
+#
+!include StdLib/StdLib.inc
diff --git a/Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc b/Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
new file mode 100644
index 000000000000..877f575d7999
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
@@ -0,0 +1,287 @@
+#
+# FLASH layout file for iMX6 Quad and Dual SOM boards.
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+# Continuation of [FV.FvMain]
+  INF MdeModulePkg/Core/Dxe/DxeMain.inf
+  INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+  #
+  # PI DXE Drivers producing Architectural Protocols (EFI Services)
+  #
+  INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+
+  INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+  INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+  INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+  INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+
+  INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  # Timers
+  INF Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
+
+  INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+  INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
+
+  INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+  INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+  INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+
+  #
+  # Filesystem Stack
+  #
+  INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  INF FatBinPkg/EnhancedFatDxe/Fat.inf
+  INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+  INF Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
+  INF Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
+
+  #
+  # PCIe
+  #
+  INF Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
+
+  #
+  # Bds
+  #
+  INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+  INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+  INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+  INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+  INF MdeModulePkg/Application/UiApp/UiApp.inf
+
+  #
+  # UEFI application (Shell Embedded Boot Loader)
+  #
+  INF ShellPkg/Application/Shell/Shell.inf
+
+INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+
+[FV.FVMAIN_COMPACT]
+FvAlignment        = 8
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+  INF ArmPlatformPkg/PrePi/PeiMPCore.inf
+
+  FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+    SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+      SECTION FV_IMAGE = FVMAIN
+    }
+  }
+
+
+################################################################################
+#
+# Rules are use with the [FV] section's module INF type to define
+# how an FFS file is created for a given INF file. The following Rule are the default
+# rules for the different module type. User can add the customized rules to define the
+# content of the FFS file.
+#
+################################################################################
+
+
+############################################################################
+# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section   #
+############################################################################
+#
+#[Rule.Common.DXE_DRIVER]
+#  FILE DRIVER = $(NAMED_GUID) {
+#    DXE_DEPEX    DXE_DEPEX               Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+#    COMPRESS PI_STD {
+#      GUIDED {
+#        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+#        UI       STRING="$(MODULE_NAME)" Optional
+#        VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+#      }
+#    }
+#  }
+#
+############################################################################
+!if 0
+[Rule.Common.SEC]
+  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+    TE  TE    Align = 32                $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.PEI_CORE]
+  FILE PEI_CORE = $(NAMED_GUID) {
+    TE     TE                           $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI     STRING ="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM]
+  FILE PEIM = $(NAMED_GUID) {
+    PEI_DEPEX PEI_DEPEX Optional       $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32      PE32                     $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM.TIANOCOMPRESSED]
+  FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
+    PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+    GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+      PE32      PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+      UI        STRING="$(MODULE_NAME)" Optional
+    }
+  }
+
+[Rule.Common.DXE_CORE]
+  FILE DXE_CORE = $(NAMED_GUID) {
+    PE32     PE32                       $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+
+[Rule.Common.UEFI_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_APPLICATION]
+  FILE APPLICATION = $(NAMED_GUID) {
+    UI     STRING ="$(MODULE_NAME)" Optional
+    PE32   PE32                         $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX DXE_DEPEX Optional      |.depex
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+  FILE APPLICATION = $(NAMED_GUID) {
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+!endif
+
+[Rule.Common.SEC]
+  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+    TE  TE    Align = 32                $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.PEI_CORE]
+  FILE PEI_CORE = $(NAMED_GUID) {
+    TE     TE                           $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI     STRING ="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM]
+  FILE PEIM = $(NAMED_GUID) {
+     PEI_DEPEX PEI_DEPEX Optional       $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32                     $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM.TIANOCOMPRESSED]
+  FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
+    PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+    GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+      PE32      PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+      UI        STRING="$(MODULE_NAME)" Optional
+    }
+  }
+
+[Rule.Common.DXE_CORE]
+  FILE DXE_CORE = $(NAMED_GUID) {
+    PE32     PE32                       $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+
+[Rule.Common.UEFI_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_APPLICATION]
+  FILE APPLICATION = $(NAMED_GUID) {
+    UI     STRING ="$(MODULE_NAME)" Optional
+    PE32   PE32                         $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+  FILE FREEFORM = $(NAMED_GUID) {
+    RAW          ACPI                 |.acpi
+    RAW          ASL Optional         |.aml
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX DXE_DEPEX Optional      |.depex
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+  FILE APPLICATION = $(NAMED_GUID) {
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
diff --git a/Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc b/Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
new file mode 100644
index 000000000000..cf3b68556a4e
--- /dev/null
+++ b/Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
@@ -0,0 +1,148 @@
+#
+# iMX6 Common Configurations Definition
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+[Defines]
+
+  # Display surface will not be drawn to.
+!ifndef CONFIG_HEADLESS
+  DEFINE CONFIG_HEADLESS = FALSE
+!endif
+
+  # Useful if working with Lauterbach JTAG. Will dump to console the complete
+  # command to copy and past into the Lauterbach command line to load symbols
+  # for each module.
+  # Use in conjution with Informational debug messages:
+  # DEBUG_INFO      0x00000040
+!ifndef CONFIG_DUMP_SYMBOL_INFO
+  DEFINE CONFIG_DUMP_SYMBOL_INFO = FALSE
+!endif
+
+  # Enable if PSCI is implemented.
+!ifndef CONFIG_MPCORE
+  DEFINE CONFIG_MPCORE = TRUE
+!endif
+
+  # Disable the PCIexpress stack by default. Enable on demand.
+!ifndef CONFIG_PCIE
+  DEFINE CONFIG_PCIE = FALSE
+!endif
+
+  # States whether OPTEE boot flow is in effect or not. This has the following
+  # implications:
+  # - OPTEE owns the SecureWorld and UEFI has to run in NormalWorld.
+  # - Specific memory layout that is defined in the platform .dsc file.
+  # - Temp: Running in single-core until PSCI is enabled.
+  # WARNING: Don't set this to FALSE unless you know what you are doing. Running
+  # UEFI in SecureWorld will most likely result in boot failure due to lack of
+  # proper CPU sec configuration. That is by UEFI design.
+!ifndef CONFIG_OPTEE
+  DEFINE CONFIG_OPTEE = TRUE
+!endif
+
+  # Allow collecting performance tracing from OPTEE hot code paths
+  # Performance summary results can be inspected with the shell app Dp.efi
+!ifndef CONFIG_OPTEE_PROFILE
+  DEFINE CONFIG_OPTEE_PROFILE = FALSE
+!endif
+
+  # Call build with -D CONFIG_SECURE_UEFI=1 to enable the follwing security features
+!if $(CONFIG_SECURE_UEFI) == TRUE
+
+  # UEFI authenticated variable runtime services
+!ifndef CONFIG_AUTH_VAR
+  DEFINE CONFIG_AUTH_VAR = TRUE
+!endif
+
+  # TPM stack for the fTPM
+!ifndef CONFIG_MEASURED_BOOT
+  DEFINE CONFIG_MEASURED_BOOT = TRUE
+!endif
+
+  # If Platform Key (PK) is provisioned, then SecureBoot variables will get
+  # updated to reflect that SecureBoot is enabled. Otherwise, SecureBoot
+  # variables will indicate that the feature is disabled, and the OS will
+  # not boot apply SecureBoot policies
+!ifndef CONFIG_SECURE_BOOT
+  DEFINE CONFIG_SECURE_BOOT = TRUE
+!endif
+
+  # Provison SecureBoot with MS test certs and keys that are baked into the FV
+  # on first UEFI boot if SecureBoot found to be not provisioned
+  DEFINE CONFIG_SECURE_BOOT_AUTO_CONFIG = TRUE
+!else
+
+!ifndef CONFIG_AUTH_VAR
+  DEFINE CONFIG_AUTH_VAR = FALSE
+!endif
+
+!ifndef CONFIG_MEASURED_BOOT
+  DEFINE CONFIG_MEASURED_BOOT = FALSE
+!endif
+
+!ifndef CONFIG_SECURE_BOOT
+  DEFINE CONFIG_SECURE_BOOT = FALSE
+!endif
+
+!endif
+
+[BuildOptions]
+#
+# For each enabled CONFIG_* flag in the dsc files, define that flag in C code.
+# Description of each CONFIG_* flag exist in iMX6DefaultConfigDsc.inc
+# Note: The = sign in BuildOptions section appends to the existing macro, while
+# == can be used to replace its value. See the EDK2 DSC specs.
+#
+!if $(CONFIG_HEADLESS) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_HEADLESS=1
+!endif
+
+!if $(CONFIG_DUMP_SYMBOL_INFO) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_DUMP_SYMBOL_INFO=1
+!endif
+
+!if $(CONFIG_MPCORE) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_MPCORE=1
+!endif
+
+!if $(CONFIG_USB) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_USB=1
+!endif
+
+!if $(CONFIG_PCIE) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_PCIE=1
+!endif
+
+!if $(CONFIG_OPTEE) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_OPTEE=1
+!endif
+
+!if $(CONFIG_OPTEE_PROFILE) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DOPTEE_PROFILE=1
+!endif
+
+!if $(CONFIG_AUTH_VAR) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_AUTH_VAR=1
+!endif
+
+!if $(CONFIG_MEASURED_BOOT) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_MEASURED_BOOT=1
+!endif
+
+!if $(CONFIG_SECURE_BOOT) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_SECURE_BOOT=1
+!endif
+
+!if $(CONFIG_SECURE_BOOT_AUTO_CONFIG) == TRUE
+  GCC:*_*_*_CC_FLAGS = -DCONFIG_SECURE_BOOT_AUTO_CONFIG=1
+!endif
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 25/27] Platform/Solidrun: Add Hummingboard Peripheral Initialization
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (23 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 24/27] Silicon/NXP: Add i.MX6 common dsc and fdf files Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-15 12:12   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 26/27] Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables Chris Co
                   ` (2 subsequent siblings)
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Michael D Kinney, Ard Biesheuvel, Leif Lindholm

This adds support to initialize the different peripherals on
the Solidrun i.MX 6Quad Hummingboard Edge.  It will initialize the
pad mux and clocks for the different peripherals.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
---
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c  | 634 ++++++++++++++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h  | 705 ++++++++++++++++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf |  91 +++
 3 files changed, 1430 insertions(+)

diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
new file mode 100644
index 000000000000..73e63484288c
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
@@ -0,0 +1,634 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*  Copyright 2018 NXP
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <IndustryStandard/Tpm20.h>
+#include <IndustryStandard/Tpm2Acpi.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/TimerLib.h>
+
+#include "iMX6BoardInit.h"
+
+STATIC CONST IMX_CLK_GATE GatesToTurnOff[] = {
+  IMX_ASRC_CLK_ENABLE,
+  IMX_CAN1_CLK_ENABLE,
+  IMX_CAN1_SERIAL_CLK_ENABLE,
+  IMX_CAN2_CLK_ENABLE,
+  IMX_CAN2_SERIAL_CLK_ENABLE,
+  IMX_DCIC1_CLK_ENABLE,
+  IMX_DCIC2_CLK_ENABLE,
+  IMX_DTCP_CLK_ENABLE,
+  IMX_ECSPI1_CLK_ENABLE,
+  IMX_ECSPI2_CLK_ENABLE,
+  IMX_ECSPI3_CLK_ENABLE,
+  IMX_ECSPI4_CLK_ENABLE,
+  IMX_ECSPI5_CLK_ENABLE,
+  IMX_ENET_CLK_ENABLE,
+  IMX_ESAI_CLK_ENABLE,
+  IMX_I2C1_SERIAL_CLK_ENABLE,
+  IMX_I2C2_SERIAL_CLK_ENABLE,
+  IMX_I2C3_SERIAL_CLK_ENABLE,
+  IMX_IIM_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
+  IMX_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE,
+  IMX_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE,
+  IMX_IPU1_DI1_CLK_ENABLE,
+  IMX_IPU2_CLK_ENABLE,
+  IMX_IPU2_DI0_CLK_ENABLE,
+  IMX_IPU2_DI1_CLK_ENABLE,
+  IMX_LDB_DI0_CLK_ENABLE,
+  IMX_LDB_DI1_CLK_ENABLE,
+  IMX_MIPI_CORE_CFG_CLK_ENABLE,
+  IMX_MLB_CLK_ENABLE,
+  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
+  IMX_PWM2_CLK_ENABLE,
+  IMX_PWM3_CLK_ENABLE,
+  IMX_PWM4_CLK_ENABLE,
+  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
+  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
+  IMX_SPDIF_CLK_ENABLE,
+  IMX_SSI1_CLK_ENABLE,
+  IMX_SSI2_CLK_ENABLE,
+  IMX_SSI3_CLK_ENABLE,
+  IMX_EIM_SLOW_CLK_ENABLE,
+  IMX_VDOAXICLK_CLK_ENABLE,
+  IMX_VPU_CLK_ENABLE,
+};
+
+STATIC CONST IMX_CLK_GATE GatesToTurnOn[] = {
+  IMX_SDMA_CLK_ENABLE,
+  IMX_SPBA_CLK_ENABLE,
+  IMX_GPT_SERIAL_CLK_ENABLE,
+  IMX_USBOH3_CLK_ENABLE,
+  IMX_PWM1_CLK_ENABLE
+};
+
+STATIC IMX_PAD GpioPins[] = {
+  IMX_PAD_ENET_RX_ER,
+  IMX_PAD_EIM_A22,
+  IMX_PAD_EIM_A21,
+  IMX_PAD_EIM_A20,
+  IMX_PAD_EIM_A19,
+  IMX_PAD_EIM_A18,
+  IMX_PAD_EIM_A17,
+  IMX_PAD_EIM_A16,
+  IMX_PAD_EIM_EB0,
+  IMX_PAD_EIM_EB1,
+  IMX_PAD_EIM_DA0,
+  IMX_PAD_EIM_DA1,
+  IMX_PAD_EIM_DA2,
+  IMX_PAD_EIM_DA3,
+  IMX_PAD_EIM_DA4,
+  IMX_PAD_EIM_DA5,
+  IMX_PAD_EIM_DA6,
+  IMX_PAD_EIM_DA7,
+  IMX_PAD_EIM_DA8,
+  IMX_PAD_EIM_DA9,
+  IMX_PAD_EIM_DA10,
+  IMX_PAD_EIM_DA11,
+  IMX_PAD_EIM_DA12,
+  IMX_PAD_EIM_DA13,
+  IMX_PAD_EIM_DA14,
+  IMX_PAD_EIM_DA15,
+  IMX_PAD_EIM_D26,
+  IMX_PAD_EIM_D27,
+  IMX_PAD_EIM_D30,
+  IMX_PAD_EIM_D31,
+  IMX_PAD_EIM_A24,
+  IMX_PAD_EIM_A23,
+  IMX_PAD_GPIO_16,
+};
+
+CONST IMX_CLK_GATE UartClockGatesToTurnOn[] = {
+  IMX_PLL3_MAIN_CLK, // IMX_UART_CLK_ENABLE,
+  IMX_UART_CLK_ROOT  // UART_SERIAL_CLK_ENABLE,
+};
+
+/**
+  Turn off clock gates which are not needed during boot. The PEP is responsible
+  to ungate clocks as needed.
+**/
+STATIC
+VOID
+GateUnusedClocks (
+  VOID
+  )
+{
+  ImxClkPwrSetClockGates (
+    GatesToTurnOff,
+    sizeof (GatesToTurnOff) / sizeof (GatesToTurnOff[0]),
+    IMX_CLOCK_GATE_STATE_OFF);
+}
+
+/**
+  Turn on required clocks, that are not handled by the PEP.
+**/
+STATIC
+VOID
+UngateRequiredClocks (
+  VOID
+  )
+{
+  ImxClkPwrSetClockGates (
+    GatesToTurnOn,
+    sizeof (GatesToTurnOn) / sizeof (GatesToTurnOn[0]),
+    IMX_CLOCK_GATE_STATE_ON);
+}
+
+STATIC
+VOID
+EnetInit (
+  VOID
+  )
+{
+  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogReg;
+  IMX_CCM_ANALOG_PLL_ENET_REG         CcmAnalogPllReg;
+  UINT32                              Counter;
+
+  // Apply ENET pin-muxing configurations (ALT 1)
+  ImxPadConfig (IMX_PAD_ENET_MDIO, IMX_PAD_ENET_MDIO_ENET_MDIO);
+  ImxPadConfig (IMX_PAD_ENET_MDC, IMX_PAD_ENET_MDC_ENET_MDC);
+  ImxPadConfig (IMX_PAD_KEY_ROW4, IMX_PAD_CFG_KEY_ROW4_GPIO4_IO15);
+  ImxPadConfig (IMX_PAD_DI0_PIN2, IMX_PAD_DI0_PIN2_GPIO4_IO18);
+  ImxPadConfig (IMX_PAD_GPIO_16, IMX_PAD_GPIO_16_ENET_REF_CLK);
+  ImxPadConfig (IMX_PAD_ENET_REF_CLK, IMX_PAD_ENET_REF_CLK_ENET_REF_CLK);
+  ImxPadConfig (IMX_PAD_RGMII_TD0, IMX_PAD_RGMII_TD0_RGMII_TD0);
+  ImxPadConfig (IMX_PAD_RGMII_TD1, IMX_PAD_RGMII_TD1_RGMII_TD1);
+  ImxPadConfig (IMX_PAD_RGMII_TD2, IMX_PAD_RGMII_TD2_RGMII_TD2);
+  ImxPadConfig (IMX_PAD_RGMII_TD3, IMX_PAD_RGMII_TD3_RGMII_TD3);
+  ImxPadConfig (IMX_PAD_RGMII_TXC, IMX_PAD_RGMII_TXC_RGMII_TXC);
+  ImxPadConfig (IMX_PAD_RGMII_TX_CTL, IMX_PAD_RGMII_TX_CTL_RGMII_TX_CTL);
+
+  ImxPadConfig (IMX_PAD_RGMII_RD0, IMX_PAD_RGMII_RD0_ENET_RGMII_RD0);
+  ImxPadConfig (IMX_PAD_RGMII_RD1, IMX_PAD_RGMII_RD1_ENET_RGMII_RD1);
+  ImxPadConfig (IMX_PAD_RGMII_RD2, IMX_PAD_RGMII_RD2_ENET_RGMII_RD2);
+  ImxPadConfig (IMX_PAD_RGMII_RD3, IMX_PAD_RGMII_RD3_ENET_RGMII_RD3);
+  ImxPadConfig (IMX_PAD_RGMII_RXC, IMX_PAD_RGMII_RXC_ENET_RGMII_RXC);
+  ImxPadConfig (IMX_PAD_RGMII_RX_CTL, IMX_PAD_RGMII_RX_CTL_RGMII_RX_CTL);
+
+  // Enable ENET PLL, also required for PCIe
+  pCcmAnalogReg = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
+  CcmAnalogPllReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogReg->PLL_ENET);
+  CcmAnalogPllReg.POWERDOWN = 0;
+  CcmAnalogPllReg.ENABLE = 1;
+  MmioWrite32 ((UINTN)&pCcmAnalogReg->PLL_ENET, CcmAnalogPllReg.AsUint32);
+
+  for (Counter = 0; Counter < 100; Counter++) {
+    CcmAnalogPllReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogReg->PLL_ENET);
+    if (CcmAnalogPllReg.LOCK != 0) {
+      break;
+    }
+    MicroSecondDelay (100);
+  }
+  if (CcmAnalogPllReg.LOCK == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PLL_ENET is not locked!\n", __FUNCTION__));
+    return;
+  }
+
+  // Enable PCIe output 125Mhz
+  CcmAnalogPllReg.BYPASS = 0;
+  CcmAnalogPllReg.ENABLE_125M = 1;
+  CcmAnalogPllReg.DIV_SELECT = PLL_ENET_DIV_SELECT_25MHZ;
+  MmioWrite32 ((UINTN)&pCcmAnalogReg->PLL_ENET, CcmAnalogPllReg.AsUint32);
+  MicroSecondDelay (50000);
+
+  if (CcmAnalogPllReg.LOCK == 0) {
+    DEBUG ((DEBUG_ERROR, "%a: PLL_ENET is not locked!\n", __FUNCTION__));
+  }
+}
+
+/**
+  Set SSI3 clock dividers to provide a bit clock capable of
+  providing a clock suitable for stereo 44.1 KHz playback at 32 bit
+  from PLL3 PFD2 which runs at 508.2 MHz.
+
+  We only need to scale down the PLL3 FPD2 clock by 1:15 to provide a
+  reference clock.  The WDM audio class driver will later setup additional
+  dividers in the SSI3 block to provide the required bit clock rate.
+
+  This routine also handles all GPIO/PadConfig init required for audio.
+**/
+STATIC
+VOID
+SetupAudio (
+  VOID
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmReg;
+  IMX_CCM_CCOSR_REG           CcosrReg;
+  IMX_CCM_CS1CDR_REG          CsicdrReg;
+
+  pCcmReg = (IMX_CCM_REGISTERS *)IMX_CCM_BASE;
+  CsicdrReg = (IMX_CCM_CS1CDR_REG) MmioRead32 ((UINTN)&pCcmReg->CS1CDR);
+  CsicdrReg.ssi3_clk_pred = 0; // divide by 1.
+  CsicdrReg.ssi3_clk_podf = 14; // divide by 15.
+  MmioWrite32 ((UINTN)&pCcmReg->CS1CDR, CsicdrReg.AsUint32);
+
+  // Enable output on CCM_CLKO1, select pll3_sw_clk/2 as the source.
+  CcosrReg = (IMX_CCM_CCOSR_REG) MmioRead32 ((UINTN)&pCcmReg->CCOSR);
+  CcosrReg.CLKO1_SEL = 0;
+  CcosrReg.CLKO1_DIV = 0;
+  CcosrReg.CLKO1_EN = 1;
+
+  MmioWrite32 ((UINTN)&pCcmReg->CCOSR, CcosrReg.AsUint32);
+  // Set GPIO05 alt config to ALT3 (CCM_CLKO1).
+  // This clock drives the master clock for the audio codec.
+  ImxPadConfig (IMX_PAD_GPIO_5, IMX_PAD_CFG_GPIO_5_CCM_CLKO1);
+
+  // Set alt config for KEY_COL0, KEY_ROW0, KEY_COL1 to ALT2 (AUD5_TXC/TXD/TXFS)
+  // DSP_DAT19 is set to ALT3 for AUD5_RXD.
+  ImxPadConfig (IMX_PAD_KEY_COL0, IMX_PAD_CFG_KEY_COL0_AUD5_TXC);
+  ImxPadConfig (IMX_PAD_KEY_ROW0, IMX_PAD_CFG_KEY_ROW0_AUD5_TXD);
+  ImxPadConfig (IMX_PAD_KEY_COL1, IMX_PAD_CFG_KEY_COL1_AUD5_TXFS);
+  ImxPadConfig (IMX_PAD_DISP0_DAT19, IMX_PAD_CFG_DISP0_DAT19_AUD5_RXD);
+}
+
+/**
+  Initialize clock and power for modules on the SoC.
+**/
+VOID
+ImxClkPwrInit (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  GateUnusedClocks();
+  UngateRequiredClocks();
+
+  if (FeaturePcdGet (PcdGpuEnable)) {
+    Status = ImxClkPwrGpuEnable ();
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    Status = ImxClkPwrIpuLDBxEnable ();
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  Status = ImxClkPwrIpuDIxEnable();
+  ASSERT_EFI_ERROR (Status);
+
+  ASSERT_EFI_ERROR (ImxClkPwrValidateClocks ());
+}
+
+/**
+  Initialize SDHC modules on the SOC and perform required pin-muxing
+**/
+VOID
+SdhcInit (
+  VOID
+  )
+{
+  // uSDHC2: SDCard Socket
+  ImxPadConfig (IMX_PAD_SD2_CLK, IMX_PAD_CFG_SD2_CLK_SD2_CLK);
+  ImxPadConfig (IMX_PAD_SD2_CMD, IMX_PAD_CFG_SD2_CMD_SD2_CMD);
+  ImxPadConfig (IMX_PAD_SD2_DAT0, IMX_PAD_CFG_SD2_DAT0_SD2_DATA0);
+  ImxPadConfig (IMX_PAD_SD2_DAT1, IMX_PAD_CFG_SD2_DAT1_SD2_DATA1);
+  ImxPadConfig (IMX_PAD_SD2_DAT2, IMX_PAD_CFG_SD2_DAT2_SD2_DATA2);
+  ImxPadConfig (IMX_PAD_SD2_DAT3, IMX_PAD_CFG_SD2_DAT3_SD2_DATA3);
+  ImxPadConfig (IMX_PAD_GPIO_4, IMX_PAD_CFG_GPIO_4_SD2_CD_B);
+  ImxPadConfig (IMX_PAD_KEY_ROW1, IMX_PAD_CFG_KEY_ROW1_SD2_VSELECT);
+
+#if DEBUG
+  DEBUG ((DEBUG_INIT, "uSDHC2 PAD Config:\n"));
+  ImxPadDumpConfig ("CLK", IMX_PAD_SD2_CLK);
+  ImxPadDumpConfig ("CMD", IMX_PAD_SD2_CMD);
+  ImxPadDumpConfig ("DAT0", IMX_PAD_SD2_DAT0);
+  ImxPadDumpConfig ("DAT1", IMX_PAD_SD2_DAT1);
+  ImxPadDumpConfig ("DAT2", IMX_PAD_SD2_DAT2);
+  ImxPadDumpConfig ("DAT3", IMX_PAD_SD2_DAT3);
+  ImxPadDumpConfig ("VSELECT", IMX_PAD_KEY_ROW1);
+  ImxPadDumpConfig ("CD", IMX_PAD_GPIO_4);
+#endif // DEBUG
+
+  // Power-on SDCard through the GPIO signal connected to
+  // Q1 MOSFET Gate acting as a switch to SDCard VDD supply voltage
+  ImxPadConfig (IMX_PAD_DISP0_DAT9, IMX_PAD_CFG_DISP0_DAT9_GPIO4_IO30);
+  ImxGpioDirection (IMX_GPIO_BANK4, 30, IMX_GPIO_DIR_OUTPUT);
+  ImxGpioWrite (IMX_GPIO_BANK4, 30, IMX_GPIO_LOW);
+
+  // Pre-configure the GPIO ALT5 of all SD2_* pads to be input pins.
+  // SD2_CLK: GPIO1_IO10
+  ImxGpioDirection (IMX_GPIO_BANK1, 10, IMX_GPIO_DIR_INPUT);
+
+  // SD2_CMD: GPIO1_IO11
+  ImxGpioDirection (IMX_GPIO_BANK1, 11, IMX_GPIO_DIR_INPUT);
+
+  // SD2_DATA0: GPIO1_IO15
+  ImxGpioDirection (IMX_GPIO_BANK1, 15, IMX_GPIO_DIR_INPUT);
+
+  // SD2_DATA1: GPIO1_IO14
+  ImxGpioDirection (IMX_GPIO_BANK1, 14, IMX_GPIO_DIR_INPUT);
+
+  // SD2_DATA2: GPIO1_IO13
+  ImxGpioDirection (IMX_GPIO_BANK1, 13, IMX_GPIO_DIR_INPUT);
+
+  // SD2_DATA3: GPIO1_IO12
+  ImxGpioDirection (IMX_GPIO_BANK1, 12, IMX_GPIO_DIR_INPUT);
+
+  // uSDHC3: eMMC Socket
+  ImxPadConfig (IMX_PAD_SD3_CLK, IMX_PAD_CFG_SD3_CLK_SD3_CLK);
+  ImxPadConfig (IMX_PAD_SD3_CMD, IMX_PAD_CFG_SD3_CMD_SD3_CMD);
+  ImxPadConfig (IMX_PAD_SD3_RST, IMX_PAD_CFG_SD3_RST_SD3_RST);
+  ImxPadConfig (IMX_PAD_SD3_DAT0, IMX_PAD_CFG_SD3_DAT0_SD3_DATA0);
+  ImxPadConfig (IMX_PAD_SD3_DAT1, IMX_PAD_CFG_SD3_DAT1_SD3_DATA1);
+  ImxPadConfig (IMX_PAD_SD3_DAT2, IMX_PAD_CFG_SD3_DAT2_SD3_DATA2);
+  ImxPadConfig (IMX_PAD_SD3_DAT3, IMX_PAD_CFG_SD3_DAT3_SD3_DATA3);
+  ImxPadConfig (IMX_PAD_SD3_DAT4, IMX_PAD_CFG_SD3_DAT4_SD3_DATA4);
+  ImxPadConfig (IMX_PAD_SD3_DAT5, IMX_PAD_CFG_SD3_DAT5_SD3_DATA5);
+  ImxPadConfig (IMX_PAD_SD3_DAT6, IMX_PAD_CFG_SD3_DAT6_SD3_DATA6);
+  ImxPadConfig (IMX_PAD_SD3_DAT7, IMX_PAD_CFG_SD3_DAT7_SD3_DATA7);
+}
+
+/**
+  Initialize EHCI modules on the SOC and perform required pin-muxing.
+  This routine also initializes PHY0(OTG) and PHY1 (USBH1).
+**/
+VOID
+EhciInit (
+  VOID
+  )
+{
+  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxGprReg;
+  IMX_IOMUXC_GPR1_REG                 IoMuxGpr1Reg;
+
+  // Pin-mux OTG Over Current
+  ImxPadConfig (IMX_PAD_KEY_COL4, IMX_PAD_CFG_KEY_COL4_USB_OTG_OC);
+
+  // Pin-mux and enable OTG power
+  ImxPadConfig (IMX_PAD_EIM_D22, IMX_PAD_CFG_EIM_DATA22_GPIO3_IO22_USB_OTG_PWR);
+  ImxGpioDirection (IMX_GPIO_BANK3, 22, IMX_GPIO_DIR_OUTPUT);
+  ImxGpioWrite (IMX_GPIO_BANK3, 22, IMX_GPIO_HIGH);
+
+  // Pin-mux and configure USB_OTG_ID as HOST
+  ImxPadConfig (IMX_PAD_GPIO_1, IMX_PAD_CFG_GPIO01_USB_OTG_ID_HOST);
+
+  // Configure USB_OTG_ID pin
+  pIoMuxGprReg = (IMX_IOMUXC_GPR_REGISTERS *) IOMUXC_GPR_BASE_ADDRESS;
+  IoMuxGpr1Reg = (IMX_IOMUXC_GPR1_REG) MmioRead32 ((UINTN)&pIoMuxGprReg->GPR1);
+  IoMuxGpr1Reg.USB_OTG_ID_SEL = IMX_IOMUXC_GPR1_USB_OTG_ID_SEL_GPIO_1;
+  MmioWrite32 ((UINTN)&pIoMuxGprReg->GPR1, IoMuxGpr1Reg.AsUint32);
+
+  // Pin-mux and enable USBH1 power
+  ImxPadConfig (IMX_PAD_GPIO_0, IMX_PAD_CFG_GPIO0_GPIO1_IO0_USBH1_PWR);
+  ImxGpioDirection (IMX_GPIO_BANK1, 0, IMX_GPIO_DIR_OUTPUT);
+  ImxGpioWrite (IMX_GPIO_BANK1, 0, IMX_GPIO_HIGH);
+
+  // Initialize PHY0 (OTG)
+  ImxUsbPhyInit (IMX_USBPHY0);
+
+  // Initialize PHY1 (USBH1)
+  ImxUsbPhyInit (IMX_USBPHY1);
+}
+
+/**
+  Initialize I2C modules on the SOC and perform required pin-muxing
+**/
+VOID
+I2cInit (
+  VOID
+  )
+{
+  // Enable 1.8V and 3.3V power rails for sensors connected to I2C1.
+  // The SENSOR_PWR_EN on EIM_EB3 line powers the pullups on I2c1.
+  ImxPadConfig (IMX_PAD_EIM_EB3, IMX_PAD_CFG_EIM_EB3_GPIO2_IO31);
+  ImxGpioDirection (IMX_GPIO_BANK2, 31, IMX_GPIO_DIR_OUTPUT);
+  ImxGpioWrite (IMX_GPIO_BANK2, 31, IMX_GPIO_HIGH); // set GPIO2_IO31 to 1
+  DEBUG ((DEBUG_INFO, "%a: Mux IMX_PAD_EIM_EB3 to GPIO Alt5. Set GPIO2_IO31\n",
+          __FUNCTION__));
+
+  // Configure I2C1. EIM_D21 is I2C1_SCL and EIM_D28 is I2C1_SDA. Alt6, Alt1
+  ImxPadConfig (IMX_PAD_EIM_D21, IMX_PAD_CFG_EIM_D21_I2C1_SCL);
+  ImxPadConfig (IMX_PAD_EIM_D28, IMX_PAD_CFG_EIM_D28_I2C1_SDA);
+  DEBUG ((DEBUG_INFO, "%a: I2C1 pin muxed via EIM D28,21\n", __FUNCTION__));
+
+  // I2C2 is used by GOP/Windows display driver. Do not configure I2C2 SCL via KEY_COL3, SDA via KEY_ROW3
+
+  // Configure I2C3 SCL via EIM_D17, SDA via EIM_D18. Inputs Alt6
+  ImxPadConfig (IMX_PAD_EIM_D17, IMX_PAD_CFG_EIM_D17_I2C3_SCL);
+  ImxPadConfig (IMX_PAD_EIM_D18, IMX_PAD_CFG_EIM_D18_I2C3_SDA);
+  DEBUG ((DEBUG_INFO, "%a: I2C3 pin muxed EIM_D17, 18\n", __FUNCTION__));
+}
+
+/**
+  Initialize SPI modules on the SOC and perform required pin-muxing
+**/
+VOID
+SpiInit (
+  VOID
+  )
+{
+  UINT32  RegValue;
+  // On Hummingboard only ESPI2 is exposed.
+  // Configure the return path for ECSPI2_MISO
+  RegValue = MmioRead32 (IOMUXC_ECSPI2_MISO_SELECT_INPUT);
+  RegValue &= ~3;
+  RegValue |= (IMX_IOMUXC_ECSPI2_MISO_EIM_OE_B_ALT2 << 0);
+  MmioWrite32 (IOMUXC_ECSPI2_MISO_SELECT_INPUT, RegValue);
+}
+
+/**
+  Initialize PCI Express module on the SOC and perform required pin-muxing
+**/
+VOID
+PcieInit (
+  VOID
+  )
+{
+  // PCIe GPIO Reset
+  ImxPadConfig (IMX_PAD_SD4_DAT3, IMX_PAD_CFG_SD4_DATA3_GPIO2_IO11);
+  ImxGpioDirection (IMX_GPIO_BANK2, 11, IMX_GPIO_DIR_OUTPUT);
+  ImxGpioWrite (IMX_GPIO_BANK2, 11, IMX_GPIO_LOW);
+}
+
+/**
+  Initialize exposed GPIO pins on carrier board. By default some
+  pins are set to CMOS inputs while others are set to Schmitt
+  triggers.  Normalize them all to Schmitt trigger inputs by setting
+  the hysteresis bit (16) in the pad ctl register.
+**/
+VOID
+GpioInit (
+  VOID
+  )
+{
+  UINT32  i;
+  IMX_PAD CurPad;
+
+  for (i = 0; i < sizeof (GpioPins) / sizeof (IMX_PAD); ++i) {
+    CurPad = GpioPins[i];
+    MmioOr32 (IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (CurPad), 1 << 16);
+  }
+}
+
+/**
+  Initalize the PWM controllers
+  PWM1 is exposed through Mikrobus header
+  Pinmux pad DISP0_DAT8 to (ALT2) PWM1_OUT
+**/
+VOID
+PwmInit (
+  VOID
+  )
+{
+  ImxPadConfig (IMX_PAD_DISP0_DAT8, IMX_PAD_CFG_DISP0_DAT8_PWM1_OUT);
+}
+
+/**
+    Initalize the UART controllers
+**/
+VOID
+UartInit (
+  VOID
+  )
+{
+  // UARTs share same Clock:
+  // PLL3 (480 MHz) -> pll3_sw_clk -> CG -> /6 -> uart_clk_root = 80 MHz
+  ImxClkPwrSetClockGates (
+    UartClockGatesToTurnOn,
+    sizeof (UartClockGatesToTurnOn) / sizeof (UartClockGatesToTurnOn[0]),
+    IMX_CLOCK_GATE_STATE_ON);
+
+  // Configure pin mux for UART 1 and UART 3
+  ImxPadConfig (IMX_PAD_CSI0_DAT11, IMX_PAD_UART1_RX_DATA);
+  ImxPadConfig (IMX_PAD_CSI0_DAT10, IMX_PAD_UART1_TX_DATA);
+  ImxPadConfig (IMX_PAD_EIM_D25, IMX_PAD_UART3_RX_DATA);
+  ImxPadConfig (IMX_PAD_EIM_D24, IMX_PAD_UART3_TX_DATA);
+
+  SerialPortInitialize ();
+  SerialPortWrite (
+    (UINT8 *)SERIAL_DEBUG_PORT_INIT_MSG,
+    (UINTN)sizeof (SERIAL_DEBUG_PORT_INIT_MSG));
+}
+
+/**
+    Initialize the TPM2 control area.
+**/
+VOID
+Tpm2AcpiControlAreaInit (
+  VOID
+  )
+{
+  EFI_TPM2_ACPI_CONTROL_AREA  *pControlArea;
+  EFI_PHYSICAL_ADDRESS        BaseAddress;
+  UINT32                      BufferSize;
+
+  BaseAddress = PcdGet64 (PcdTpm2AcpiBufferBase);
+  BufferSize = PcdGet32 (PcdTpm2AcpiBufferSize);
+
+  if ((BaseAddress == 0) || (BufferSize == 0)) {
+    // TPM not enabled
+    return;
+  }
+
+  ASSERT (BufferSize >= EFI_PAGE_SIZE * 3);
+
+  pControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *) ((UINTN)BaseAddress);
+  ZeroMem (pControlArea, sizeof (EFI_TPM2_ACPI_CONTROL_AREA));
+  BufferSize = EFI_PAGE_SIZE;
+  pControlArea->Command = (UINT64) ((UINTN) (pControlArea + 1));
+  pControlArea->CommandSize = BufferSize;
+  pControlArea->Response = pControlArea->Command + BufferSize;
+  pControlArea->ResponseSize = BufferSize;
+}
+
+/**
+  Initalize LVDS
+**/
+VOID
+LvdsInit (
+  VOID
+  )
+{
+  volatile IMX_CCM_REGISTERS  *pCcmReg;
+  IMX_CCM_CCGR3_REG           Ccgr3Reg;
+
+  pCcmReg = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
+  Ccgr3Reg = (IMX_CCM_CCGR3_REG) MmioRead32 ((UINTN) &pCcmReg->CCGR[3]);
+  Ccgr3Reg.ldb_di0_clk_enable = 0x3;
+  MmioWrite32 ((UINTN) &pCcmReg->CCGR[3], Ccgr3Reg.AsUint32);
+
+  // initalize backlight pin
+  ImxPadConfig (IMX_PAD_SD4_DAT1, IMX_PAD_CFG_SD4_DATA1_GPIO2_IO09);
+  ImxGpioDirection (IMX_GPIO_BANK2, 9, IMX_GPIO_DIR_OUTPUT);
+  ImxGpioWrite (IMX_GPIO_BANK2, 9, IMX_GPIO_HIGH);
+}
+
+/**
+  Initialize controllers that must setup at the early stage for iMX6 Quad
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+  IN  UINTN                     MpId
+  )
+{
+  if (!ArmPlatformIsPrimaryCore (MpId)) {
+    return RETURN_SUCCESS;
+  }
+
+  ImxClkPwrInit ();
+
+  // initialize default UEFI debug port early so we can use its debug output
+  SerialPortInitialize ();
+  SerialPortWrite (
+    (UINT8 *)SERIAL_DEBUG_PORT_INIT_MSG,
+    (UINTN)sizeof (SERIAL_DEBUG_PORT_INIT_MSG));
+
+  // Initialize timer early on because the following init path will be calling
+  // delay functions. PrePi.c calls ArmPlatformInitialize before it calls
+  // TimerConstructor to initialize the timer.
+  TimerConstructor ();
+
+  SdhcInit ();
+  EhciInit ();
+  EnetInit ();
+  I2cInit ();
+  SpiInit ();
+  PcieInit ();
+  SetupAudio ();
+  GpioInit ();
+  PwmInit ();
+
+  if (FeaturePcdGet (PcdLvdsEnable)) {
+    LvdsInit ();
+  }
+
+  Tpm2AcpiControlAreaInit ();
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Return the current Boot Mode
+
+  This function returns the boot reason on the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+  VOID
+  )
+{
+  return BOOT_WITH_FULL_CONFIGURATION;
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
new file mode 100644
index 000000000000..08ac78b16e8f
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
@@ -0,0 +1,705 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _IMX6_BOARD_INIT_H_
+#define _IMX6_BOARD_INIT_H_
+
+#include <iMX6.h>
+#include <iMX6ClkPwr.h>
+#include <iMX6IoMux.h>
+#include <iMX6Timer.h>
+#include <iMX6UsbPhy.h>
+
+//  Prebaked pad configurations that include mux and drive settings where
+//  each enum named as IMX_<MODULE-NAME>_PADCFG contains configurations
+//  for pads used by that module
+typedef enum {
+  IMX_PAD_ENET_MDIO_ENET_MDIO = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_ENABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_PULL,
+                                  IMX_PUS_100K_OHM_PU,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_ENET_MDIO_ALT1_ENET_MDIO),
+
+  IMX_PAD_ENET_MDC_ENET_MDC = _IMX_MAKE_PADCFG (
+                                IMX_SRE_SLOW,
+                                IMX_DSE_40_OHM,
+                                IMX_SPEED_MEDIUM,
+                                IMX_ODE_DISABLE,
+                                IMX_PKE_DISABLE,
+                                IMX_PUE_PULL,
+                                IMX_PUS_100K_OHM_PU,
+                                IMX_HYS_ENABLED,
+                                IMX_SION_DISABLED,
+                                IMX_IOMUXC_ENET_MDC_ALT1_ENET_MDC),
+
+  IMX_PAD_CFG_KEY_ROW4_GPIO4_IO15 = _IMX_MAKE_PADCFG (
+                                      IMX_SRE_SLOW,
+                                      IMX_DSE_40_OHM,
+                                      IMX_SPEED_MEDIUM,
+                                      IMX_ODE_DISABLE,
+                                      IMX_PKE_DISABLE,
+                                      IMX_PUE_PULL,
+                                      IMX_PUS_100K_OHM_PD,
+                                      IMX_HYS_ENABLED,
+                                      IMX_SION_DISABLED,
+                                      IMX_IOMUXC_KEY_ROW4_ALT5_GPIO4_IO15),
+
+  IMX_PAD_DI0_PIN2_GPIO4_IO18 = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_DISABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_PULL,
+                                  IMX_PUS_100K_OHM_PD,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_DI0_PIN2_ALT5_GPIO4_IO18),
+
+  IMX_PAD_GPIO_16_ENET_REF_CLK = _IMX_MAKE_PADCFG_INPSEL (
+                                   IMX_SRE_SLOW,
+                                   IMX_DSE_40_OHM,
+                                   IMX_SPEED_MEDIUM,
+                                   IMX_ODE_DISABLE,
+                                   IMX_PKE_DISABLE,
+                                   IMX_PUE_PULL,
+                                   IMX_PUS_100K_OHM_PU,
+                                   IMX_HYS_ENABLED,
+                                   IMX_SION_DISABLED,
+                                   IMX_IOMUXC_GPIO_16_ALT2_ENET_REF_CLK,
+                                   IOMUXC_ENET_REF_CLK_SELECT_INPUT,
+                                   GPIO16_ALT2),
+
+  IMX_PAD_RGMII_TXC_RGMII_TXC = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_DISABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_PULL,
+                                  IMX_PUS_100K_OHM_PU,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_RGMII_TXC_ALT1_RGMII_TXC),
+
+  IMX_PAD_RGMII_TD0_RGMII_TD0 = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_DISABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_KEEP,
+                                  IMX_PUS_100K_OHM_PU,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_RGMII_TD0_ALT1_RGMII_TD0),
+
+  IMX_PAD_RGMII_TD1_RGMII_TD1 = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_DISABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_KEEP,
+                                  IMX_PUS_100K_OHM_PU,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_RGMII_TD1_ALT1_RGMII_TD1),
+
+  IMX_PAD_RGMII_TD2_RGMII_TD2 = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_DISABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_KEEP,
+                                  IMX_PUS_100K_OHM_PU,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_RGMII_TD2_ALT1_RGMII_TD2),
+
+  IMX_PAD_RGMII_TD3_RGMII_TD3 = _IMX_MAKE_PADCFG (
+                                  IMX_SRE_SLOW,
+                                  IMX_DSE_40_OHM,
+                                  IMX_SPEED_MEDIUM,
+                                  IMX_ODE_DISABLE,
+                                  IMX_PKE_DISABLE,
+                                  IMX_PUE_KEEP,
+                                  IMX_PUS_100K_OHM_PU,
+                                  IMX_HYS_ENABLED,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_RGMII_TD3_ALT1_RGMII_TD3),
+
+  IMX_PAD_RGMII_TX_CTL_RGMII_TX_CTL = _IMX_MAKE_PADCFG (
+                                        IMX_SRE_SLOW,
+                                        IMX_DSE_40_OHM,
+                                        IMX_SPEED_MEDIUM,
+                                        IMX_ODE_DISABLE,
+                                        IMX_PKE_DISABLE,
+                                        IMX_PUE_PULL,
+                                        IMX_PUS_100K_OHM_PU,
+                                        IMX_HYS_ENABLED,
+                                        IMX_SION_DISABLED,
+                                        IMX_IOMUXC_RGMII_TX_CTL_ALT1_RGMII_TX_CTL),
+
+  IMX_PAD_ENET_REF_CLK_ENET_REF_CLK = _IMX_MAKE_PADCFG (
+                                        IMX_SRE_FAST,
+                                        IMX_DSE_40_OHM,
+                                        IMX_SPEED_MEDIUM,
+                                        IMX_ODE_DISABLE,
+                                        IMX_PKE_DISABLE,
+                                        IMX_PUE_KEEP,
+                                        IMX_PUS_100K_OHM_PD,
+                                        IMX_HYS_DISABLED,
+                                        IMX_SION_DISABLED,
+                                        IMX_IOMUXC_ENET_REF_CLK_ALT1_ENET_TX_CLK),
+
+  IMX_PAD_RGMII_RXC_ENET_RGMII_RXC = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_DISABLE,
+                                       IMX_PUE_KEEP,
+                                       IMX_PUS_100K_OHM_PU,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_RGMII_RXC_ALT1_RGMII_RXC),
+
+  IMX_PAD_RGMII_RD0_ENET_RGMII_RD0 = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_DISABLE,
+                                       IMX_PUE_KEEP,
+                                       IMX_PUS_100K_OHM_PD,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_RGMII_RD0_ALT1_RGMII_RD0),
+
+  IMX_PAD_RGMII_RD1_ENET_RGMII_RD1 = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_DISABLE,
+                                       IMX_PUE_KEEP,
+                                       IMX_PUS_100K_OHM_PD,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_RGMII_RD1_ALT1_RGMII_RD1),
+
+  IMX_PAD_RGMII_RD2_ENET_RGMII_RD2 = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_DISABLE,
+                                       IMX_PUE_KEEP,
+                                       IMX_PUS_100K_OHM_PU,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_RGMII_RD2_ALT1_RGMII_RD2),
+
+  IMX_PAD_RGMII_RD3_ENET_RGMII_RD3 = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_DISABLE,
+                                       IMX_PUE_KEEP,
+                                       IMX_PUS_100K_OHM_PU,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_RGMII_RD3_ALT1_RGMII_RD3),
+
+  IMX_PAD_RGMII_RX_CTL_RGMII_RX_CTL = _IMX_MAKE_PADCFG (
+                                        IMX_SRE_SLOW,
+                                        IMX_DSE_40_OHM,
+                                        IMX_SPEED_MEDIUM,
+                                        IMX_ODE_DISABLE,
+                                        IMX_PKE_DISABLE,
+                                        IMX_PUE_KEEP,
+                                        IMX_PUS_100K_OHM_PD,
+                                        IMX_HYS_ENABLED,
+                                        IMX_SION_DISABLED,
+                                        IMX_IOMUXC_RGMII_RX_CTL_ALT1_RGMII_RX_CTL),
+} IMX_ENET_PADCFG;
+
+typedef enum {
+  IMX_PAD_CFG_EIM_DATA22_GPIO3_IO22_USB_OTG_PWR = _IMX_MAKE_PADCFG (
+                                                    IMX_SRE_SLOW,
+                                                    IMX_DSE_40_OHM,
+                                                    IMX_SPEED_MEDIUM,
+                                                    IMX_ODE_DISABLE,
+                                                    IMX_PKE_ENABLE,
+                                                    IMX_PUE_PULL,
+                                                    IMX_PUS_100K_OHM_PU,
+                                                    IMX_HYS_ENABLED,
+                                                    IMX_SION_DISABLED,
+                                                    IMX_IOMUXC_EIM_D22_ALT5_GPIO3_IO22),
+
+  IMX_PAD_CFG_KEY_COL4_USB_OTG_OC = _IMX_MAKE_PADCFG_INPSEL (
+                                      IMX_SRE_SLOW,
+                                      IMX_DSE_40_OHM,
+                                      IMX_SPEED_LOW,
+                                      IMX_ODE_DISABLE,
+                                      IMX_PKE_ENABLE,
+                                      IMX_PUE_PULL,
+                                      IMX_PUS_100K_OHM_PU,
+                                      IMX_HYS_ENABLED,
+                                      IMX_SION_DISABLED,
+                                      IMX_IOMUXC_KEY_COL4_ALT2_USB_OTG_OC,
+                                      IOMUXC_USB_OTG_OC_SELECT_INPUT,
+                                      KEY_COL4_ALT2),
+
+  IMX_PAD_CFG_GPIO0_GPIO1_IO0_USBH1_PWR = _IMX_MAKE_PADCFG (
+                                            IMX_SRE_SLOW,
+                                            IMX_DSE_40_OHM,
+                                            IMX_SPEED_MEDIUM,
+                                            IMX_ODE_DISABLE,
+                                            IMX_PKE_ENABLE,
+                                            IMX_PUE_PULL,
+                                            IMX_PUS_100K_OHM_PU,
+                                            IMX_HYS_ENABLED,
+                                            IMX_SION_DISABLED,
+                                            IMX_IOMUXC_GPIO_0_ALT5_GPIO1_IO00),
+
+  IMX_PAD_CFG_GPIO01_USB_OTG_ID_HOST = _IMX_MAKE_PADCFG (
+                                         IMX_SRE_FAST,
+                                         IMX_DSE_90_OHM,
+                                         IMX_SPEED_MEDIUM,
+                                         IMX_ODE_DISABLE,
+                                         IMX_PKE_ENABLE,
+                                         IMX_PUE_PULL,
+                                         IMX_PUS_100K_OHM_PD,
+                                         IMX_HYS_ENABLED,
+                                         IMX_SION_DISABLED,
+                                         IMX_IOMUXC_GPIO_1_ALT3_USB_OTG_ID),
+
+  IMX_PAD_CFG_GPIO01_USB_OTG_ID_DEVICE = _IMX_MAKE_PADCFG (
+                                           IMX_SRE_FAST,
+                                           IMX_DSE_90_OHM,
+                                           IMX_SPEED_MEDIUM,
+                                           IMX_ODE_DISABLE,
+                                           IMX_PKE_ENABLE,
+                                           IMX_PUE_PULL,
+                                           IMX_PUS_100K_OHM_PU,
+                                           IMX_HYS_ENABLED,
+                                           IMX_SION_DISABLED,
+                                           IMX_IOMUXC_GPIO_1_ALT3_USB_OTG_ID),
+} IMX_EHCI_PADCFG;
+
+typedef enum {
+  IMX_PAD_CFG_SD4_DATA3_GPIO2_IO11 = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_ENABLE,
+                                       IMX_PUE_PULL,
+                                       IMX_PUS_100K_OHM_PU,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_SD4_DAT3_ALT5_GPIO2_IO11),
+} IMX_IMX6Q_PCIE_PADCFG;
+
+typedef enum {
+  IMX_PAD_CFG_EIM_EB3_GPIO2_IO31 = _IMX_MAKE_PADCFG (
+                                     IMX_SRE_SLOW,
+                                     IMX_DSE_260_OHM,
+                                     IMX_SPEED_LOW,
+                                     IMX_ODE_DISABLE,
+                                     IMX_PKE_DISABLE,
+                                     IMX_PUE_PULL,
+                                     IMX_PUS_100K_OHM_PU,
+                                     IMX_HYS_DISABLED,
+                                     IMX_SION_ENABLED,
+                                     IMX_IOMUXC_EIM_EB3_ALT5_GPIO2_IO31),
+
+  IMX_PAD_CFG_EIM_D21_I2C1_SCL = _IMX_MAKE_PADCFG_INPSEL (
+                                   IMX_SRE_FAST,
+                                   IMX_DSE_40_OHM,
+                                   IMX_SPEED_MEDIUM,
+                                   IMX_ODE_ENABLE,
+                                   IMX_PKE_ENABLE,
+                                   IMX_PUE_PULL,
+                                   IMX_PUS_47K_OHM_PU,
+                                   IMX_HYS_ENABLED,
+                                   IMX_SION_ENABLED,
+                                   IMX_IOMUXC_EIM_D21_ALT6_I2C1_SCL,
+                                   IOMUXC_I2C1_SCL_IN_SELECT_INPUT,
+                                   EIM_DATA21_ALT6),
+
+  IMX_PAD_CFG_EIM_D28_I2C1_SDA = _IMX_MAKE_PADCFG_INPSEL (
+                                   IMX_SRE_FAST,
+                                   IMX_DSE_40_OHM,
+                                   IMX_SPEED_MEDIUM,
+                                   IMX_ODE_ENABLE,
+                                   IMX_PKE_ENABLE,
+                                   IMX_PUE_PULL,
+                                   IMX_PUS_47K_OHM_PU,
+                                   IMX_HYS_ENABLED,
+                                   IMX_SION_ENABLED,
+                                   IMX_IOMUXC_EIM_D28_ALT1_I2C1_SDA,
+                                   IOMUXC_I2C1_SDA_IN_SELECT_INPUT,
+                                   EIM_DATA28_ALT1),
+
+  IMX_PAD_CFG_EIM_D17_I2C3_SCL = _IMX_MAKE_PADCFG_INPSEL (
+                                   IMX_SRE_FAST,
+                                   IMX_DSE_40_OHM,
+                                   IMX_SPEED_MEDIUM,
+                                   IMX_ODE_ENABLE,
+                                   IMX_PKE_ENABLE,
+                                   IMX_PUE_PULL,
+                                   IMX_PUS_47K_OHM_PU,
+                                   IMX_HYS_ENABLED,
+                                   IMX_SION_ENABLED,
+                                   IMX_IOMUXC_EIM_D17_ALT6_I2C3_SCL,
+                                   IOMUXC_I2C3_SCL_IN_SELECT_INPUT,
+                                   EIM_DATA17_ALT6),
+
+  IMX_PAD_CFG_EIM_D18_I2C3_SDA = _IMX_MAKE_PADCFG_INPSEL (
+                                   IMX_SRE_FAST,
+                                   IMX_DSE_40_OHM,
+                                   IMX_SPEED_MEDIUM,
+                                   IMX_ODE_ENABLE,
+                                   IMX_PKE_ENABLE,
+                                   IMX_PUE_PULL,
+                                   IMX_PUS_47K_OHM_PU,
+                                   IMX_HYS_ENABLED,
+                                   IMX_SION_ENABLED,
+                                   IMX_IOMUXC_EIM_D18_ALT6_I2C3_SDA,
+                                   IOMUXC_I2C3_SDA_IN_SELECT_INPUT,
+                                   EIM_DATA18_ALT6),
+} IMX_I2C_PADCFG;
+
+typedef enum {
+  IMX_PAD_CFG_GPIO_5_CCM_CLKO1 = _IMX_MAKE_PADCFG (
+                                   IMX_SRE_SLOW,
+                                   IMX_DSE_40_OHM,
+                                   IMX_SPEED_MEDIUM,
+                                   IMX_ODE_DISABLE,
+                                   IMX_PKE_ENABLE,
+                                   IMX_PUE_PULL,
+                                   IMX_PUS_100K_OHM_PU,
+                                   IMX_HYS_ENABLED,
+                                   IMX_SION_DISABLED,
+                                   IMX_IOMUXC_GPIO_5_ALT3_CCM_CLKO1),
+
+  IMX_PAD_CFG_KEY_COL0_AUD5_TXC = _IMX_MAKE_PADCFG_INPSEL (
+                                    IMX_SRE_SLOW,
+                                    IMX_DSE_40_OHM,
+                                    IMX_SPEED_MEDIUM,
+                                    IMX_ODE_DISABLE,
+                                    IMX_PKE_ENABLE,
+                                    IMX_PUE_PULL,
+                                    IMX_PUS_100K_OHM_PU,
+                                    IMX_HYS_ENABLED,
+                                    IMX_SION_DISABLED,
+                                    IMX_IOMUXC_KEY_COL0_ALT2_AUD5_TXC,
+                                    IOMUXC_AUD5_INPUT_TXCLK_AMX_SELECT_INPUT,
+                                    KEY_COL0_ALT2),
+
+  IMX_PAD_CFG_KEY_ROW0_AUD5_TXD = _IMX_MAKE_PADCFG_INPSEL (
+                                    IMX_SRE_SLOW,
+                                    IMX_DSE_40_OHM,
+                                    IMX_SPEED_MEDIUM,
+                                    IMX_ODE_DISABLE,
+                                    IMX_PKE_ENABLE,
+                                    IMX_PUE_PULL,
+                                    IMX_PUS_100K_OHM_PU,
+                                    IMX_HYS_ENABLED,
+                                    IMX_SION_DISABLED,
+                                    IMX_IOMUXC_KEY_ROW0_ALT2_AUD5_TXD,
+                                    IOMUXC_AUD5_INPUT_DB_AMX_SELECT_INPUT,
+                                    KEY_ROW0_ALT2),
+
+  IMX_PAD_CFG_KEY_COL1_AUD5_TXFS = _IMX_MAKE_PADCFG_INPSEL (
+                                     IMX_SRE_SLOW,
+                                     IMX_DSE_40_OHM,
+                                     IMX_SPEED_MEDIUM,
+                                     IMX_ODE_DISABLE,
+                                     IMX_PKE_ENABLE,
+                                     IMX_PUE_PULL,
+                                     IMX_PUS_100K_OHM_PU,
+                                     IMX_HYS_ENABLED,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_KEY_COL1_ALT2_AUD5_TXFS,
+                                     IOMUXC_AUD5_INPUT_TXFS_AMX_SELECT_INPUT,
+                                     KEY_COL1_ALT2),
+
+  IMX_PAD_CFG_DISP0_DAT19_AUD5_RXD = _IMX_MAKE_PADCFG_INPSEL (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_ENABLE,
+                                       IMX_PUE_PULL,
+                                       IMX_PUS_100K_OHM_PU,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_DISP0_DAT19_ALT3_AUD5_RXD,
+                                       IOMUXC_AUD5_INPUT_DA_AMX_SELECT_INPUT,
+                                       DISP0_DATA19_ALT3),
+} IMX_AUDIO_PADCFG;
+
+typedef enum {
+  IMX_USDHC_CMD_PAD_CTL = _IMX_MAKE_PAD_CTL (
+                            IMX_SRE_FAST,
+                            IMX_DSE_33_OHM,
+                            IMX_SPEED_MEDIUM,
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_ENABLE,
+                            IMX_PUE_PULL,
+                            IMX_PUS_47K_OHM_PU,
+                            IMX_HYS_ENABLED),
+
+  IMX_USDHC_CLK_PAD_CTL = _IMX_MAKE_PAD_CTL (
+                            IMX_SRE_FAST,
+                            IMX_DSE_33_OHM,
+                            IMX_SPEED_MEDIUM,
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_DISABLE,
+                            0,
+                            0,
+                            IMX_HYS_ENABLED),
+
+  IMX_USDHC_DAT_PAD_CTL = _IMX_MAKE_PAD_CTL (
+                            IMX_SRE_FAST,
+                            IMX_DSE_33_OHM,
+                            IMX_SPEED_MEDIUM,
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_ENABLE,
+                            IMX_PUE_PULL,
+                            IMX_PUS_47K_OHM_PU,
+                            IMX_HYS_ENABLED),
+
+  IMX_USDHC_GPIO_PAD_CTL = _IMX_MAKE_PAD_CTL (
+                             IMX_SRE_FAST,
+                             IMX_DSE_33_OHM,
+                             IMX_SPEED_LOW,
+                             IMX_ODE_DISABLE,
+                             IMX_PKE_DISABLE,
+                             0,
+                             0,
+                             IMX_HYS_ENABLED),
+
+  IMX_USDHC_CD_PAD_CTL = _IMX_MAKE_PAD_CTL (
+                           IMX_SRE_FAST,
+                           IMX_DSE_33_OHM,
+                           IMX_SPEED_LOW,
+                           IMX_ODE_DISABLE,
+                           IMX_PKE_ENABLE,
+                           IMX_PUE_PULL,
+                           IMX_PUS_47K_OHM_PU,
+                           IMX_HYS_ENABLED),
+
+  IMX_PAD_CFG_SD2_CLK_SD2_CLK = _IMX_MAKE_PADCFG2 (
+                                  IMX_USDHC_CLK_PAD_CTL,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_SD2_CLK_ALT0_SD2_CLK),
+
+  IMX_PAD_CFG_SD2_CMD_SD2_CMD = _IMX_MAKE_PADCFG2 (
+                                  IMX_USDHC_CMD_PAD_CTL,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_SD2_CMD_ALT0_SD2_CMD),
+
+  IMX_PAD_CFG_SD2_DAT0_SD2_DATA0 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD2_DAT0_ALT0_SD2_DATA0),
+
+  IMX_PAD_CFG_SD2_DAT1_SD2_DATA1 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD2_DAT1_ALT0_SD2_DATA1),
+
+  IMX_PAD_CFG_SD2_DAT2_SD2_DATA2 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD2_DAT2_ALT0_SD2_DATA2),
+
+  IMX_PAD_CFG_SD2_DAT3_SD2_DATA3 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD2_DAT3_ALT0_SD2_DATA3),
+
+  IMX_PAD_CFG_KEY_ROW1_SD2_VSELECT = _IMX_MAKE_PADCFG2 (
+                                       IMX_USDHC_GPIO_PAD_CTL,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_KEY_ROW1_ALT6_SD2_VSELECT),
+
+  IMX_PAD_CFG_GPIO_4_SD2_CD_B = _IMX_MAKE_PADCFG2 (
+                                  IMX_USDHC_CD_PAD_CTL,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_GPIO_4_ALT6_SD2_CD_B),
+
+  IMX_PAD_CFG_DISP0_DAT9_GPIO4_IO30 = _IMX_MAKE_PADCFG2 (
+                                        IMX_USDHC_GPIO_PAD_CTL,
+                                        IMX_SION_DISABLED,
+                                        IMX_IOMUXC_DISP0_DAT9_ALT5_GPIO4_IO30),
+} IMX_USDHC2_PADCFG;
+
+typedef enum {
+  IMX_PAD_CFG_SD3_CLK_SD3_CLK = _IMX_MAKE_PADCFG2 (
+                                  IMX_USDHC_CLK_PAD_CTL,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_SD3_CLK_ALT0_SD3_CLK),
+
+  IMX_PAD_CFG_SD3_CMD_SD3_CMD = _IMX_MAKE_PADCFG2 (
+                                  IMX_USDHC_CMD_PAD_CTL,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_SD3_CMD_ALT0_SD3_CMD),
+
+  IMX_PAD_CFG_SD3_RST_SD3_RST = _IMX_MAKE_PADCFG2 (
+                                  IMX_USDHC_GPIO_PAD_CTL,
+                                  IMX_SION_DISABLED,
+                                  IMX_IOMUXC_SD3_RST_ALT0_SD3_RESET),
+
+  IMX_PAD_CFG_SD3_DAT0_SD3_DATA0 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT0_ALT0_SD3_DATA0),
+
+  IMX_PAD_CFG_SD3_DAT1_SD3_DATA1 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT1_ALT0_SD3_DATA1),
+
+  IMX_PAD_CFG_SD3_DAT2_SD3_DATA2 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT2_ALT0_SD3_DATA2),
+
+  IMX_PAD_CFG_SD3_DAT3_SD3_DATA3 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT3_ALT0_SD3_DATA3),
+
+  IMX_PAD_CFG_SD3_DAT4_SD3_DATA4 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT4_ALT0_SD3_DATA4),
+
+  IMX_PAD_CFG_SD3_DAT5_SD3_DATA5 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT5_ALT0_SD3_DATA5),
+
+  IMX_PAD_CFG_SD3_DAT6_SD3_DATA6 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT6_ALT0_SD3_DATA6),
+
+  IMX_PAD_CFG_SD3_DAT7_SD3_DATA7 = _IMX_MAKE_PADCFG2 (
+                                     IMX_USDHC_DAT_PAD_CTL,
+                                     IMX_SION_DISABLED,
+                                     IMX_IOMUXC_SD3_DAT7_ALT0_SD3_DATA7),
+} IMX_USDHC3_PADCFG;
+
+typedef enum {
+  IMX_PWM_CLK_PAD_CTL = _IMX_MAKE_PAD_CTL (
+                          IMX_SRE_FAST,
+                          IMX_DSE_33_OHM,
+                          IMX_SPEED_LOW,
+                          IMX_ODE_DISABLE,
+                          IMX_PKE_DISABLE,
+                          0,
+                          0,
+                          IMX_HYS_ENABLED),
+
+  IMX_PAD_CFG_DISP0_DAT8_PWM1_OUT = _IMX_MAKE_PADCFG2 (
+                                      IMX_PWM_CLK_PAD_CTL,
+                                      IMX_SION_DISABLED,
+                                      IMX_IOMUXC_DISP0_DAT8_ALT2_PWM1_OUT),
+} IMX_PWM_PADCFG;
+
+typedef enum {
+  IMX_PAD_UART1_RX_DATA = _IMX_MAKE_PADCFG_INPSEL (
+                            IMX_SRE_SLOW,
+                            IMX_DSE_40_OHM,     // 25 Ohm @ 3.3V, 40 Ohm @ 1.8V
+                            IMX_SPEED_MEDIUM,   // 10 MEDIUM - 100, 150 MHz
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_ENABLE,       // 12 Pull/Keeper Enabled
+                            IMX_PUE_PULL,         // 13 Pull Enabled
+                            IMX_PUS_100K_OHM_PU,  // 14-15 100K Ohm Pull Up
+                            IMX_HYS_ENABLED,
+                            IMX_SION_DISABLED,
+                            IMX_IOMUXC_CSI0_DAT11_ALT3_UART1_RX_DATA,
+                            IOMUXC_UART1_UART_RX_DATA_SELECT_INPUT,
+                            CSI0_DATA11_ALT3),
+
+  IMX_PAD_UART1_TX_DATA = _IMX_MAKE_PADCFG (
+                            IMX_SRE_SLOW,
+                            IMX_DSE_40_OHM,
+                            IMX_SPEED_MEDIUM,
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_ENABLE,
+                            IMX_PUE_PULL,
+                            IMX_PUS_100K_OHM_PU,
+                            IMX_HYS_ENABLED,
+                            IMX_SION_DISABLED,
+                            IMX_IOMUXC_CSI0_DAT10_ALT3_UART1_TX_DATA),
+
+  IMX_PAD_UART3_RX_DATA = _IMX_MAKE_PADCFG_INPSEL (
+                            IMX_SRE_SLOW,
+                            IMX_DSE_40_OHM,
+                            IMX_SPEED_MEDIUM,
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_ENABLE,
+                            IMX_PUE_PULL,
+                            IMX_PUS_100K_OHM_PU,
+                            IMX_HYS_ENABLED,
+                            IMX_SION_DISABLED,
+                            IMX_IOMUXC_EIM_D25_ALT2_UART3_RX_DATA,
+                            IOMUXC_UART3_UART_RX_DATA_SELECT_INPUT,
+                            EIM_DATA25_ALT2),
+
+  IMX_PAD_UART3_TX_DATA = _IMX_MAKE_PADCFG (
+                            IMX_SRE_SLOW,
+                            IMX_DSE_40_OHM,
+                            IMX_SPEED_MEDIUM,
+                            IMX_ODE_DISABLE,
+                            IMX_PKE_ENABLE,
+                            IMX_PUE_PULL,
+                            IMX_PUS_100K_OHM_PU,
+                            IMX_HYS_ENABLED,
+                            IMX_SION_DISABLED,
+                            IMX_IOMUXC_EIM_D24_ALT2_UART3_TX_DATA),
+} IMX_UART_PADCFG;
+
+typedef enum {
+  IMX_PAD_CFG_SD4_DATA1_GPIO2_IO09 = _IMX_MAKE_PADCFG (
+                                       IMX_SRE_SLOW,
+                                       IMX_DSE_40_OHM,
+                                       IMX_SPEED_MEDIUM,
+                                       IMX_ODE_DISABLE,
+                                       IMX_PKE_ENABLE,
+                                       IMX_PUE_PULL,
+                                       IMX_PUS_100K_OHM_PU,
+                                       IMX_HYS_ENABLED,
+                                       IMX_SION_DISABLED,
+                                       IMX_IOMUXC_SD4_DAT1_ALT5_GPIO2_IO09),
+
+} IMX_IMX6Q_LDB_PADCFG;
+
+#endif /* _IMX6_BOARD_INIT_H_ */
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
new file mode 100644
index 000000000000..687b9a59930d
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
@@ -0,0 +1,91 @@
+#/* @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = iMX6BoardLib
+  FILE_GUID                      = 736343a0-1d96-11e0-aaaa-0002a5d5c51b
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformLib
+  DEFINE BOARD_LIB_COMMON_DIR    = Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  iMX6ClkPwrLib
+  iMX6UsbPhyLib
+  IoLib
+  MemoryAllocationLib
+  SerialPortLib
+
+[Sources.common]
+  $(BOARD_LIB_COMMON_DIR)/iMX6BoardHelper.S    | GCC
+  $(BOARD_LIB_COMMON_DIR)/iMX6BoardMem.c
+  $(BOARD_LIB_COMMON_DIR)/iMX6QBoardCoreDef.c
+  iMX6BoardInit.c
+
+[FeaturePcd]
+  giMX6TokenSpaceGuid.PcdGpuEnable
+  giMX6TokenSpaceGuid.PcdLvdsEnable
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFdSize
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+  giMX6TokenSpaceGuid.PcdFrameBufferBase
+  giMX6TokenSpaceGuid.PcdFrameBufferSize
+  giMX6TokenSpaceGuid.PcdSrcBase
+
+  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
+
+  #
+  # TPM2 control area
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize
+
+  #
+  # TrustZone private memory
+  # This memory is managed privately by the OpTEE OS.
+  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
+  #    CFG_DDR_TEETZ_RESERVED_START & CFG_DDR_TEETZ_RESERVED_START
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize
+
+  #
+  # TrustZone shared memory
+  # This memory is manager by the normal world but shared with the OpTEE OS.
+  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
+  #    CFG_SHMEM_START & CFG_SHMEM_SIZE
+  #
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase
+  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 26/27] Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (24 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 25/27] Platform/Solidrun: Add Hummingboard Peripheral Initialization Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-15 12:19   ` Leif Lindholm
  2018-09-21  8:26 ` [PATCH edk2-platforms 27/27] Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files Chris Co
  2018-12-15 13:32 ` [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Leif Lindholm
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Michael D Kinney, Ard Biesheuvel, Leif Lindholm

This adds ACPI table support for SolidRun's i.MX 6Quad Hummingboard Edge
platform.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
---
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf      |  55 ++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl            |  38 +++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl      |  71 ++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl |  33 ++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl        |  54 +++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl        |  32 ++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl        | 234 +++++++++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl       | 144 ++++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl        |  43 +++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl       | 198 +++++++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl        | 343 ++++++++++++++++++++
 11 files changed, 1245 insertions(+)

diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
new file mode 100644
index 000000000000..2386c60d211d
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
@@ -0,0 +1,55 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = PlatformAcpiTables
+  FILE_GUID                      = 7E374E25-8E01-4FEE-87F2-390C23C606CD
+  MODULE_TYPE                    = USER_DEFINED
+  VERSION_STRING                 = 1.0
+  DEFINE COMMON_ACPI_DIR         = Silicon/NXP/iMX6Pkg/AcpiTables
+
+[Sources]
+  DSDT.asl
+  $(COMMON_ACPI_DIR)/Csrt.aslc
+  $(COMMON_ACPI_DIR)/Dbg2.aslc
+  $(COMMON_ACPI_DIR)/Fadt.aslc
+  $(COMMON_ACPI_DIR)/Madt.aslc
+  $(COMMON_ACPI_DIR)/Mcfg.aslc
+  $(COMMON_ACPI_DIR)/Tpm2.aslc
+  $(COMMON_ACPI_DIR)/Spcr.aslc
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
+  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+  gArmTokenSpaceGuid.PcdGicDistributorBase
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+
+  giMX6TokenSpaceGuid.PcdPcieDeviceConfigBase
+  giMX6TokenSpaceGuid.PcdPcieHostConfigBase
+
+  giMXPlatformTokenSpaceGuid.PcdKdUartInstance
+
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase
+  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
new file mode 100644
index 000000000000..6e639bb838a6
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
@@ -0,0 +1,38 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "Dsdt-Common.h"
+
+#define SOC_TYPE 0x00000063  // iMX6 Quad
+
+DefinitionBlock ("DSDT.aml", "DSDT", 5, "MSFT", "EDK2", 1)
+{
+  Scope (\_SB_) {
+    include ("Dsdt-Platform.asl")
+    include ("Dsdt-Gpio.asl")
+    include ("Dsdt-Gfx.asl")
+    include ("Dsdt-Usb.asl")
+    include ("Dsdt-PCIe.asl")
+    include ("Dsdt-Sdhc.asl")
+    include ("Dsdt-Enet.asl")
+    include ("Dsdt-Audio.asl")
+    include ("Dsdt-AudioCodec.asl")
+    include ("Dsdt-Uart.asl")
+    include ("Dsdt-I2c.asl")
+    include ("Dsdt-Spi.asl")
+    include ("Dsdt-Rhp.asl")
+    include ("Dsdt-Pwm.asl")
+    include ("Dsdt-TrEE.asl")
+  } // \_SB_
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
new file mode 100644
index 000000000000..23fbf5f52677
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
@@ -0,0 +1,71 @@
+/** @file
+*
+*  iMX6 Quad Synchronous Serial Interface (SSI)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (SSI1)
+{
+  Name (_HID, "NXP010A")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02028000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 78 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (SSI2)
+{
+  Name (_HID, "NXP010A")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x0202C000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 79 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (SSI3)
+{
+  Name (_HID, "NXP010A")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02030000, 0x4000, )
+      MEMORY32FIXED (ReadWrite, 0x021d8000, 0x38, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 80 }
+      MsftFunctionConfig (Shared, PullDown, 0, "\\_SB.SSI3", 0, ResourceConsumer, ) { 7, 5 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
new file mode 100644
index 000000000000..8ab9bece73d7
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
@@ -0,0 +1,33 @@
+/** @file
+*
+*  iMX6 Quad Freescale SGTL5000 audio codec
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (ACDK)
+{
+  Name (_HID, "SGTL5000")
+  Name (_UID, 0x0)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      I2CSerialBus (0x0a, ControllerInitiated, 400000, AddressingMode7Bit,
+                    "\\_SB.I2C1", 0, ResourceConsumer)
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
new file mode 100644
index 000000000000..7e1d0cc2c9ab
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
@@ -0,0 +1,54 @@
+/** @file
+*
+*  iMX6 Quad I2C Controllers
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (I2C1)
+{
+  Name (_HID, "NXP0104")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
+    })
+    Return (RBUF)
+  }
+}
+
+// Device (I2C2)
+// do not include I2C2 resources since it is pin muxed to HDMI
+
+Device (I2C3)
+{
+  Name (_HID, "NXP0104")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
new file mode 100644
index 000000000000..59565c576a71
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
@@ -0,0 +1,32 @@
+/** @file
+*  iMX6 Quad Pulse Width Modulator (PWM)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (PWM1)
+{
+  Name (_HID, "NXP010E")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
new file mode 100644
index 000000000000..be5048fe3963
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
@@ -0,0 +1,234 @@
+/** @file
+*
+*  iMX6 Quad Resource Hub Proxy
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (RHPX)
+{
+  Name (_HID, "MSFT8000")
+  Name (_CID, "MSFT8000")
+  Name (_UID, 1)
+
+  Name (_CRS, ResourceTemplate() {
+    // Index 0
+    I2CSerialBus (0xFFFF,, 0,, "\\_SB.I2C3",,,,)
+
+    // Index 1
+    SPISerialBus (             // SCKL
+      // MOSI
+      // MISO
+      // CE0
+      0,                      // Device selection (CE0)
+      PolarityLow,            // Device selection polarity
+      FourWireMode,           // wiremode
+      8,                      // databit len
+      ControllerInitiated,    // slave mode
+      4000000,                // connection speed
+      ClockPolarityLow,       // clock polarity
+      ClockPhaseFirst,        // clock phase
+      "\\_SB.SPI2",           // ResourceSource: SPI bus controller name
+      0,                      // ResourceSourceIndex
+                              // Resource usage
+                              // DescriptorName: creates name for
+                              //   offset of resource descriptor
+    )                         // Vendor Data
+
+    // SPDIF_IN - GPIO1_IO24 PAD_ENET_RX_ER
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 24 } // 0 * 32 + 24
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 24 }
+
+    // DISP1_DATA17 - GPIO2_IO16 PAD_EIM_ADDR22
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 48 } // 1 * 32 + 16
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 48 }
+
+    // DISP1_DATA16 - GPIO2_IO17 PAD_EIM_ADDR21
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 49 } // 1 * 32 + 17
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 49 }
+
+    // DISP1_DATA15 - GPIO2_IO18 PAD_EIM_ADDR20
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 50 } // 1 * 32 + 18
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 50 }
+
+    // DISP1_DATA14 - GPIO2_IO19 PAD_EIM_ADDR19
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 51 } // 1 * 32 + 19
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 51 }
+
+    // DISP1_DATA13 - GPIO2_IO20 PAD_EIM_ADDR18
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 52 } // 1 * 32 + 20
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 52 }
+
+    // DISP1_DATA12 - GPIO2_IO21 PAD_EIM_ADDR17
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 53 } // 1 * 32 + 21
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 53 }
+
+    // DI1_DISP_CLK - GPIO2_IO22 PAD_EIM_ADDR16
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 54 } // 1 * 32 + 22
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 54 }
+
+    // DISP1_DATA11 - GPIO2_IO28 PAD_EIM_EB0
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 60 } // 1 * 32 + 28
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 60 }
+
+    // DISP1_DATA10 - GPIO2_IO29 PAD_EIM_EB1
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 61 } // 1 * 32 + 29
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 61 }
+
+    // DISP1_DATA09 - GPIO3_IO00 PAD_EIM_AD00
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 64 } // 2 * 32 + 0
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 64 }
+
+    // DISP1_DATA08 - GPIO3_IO01 PAD_EIM_AD01
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 65 } // 2 * 32 + 1
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 65 }
+
+    // DISP1_DATA07 - GPIO3_IO02 PAD_EIM_AD02
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 66 } // 2 * 32 + 2
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 66 }
+
+    // DISP1_DATA06 - GPIO3_IO03 PAD_EIM_AD03
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 67 } // 2 * 32 + 3
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 67 }
+
+    // DISP1_DATA05 - GPIO3_IO04 PAD_EIM_AD04
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 68 } // 2 * 32 + 4
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 68 }
+
+    // DISP1_DATA04 - GPIO3_IO05 PAD_EIM_AD05
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 69 } // 2 * 32 + 5
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 69 }
+
+    // DISP1_DATA03 - GPIO3_IO06 PAD_EIM_AD06
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 70 } // 2 * 32 + 6
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 70 }
+
+    // DISP1_DATA02 - GPIO3_IO07 PAD_EIM_AD07
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 71 } // 2 * 32 + 7
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 71 }
+
+    // DISP1_DATA01 - GPIO3_IO08 PAD_EIM_AD08
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 72 } // 2 * 32 + 8
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 72 }
+
+    // DISP1_DATA00 - GPIO3_IO09 PAD_EIM_AD09
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 73 } // 2 * 32 + 9
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 73 }
+
+    // DI1_PIN15 - GPIO3_IO10 PAD_EIM_AD10
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 74 } // 2 * 32 + 10
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 74 }
+
+    // DI1_PIN02 - GPIO3_IO11 PAD_EIM_AD11
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 75 } // 2 * 32 + 11
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 75 }
+
+    // DI1_PIN03 - GPIO3_IO12 PAD_EIM_AD12
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 76 } // 2 * 32 + 12
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 76 }
+
+    // DI1_D0_CS - GPIO3_IO13 PAD_EIM_AD13
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 77 } // 2 * 32 + 13
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 77 }
+
+    // DI1_D1_CS - GPIO3_IO14 PAD_EIM_AD14
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 78 } // 2 * 32 + 14
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 78 }
+
+    // DI1_PIN01 - GPIO3_IO15 PAD_EIM_AD15
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 79 } // 2 * 32 + 15
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 79 }
+
+    // DISP1_DATA22 - GPIO3_IO26 PAD_EIM_DATA26
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 90 } // 2 * 32 + 26
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 90 }
+
+    // DISP1_DATA23 - GPIO3_IO27 PAD_EIM_DATA27
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 91 } // 2 * 32 + 27
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 91 }
+
+    // DISP1_DATA21 - GPIO3_IO30 PAD_EIM_DATA30
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 94 } // 2 * 32 + 20
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 94 }
+
+    // DISP1_DATA20 - GPIO3_IO31 PAD_EIM_DATA31
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 95 } // 2 * 32 + 31
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 95 }
+
+    // DISP1_DATA19 - GPIO5_IO04 PAD_EIM_ADDR24
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 132 } // 4 * 32 + 4
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 132 }
+
+    // DISP1_DATA18 - GPIO6_IO06 PAD_EIM_ADDR23
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 166 } // 5 * 32 + 6
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 166 }
+
+    // SPDIF_OUT - GPIO7_IO12 PAD_GPIO17
+    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,, ) { 204 } // 6 * 32 + 12
+    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 204 }
+  })
+
+  Name (_DSD, Package() {
+    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+    Package() {
+      // I2C3
+      Package (2) { "bus-I2C-I2C3", Package() { 0 } },
+
+      // SPI 2
+      Package (2) { "bus-SPI-SPI2", Package() { 1 } }, // Index 1
+      Package (2) { "SPI2-MinClockInHz", 115 },        // 115 Hz
+      Package (2) { "SPI2-MaxClockInHz", 12000000 },   // 12 MHz
+      // Data bit length
+      Package (2) { "SPI2-SupportedDataBitLengths", Package() { 8, 16, 32 } },
+
+      // GPIO Pin Count and supported drive modes
+      Package (2) { "GPIO-PinCount", 206 },
+      Package (2) { "GPIO-UseDescriptorPinNumbers", 1 },
+
+      // InputHighImpedance, InputPullUp, InputPullDown, OutputCmos
+      Package (2) { "GPIO-SupportedDriveModes", 0xf },
+    }
+  })
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
new file mode 100644
index 000000000000..d3f275d21473
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
@@ -0,0 +1,144 @@
+/** @file
+*
+*  iMX6 Quad Ultra Secured Digital Host Controllers (uSDHC)
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+// uSDHC1: WLAN SDIO Socket
+Device (SDH1)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x1)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Name (_S1D, 0x1)
+  Name (_S2D, 0x1)
+  Name (_S3D, 0x1)
+  Name (_S4D, 0x1)
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
+    })
+    Return (RBUF)
+  }
+
+  Device (SD0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+
+  Device (TIWL)
+  {
+    Name (_ADR, 0)
+    // TODO: We must replace these HID and CID values with valid ones
+    Name (_HID, "TI_WLAN")
+    Name (_CID, "TI_WLAN")
+    Name (_UID, 1)
+
+    Method (_STA) {
+      Return(0xf)
+    }
+
+    Method (_CRS, 0x0, NotSerialized) {
+      Name (RBUF, ResourceTemplate () {
+        GpioInt(Edge, ActiveHigh, Exclusive, PullNone, 0, "\\_SB.GPIO", 0,
+                ResourceConsumer,,) { 164 } // WLAN_EN
+        GpioIo(Exclusive, PullNone, 0, 2, IoRestrictionOutputOnly,
+                "\\_SB.GPIO",0, ResourceConsumer,,) { 154 }
+      })
+      Return (RBUF)
+    }
+  }
+}
+
+// uSDHC2: SDCard Socket
+Device (SDH2)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x2)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Name (_S1D, 0x1)
+  Name (_S2D, 0x1)
+  Name (_S3D, 0x1)
+  Name (_S4D, 0x1)
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
+    })
+    Return (RBUF)
+  }
+
+  Device (SD0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    // Despite the SDCard is a removal device, UWF requires the
+    // boot device to be non-removable. This is required for the
+    // Windows SDCard boot scenario with UWF enabled.
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+}
+
+// uSDHC3: eMMC
+Device (SDH3)
+{
+  Name (_HID, "NXP0108")
+  Name (_UID, 0x3)
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Name (_S1D, 0x1)
+  Name (_S2D, 0x1)
+  Name (_S3D, 0x1)
+  Name (_S4D, 0x1)
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
+    })
+    Return (RBUF)
+  }
+
+  Device (MMC0) {
+    Method (_ADR) {
+      Return (0)
+    }
+
+    // eMMC is non-removable
+    Method (_RMV) {
+      Return (0)
+    }
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
new file mode 100644
index 000000000000..2eb9fe41f127
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
@@ -0,0 +1,43 @@
+/** @file
+*
+*  iMX6 Quad SPI Controller
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (SPI2)
+{
+  Name (_HID, "NXP0105")
+  Name (_UID, 0x2)
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
+
+      // CS0 (PAD_EIM_RW) GPIO2_IO26
+      GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+              ResourceConsumer,, ) { 58 }
+      // CS1 (PAD_EIM_LBA) GPIO2_IO27
+      GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+              ResourceConsumer,, ) { 59 }
+
+      // MISO: PAD_EIM_OE_B (GPIO2_IO25) Alt2
+      // MOSI: PAD_EIM_CS1_B (GPIO2_IO24) Alt2
+      // SCLK: PAD_EIM_CS0_B (GPIO2_IO23) Alt2
+      MsftFunctionConfig (Exclusive, PullDown, IMX_ALT2, "\\_SB.GPIO", 0,
+                          ResourceConsumer, ) { 57, 56, 55 } })
+    Return (RBUF)
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
new file mode 100644
index 000000000000..c64c4664c442
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
@@ -0,0 +1,198 @@
+/** @file
+*
+*  iMX6 Quad UART Controllers
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (UAR1)
+{
+  Name (_HID, "NXP0106")
+  Name (_UID, 0x1)
+  Name (_DDN, "UART1")
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02020000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
+
+      // UART1_TX_DATA - CSI0_DAT10 - GPIO5_IO28 - 156
+      // UART1_RX_DATA - CSI0_DAT11 - GPIO5_IO29 - 157
+      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT3, "\\_SB.GPIO", 0,
+                          ResourceConsumer, ) { 156, 157 }
+
+      // DMA channel 2, SDMA_REQ_UART1_RX for UART1 RX DMA
+      FixedDMA (SDMA_REQ_UART1_RX, 2, Width8Bit, )
+      // DMA channel 1, SDMA_REQ_UART1_TX for UART1 TX DMA
+      FixedDMA (SDMA_REQ_UART1_TX, 1, Width8Bit, )
+
+      UARTSerialBus (
+        115200,
+        DataBitsEight,
+        StopBitsOne,
+        0,                // LinesInUse
+        LittleEndian,
+        ParityTypeNone,
+        FlowControlNone,
+        0,
+        0,
+        "\\_SB.CPU0",
+        0,
+        ResourceConsumer,
+        ,)
+    })
+    Return (RBUF)
+  }
+}
+
+Device (UAR2)
+{
+  Name (_HID, "NXP0107")
+  Name (_UID, 0x2)
+  Name (_DDN, "UART2")
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021E8000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 59 }
+
+      // DMA channel 4, SDMA_REQ_UART2_RX for UART2 RX DMA
+      FixedDMA (SDMA_REQ_UART2_RX, 4, Width8Bit, )
+      // DMA channel 3, SDMA_REQ_UART2_TX for UART2 TX DMA
+      FixedDMA (SDMA_REQ_UART2_TX, 3, Width8Bit, )
+
+      // UART2_TX_DATA - SD4_DAT7 - GPIO2_IO15 - 47
+      // UART2_RX_DATA - SD4_DAT4 - GPIO2_IO12 - 44
+      // UART2_CTS_B - SD4_DAT6 - GPIO2_IO14 - 46
+      // UART2_RTSB is not pinned out because it is connected to USB
+      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT2, "\\_SB.GPIO", 0,
+                          ResourceConsumer, ) { 44, 46, 47 }
+
+      UARTSerialBus (
+        115200,
+        DataBitsEight,
+        StopBitsOne,
+        0xC0,                // LinesInUse
+        LittleEndian,
+        ParityTypeNone,
+        FlowControlNone,
+        0,
+        0,
+        "\\_SB.CPU0",
+        0,
+        ResourceConsumer,
+        ,)
+    })
+    Return (RBUF)
+  }
+}
+
+Device (UAR3)
+{
+  Name (_HID, "NXP0107")
+  Name (_UID, 0x3)
+  Name (_DDN, "UART3")
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021EC000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 60 }
+
+      // DMA channel 6, SDMA_REQ_UART3_RX for UART3 RX DMA
+      FixedDMA (SDMA_REQ_UART3_RX, 6, Width8Bit, )
+      // DMA channel 5, SDMA_REQ_UART3_TX for UART3 TX DMA
+      FixedDMA (SDMA_REQ_UART3_TX, 5, Width8Bit, )
+
+      // UART3_TX - EIM_D24 - GPIO3_IO24 - 88
+      // UART3_RX - EIM_D25 - GPIO3_IO25 - 89
+      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT2, "\\_SB.GPIO", 0,
+                          ResourceConsumer, ) { 88, 89 }
+
+      UARTSerialBus (
+        115200,
+        DataBitsEight,
+        StopBitsOne,
+        0,                // LinesInUse
+        LittleEndian,
+        ParityTypeNone,
+        FlowControlNone,
+        0,
+        0,
+        "\\_SB.CPU0",
+        0,
+        ResourceConsumer,
+        ,)
+    })
+    Return (RBUF)
+  }
+}
+
+// Connected to bluetooth module
+Device (UAR4)
+{
+  Name (_HID, "NXP0107")
+  Name (_UID, 0x4)
+  Name (_DDN, "UART4")
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021F0000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 61 }
+
+      // DMA channel 8, SDMA_REQ_UART4_RX for UART4 RX DMA
+      FixedDMA (SDMA_REQ_UART4_RX, 8, Width8Bit, )
+      // DMA channel 7, SDMA_REQ_UART4_TX for UART4 TX DMA
+      FixedDMA (SDMA_REQ_UART4_TX, 7, Width8Bit, )
+
+      // UART4_TX_DATA - CSI0_DAT12 - GPIO5_IO30 - 158
+      // UART4_RX_DATA - CSI0_DAT13 - GPIO5_IO31 - 159
+      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT3, "\\_SB.GPIO", 0,
+                          ResourceConsumer, ) { 158, 159 }
+
+      // UART4_RTS_B - CSI0_DAT16 - GPIO6_IO02 - 162
+      // UART4_CTS_B - CSI0_DAT17 - GPIO6_IO03 - 163
+      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT3, "\\_SB.GPIO", 0,
+                          ResourceConsumer, ) { 162, 163 }
+    })
+    Return (RBUF)
+  }
+}
+
+Device (UAR5)
+{
+  Name (_HID, "NXP0107")
+  Name (_UID, 0x5)
+  Name (_DDN, "UART5")
+  Method (_STA) {
+    Return (0)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x021F4000, 0x4000, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 62 }
+
+      // DMA channel 10, SDMA_REQ_UART5_RX for UART5 RX DMA
+      FixedDMA (SDMA_REQ_UART5_RX, 10, Width8Bit, )
+      // DMA channel 9, SDMA_REQ_UART5_TX for UART5 TX DMA
+      FixedDMA (SDMA_REQ_UART5_TX, 9, Width8Bit, )
+    })
+    Return (RBUF)
+  }
+}
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
new file mode 100644
index 000000000000..65a0782d2705
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
@@ -0,0 +1,343 @@
+/** @file
+*
+*  iMX6 Quad EHCI USB Controllers
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+Device (URS0)
+{
+  Name (_HID, "PNP0C90")
+  Name (_UID, 0x0)
+
+  // URS requires device to at least be wake-able from D2 state
+  // WDF also requires that _DSW (enable & disable wake ability) to be present
+  Name (_S0W, 0x3)
+  Name (_PRW, Package() { 0, 0 })
+  Method (_DSW, 0x3, NotSerialized) {
+  }
+
+  Method (_STA) {
+    Return (0xf)
+  }
+
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      // Controller register address space. URS driver would add 0x0100
+      // offset for host mode
+      MEMORY32FIXED (ReadWrite, 0x02184000, 0x200, )
+
+      // USB_OTG_ID pin, needs to be declared as *Wake as this device is
+      // expected to be wakable. The USB PHY is capable to detect
+      // USB ID changes but the interrupt cannot be acknowledge
+      // and the behaviour is undefined based on NXP feedback. So
+      // the the only way to reliably detect USB ID changed is to
+      // either to share interrupts or assign a GPIO to detect.
+      // The URS driver does not properly handle level sensitive
+      // interrupts which can lead to an interrupt storm. Therefore we use
+      // an edge sensitive GPIO interrupt.
+      //
+      // USB_OTG_ID connected to GPIO_1 (GPIO1_IO01). Use 1ms debounce.
+      GpioInt (Edge, ActiveBoth, SharedAndWake, PullDefault, 100, "\\_SB.GPIO",) { 1 }
+    })
+    Return (RBUF)
+  }
+
+  Name (OTGR, ResourceTemplate() {
+    GpioIO (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
+            ResourceConsumer,,) {
+      1
+    }
+  })
+
+  Scope (\_SB_.GPIO) {
+    OperationRegion (OTGP, GeneralPurposeIO, Zero, One)
+  }
+
+  Field (\_SB_.GPIO.OTGP, ByteAcc, NoLock, Preserve) {
+    Connection (\_SB_.URS0.OTGR),
+    OTGF, 1
+  }
+
+  // Device Specific Method takes 4 args:
+  //  Arg0 : Buffer containing a UUID [16 bytes]
+  //  Arg1 : Integer containing the Revision ID
+  //  Arg2 : Integer containing the Function Index
+  //  Arg3 : Package that contains function-specific arguments (Unused?)
+  Method (_DSM, 0x4, NotSerialized) {
+    Name (RET, 0x0); // Declare return variable
+    Name (PVAL, 0x0); // Declare pin value variable
+
+    // Check UUID
+    switch (ToBuffer (Arg0)) {
+    // URS UUID
+    case (ToUUID ("14EB0A6A-79ED-4B37-A8C7-84604B55C5C3")) {
+        // Function index
+        switch (Arg2) {
+
+        // Function 0: Return supported functions, based on revision
+        // Return value and revision ID lack documentation
+        case (0) {
+            switch (Arg1) {
+            // Revision 0: function {1,2} supported
+            case (0) {
+                Return (0x03);
+              }
+              default {
+                Return (0x0);
+              }
+            }
+          }
+
+        // Function 1: Read USB_OTG_ID pin value
+        //
+        // Return value
+        // 0 = UrsHardwareEventIdFloat (Function)
+        // 1 = UrsHardwareEventIdGround (Host)
+        case (1) {
+            Store (OTGF, PVAL);                  // Read value of OTG_ID Pin
+            Store (LEqual (PVAL, 0), RET);       // Complement value
+            Return (RET);
+          }
+
+        // Function 2: Read USB_OTG_ID pin value
+        //
+        // Return value
+        // 0 = UrsHardwareEventIdFloat (Function)
+        // 1 = UrsHardwareEventIdGround (Host)
+        case (2) {
+            Store (OTGF, PVAL);                  // Read value of OTG_ID Pin
+            Store (LEqual (PVAL, 0), RET);       // Complement value
+            Return (RET);
+          }
+
+        // Unknown function index
+          default {
+            Return (0x0);
+          }
+        } // Function index
+      }
+
+    // Unknown UUID
+      default {
+        Return (0x0);
+      }
+    } // Check UUID
+  } // _DSM
+
+  Device (USB0) {
+    // The host controller device node needs to have an address of '0'
+    Name (_ADR, 0x0)
+    Name (_UID, 0x0)
+    Name (_S0W, 0x0) // D0 is the lowest supported state to wake itself up
+    Method (_STA) {
+      Return (0xf)
+    }
+    Method (_CRS, 0x0, NotSerialized) {
+      Name (RBUF, ResourceTemplate () {
+        Interrupt (ResourceConsumer, Level, ActiveHigh, SharedAndWake) { 75 }
+      })
+      Return (RBUF)
+    }
+
+    OperationRegion (OTGM, SystemMemory, 0x02184100, 0x100)
+    Field (OTGM, WordAcc, NoLock, Preserve) {
+      Offset (0x84),  // skip to register 84h
+      PTSC, 32,       // port status control
+      Offset (0xA8),  // skip to register A8h
+      DSBM, 32,       // UOG_USBMOD
+    }
+
+    Name (REG, 0x0);    // Declare register read variable
+    Method (_UBF, 0x0, NotSerialized) {
+      // Reset handled by driver so no reset required here
+      Store (0x03, DSBM);         // set host mode & little endian
+      Store (PTSC, REG);          // read PORTSC status
+      Store (OR (REG, 0x2), PTSC); // clear current PORTSC status
+    }
+  }
+
+  Device (UFN0) {
+    // The function controller device node needs to have an address of '1'
+    Name (_ADR, 0x1)
+
+    Method (_CRS, 0x0, NotSerialized) {
+      Name (RBUF, ResourceTemplate () {
+        Interrupt (ResourceConsumer, Level, ActiveHigh, SharedAndWake) { 75 }
+      })
+      Return (RBUF)
+    }
+
+    OperationRegion (OTGM, SystemMemory, 0x02184100, 0x100)
+    Field (OTGM, WordAcc, NoLock, Preserve) {
+      Offset (0x84),  // skip to register 84h
+      PTSC, 32,       // port status control
+      Offset (0xA8),  // skip to register A8h
+      DSBM, 32,       // UOG_USBMOD
+    }
+
+    Name (REG, 0x0);    // Declare register read variable
+    Method (_UBF, 0x0, NotSerialized) {
+      // Reset handled by driver so no reset required here
+      Store (0x02, DSBM);         // set device mode & little endian
+      Store (PTSC, REG);          // read PORTSC status
+      Store (OR (REG, 0x2), PTSC); // clear current PORTSC status
+    }
+
+    // Device Specific Method takes 4 args:
+    //  Arg0 : Buffer containing a UUID [16 bytes]
+    //  Arg1 : Integer containing the Revision ID
+    //  Arg2 : Integer containing the Function Index
+    //  Arg3 : Package that contains function-specific arguments
+    Method (_DSM, 0x4, NotSerialized) {
+      switch (ToBuffer (Arg0)) {
+      // UFX Chipidea interface identifier
+      case (ToUUID ("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511")) {
+          // Function selector
+          switch (Arg2) {
+
+          // Function 0: Query support
+          //   Bit  Description
+          //   ---  -------------------------------
+          //     0  Get property
+          //     1  Get properties (Function 1)
+          //     2  Set USB device state
+          case (0) {
+              switch (Arg1) {
+              // Revision 0: functions {0,1} supported
+              case (0) {
+                  Return (Buffer() { 0x03 });
+                }
+                default {
+                  Return (Buffer() { 0x01 });
+                }
+              }
+            }
+
+          // Function 1: Return device capabilities bitmap
+          //   Bit  Description
+          //   ---  -------------------------------
+          //     0  Attach detach
+          //     1  Software charging
+          case (1) {
+              Return (0x01);
+            }
+
+          // Function 2: Get port type
+          //     0x00  Unknown port
+          //     0x01  Standard downstream
+          //     0x02  Charging downstream
+          //     0x03  Dedicated charging
+          case (2) {
+              Return (0x01);
+            }
+
+          // Function 3: Set device state
+          case (3) {
+              Return (Buffer() { 0x0 });
+            }
+
+          // Unknown function
+            default {
+              Return (Buffer() { 0x0 });
+            }
+          }
+        }
+
+      // UFX interface identifier
+      case (ToUUID ("FE56CFEB-49D5-4378-A8A2-2978DBE54AD2")) {
+          // Function selector
+          switch (Arg2) {
+          // Function 1: Return number of supported USB PHYSICAL endpoints
+          // Up to 8 bidirectional endpoints
+          case (1) {
+              Return (8);
+            }
+            default {
+              Return (Buffer() { 0x0 });
+            }
+          }
+        }
+
+      //
+      // Unknown UUID
+      //
+        default {
+          Return (0x0);
+        }
+      } // UUID
+    } // _DSM
+  }
+}
+
+Device (USB1)
+{
+  Name (_HID, "NXP010C")
+  Name (_CID, "PNP0D20")
+  Name (_UID, 0x1)
+  Name (_S0W, 0x0)
+
+  // USB Host controller registers
+  OperationRegion (USBH, SystemMemory, 0x02184000, 0x1000)
+  Field (USBH, DWordAcc, NoLock, Preserve) {
+    Offset (0x00000344),
+    USTS, 32,             // USB_UH1_USBSTS
+    Offset (0x00000348),
+    INTR, 32,             // USB_UH1_USBINTR
+    Offset (0x00000384),  // skip to register 0x384
+    PSC1, 32,             // USB_UH1_PORTSC1
+    Offset (0x00000804),  // skip to register 0x804
+    NCTL, 32,             // USBNC_USB_UH1_CTRL
+  }
+
+  // USBPHY2 Registers
+  OperationRegion (PHY2, SystemMemory, 0x020CA000, 0x1000)
+  Field (PHY2, DWordAcc, NoLock, Preserve) {
+    Offset (0x0000000),     // skip to register 0
+    PPWD, 32,               // USBPHY2_PWD
+    Offset (0x00000030),    // skip to register 0x30
+    PCTL, 32,               // USBPHY2_CTRL
+    Offset (0x00000034),    // skip to register 0x34
+    PCTS, 32,               // USBPHY2_CTRL_SET
+    Offset (0x00000038),    // skip to register 0x38
+    PCTC, 32,               // USBPHY2_CTRL_CLR
+    Offset (0x00000050),    // skip to register 0x50
+    PDBG, 32,               // USBPHY2_DEBUG
+    Offset (0x00000054),    // skip to register 0x54
+    PDBS, 32,               // USBPHY2_DEBUG_SET
+    Offset (0x00000058),    // skip to register 0x58
+    PDBC, 32,               // USBPHY2_DEBUG_CLR
+  }
+
+  // Anatop Registers
+  OperationRegion (ANAT, SystemMemory, 0x020C8000, 0x1000)
+  Field (ANAT, DWordAcc, NoLock, Preserve) {
+    Offset (0x0000244),     // skip to register 0x244
+    LPBS, 32,               // ANADIG_USB2_LOOPBACK_SET
+    Offset (0x0000248),     // skip to register 0x248
+    LPBC, 32,               // ANADIG_USB2_LOOPBACK_CLR
+  }
+
+  Method (_STA) {
+    Return (0xf)
+  }
+  Method (_CRS, 0x0, NotSerialized) {
+    Name (RBUF, ResourceTemplate () {
+      MEMORY32FIXED (ReadWrite, 0x02184300, 0x100, )
+      Interrupt (ResourceConsumer, Level, ActiveHigh, ExclusiveAndWake) { 72 }
+    })
+    Return (RBUF)
+  }
+
+  Method (_UBF, 0x0, NotSerialized) {
+  }
+}
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH edk2-platforms 27/27] Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (25 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 26/27] Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables Chris Co
@ 2018-09-21  8:26 ` Chris Co
  2018-12-15 12:28   ` Leif Lindholm
  2018-12-15 13:32 ` [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Leif Lindholm
  27 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-09-21  8:26 UTC (permalink / raw)
  To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney

This adds the dsd and fdf definitions for Solidrun's i.MX 6Quad
Hummingboard Edge platform.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <christopher.co@microsoft.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc | 141 ++++++++++++++++++++
 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf | 117 ++++++++++++++++
 2 files changed, 258 insertions(+)

diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
new file mode 100644
index 000000000000..5e203bc92447
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
@@ -0,0 +1,141 @@
+#
+# HummingBoard Edge board description
+# The board is iMX6 Quad with 2GB DRAM
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+################################################################################
+#
+# Board [Defines] Section
+#
+################################################################################
+
+[Defines]
+  DEFINE BOARD_NAME     = HummingBoardEdge_iMX6Q_2GB
+  DEFINE IMX_FAMILY     = IMX6DQ
+  DEFINE IMX_CHIP_TYPE  = QUAD
+  DEFINE DRAM_SIZE      = DRAM_2GB
+  BOARD_DIR             = Platform/SolidRun/$(BOARD_NAME)
+  FLASH_DEFINITION      = $(BOARD_DIR)/$(BOARD_NAME).fdf
+
+################################################################################
+#
+# Platform Description
+#
+################################################################################
+!include Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
+
+[LibraryClasses.common]
+  ArmPlatformLib|$(BOARD_DIR)/Library/iMX6BoardLib/iMX6BoardLib.inf
+
+[Components.common]
+  # Display Support
+!if $(CONFIG_HEADLESS) == FALSE
+  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+  !if $(IMX_FAMILY) == IMX6SX
+    #
+    # Use board-specific GOP for SoloX
+    #
+    $(BOARD_DIR)/Drivers/GraphicsOutputDxe/GraphicsOutputDxe.inf
+  !else
+    Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
+  !endif
+!endif
+
+  # ACPI Support
+  MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+  MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+  $(BOARD_DIR)/AcpiTables/AcpiTables.inf
+
+  # SMBIOS Support
+  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
+  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+
+################################################################################
+#
+# Board PCD Sections
+#
+################################################################################
+
+########################
+#
+# iMX6Pkg PCDs
+#
+########################
+[PcdsFixedAtBuild.common]
+
+# SMBIOS Type0 Strings
+gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"SolidRun"
+gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision|0x00000001 # FirmwareRevision 0.1
+
+# SMBIOS Type1 Strings
+giMX6TokenSpaceGuid.PcdSystemFamily|L"HummingBoard"
+giMX6TokenSpaceGuid.PcdSystemManufacturer|L"SolidRun"
+giMX6TokenSpaceGuid.PcdSystemProductName|L"HummingBoard-Edge i4Pro"
+giMX6TokenSpaceGuid.PcdSystemSkuNumber|L"MSMX6QDW00D02GE008E00CH"
+giMX6TokenSpaceGuid.PcdSystemVersionNumber|L"1.4"
+giMX6TokenSpaceGuid.PcdSystemUuid|{0xfa,0x00,0xe9,0x0f,0x97,0x4a,0x40,0x6f,0xaf,0x0f,0x4a,0xd4,0x66,0x50,0xbe,0x5a}
+
+# SMBIOS Type2 Strings
+giMX6TokenSpaceGuid.PcdBoardAssetTag|L"0"
+giMX6TokenSpaceGuid.PcdBoardLocationInChassis|L"Open Board"
+giMX6TokenSpaceGuid.PcdBoardManufacturer|L"SolidRun"
+giMX6TokenSpaceGuid.PcdBoardProductName|L"HummingBoard-Edge i4Pro"
+giMX6TokenSpaceGuid.PcdBoardVersionNumber|L"1.4"
+
+# SMBIOS Type3 Strings
+giMX6TokenSpaceGuid.PcdChassisAssetTag|L"0"
+giMX6TokenSpaceGuid.PcdChassisManufacturer|L"SolidRun"
+giMX6TokenSpaceGuid.PcdChassisVersionNumber|L"1.4"
+
+# SMBIOS Type4 Strings
+giMX6TokenSpaceGuid.PcdProcessorAssetTag|L"0"
+giMX6TokenSpaceGuid.PcdProcessorManufacturer|L"NXP"
+giMX6TokenSpaceGuid.PcdProcessorPartNumber|L"i.MX 6Quad"
+giMX6TokenSpaceGuid.PcdProcessorSocketDesignation|L"FCPBGA"
+giMX6TokenSpaceGuid.PcdProcessorVersionNumber|L"1.0"
+
+# SMBIOS Type16
+giMX6TokenSpaceGuid.PcdPhysicalMemoryMaximumCapacity|0x200000 # 2GB
+
+# SMBIOS Type17
+giMX6TokenSpaceGuid.PcdMemoryBankLocation|L"Bank 0"
+giMX6TokenSpaceGuid.PcdMemoryDeviceLocation|L"On SoM"
+
+#
+# USB EHCI Controller (USB_UH1)
+#
+giMX6TokenSpaceGuid.PcdEHCIBase|0x02184200
+
+#
+# Enable uSDHC2 and uSDHC3 Controllers.
+# On HummingBoardEdge, SDCard slot is attached to uSDHC2
+# with CD wired to SD2_CD_B, eMMC is attached to uSDHC3
+#
+giMXPlatformTokenSpaceGuid.PcdSdhc2Enable|TRUE
+giMXPlatformTokenSpaceGuid.PcdSdhc2CardDetectSignal|0xFFFF # Use uSDHC internal CD circuit
+giMXPlatformTokenSpaceGuid.PcdSdhc3Enable|TRUE
+
+#
+# UART initialization required
+#
+giMXPlatformTokenSpaceGuid.PcdSerialRegisterBase|0x02020000   # UART1
+giMXPlatformTokenSpaceGuid.PcdKdUartInstance|1                # UART1
+
+#
+# GPIO reset pin (PERST)
+#
+giMX6TokenSpaceGuid.PcdPcieResetGpio|TRUE
+giMX6TokenSpaceGuid.PcdPcieResetGpioBankNumber|2
+giMX6TokenSpaceGuid.PcdPcieResetGpioIoNumber|11
diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
new file mode 100644
index 000000000000..f40ee824e1e3
--- /dev/null
+++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
@@ -0,0 +1,117 @@
+#
+#  iMX6 Quad Hummingboard FLASH layout
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+################################################################################
+#
+# FD Section
+# The [FD] Section is made up of the definition statements and a
+# description of what goes into  the Flash Device Image.  Each FD section
+# defines one flash "device" image.  A flash device image may be one of
+# the following: Removable media bootable image (like a boot floppy
+# image,) an Option ROM image (that would be "flashed" into an add-in
+# card,) a System "Flash"  image (that would be burned into a system's
+# flash) or an Update ("Capsule") image that will be used to update and
+# existing system flash.
+#
+################################################################################
+
+[FD.iMXBoard_EFI]
+!if $(IMX_FAMILY) == IMX6SX
+BaseAddress   = 0x82004000|gArmTokenSpaceGuid.PcdFdBaseAddress  #The base address of UEFI image
+!else
+BaseAddress   = 0x10820000|gArmTokenSpaceGuid.PcdFdBaseAddress  #The base address of UEFI image
+!endif
+Size          = 0x001D0000|gArmTokenSpaceGuid.PcdFdSize         #The size in bytes of UEFI image
+ErasePolarity = 1
+BlockSize     = 0x1
+NumBlocks     = 0x001D0000
+
+################################################################################
+#
+# Following are lists of FD Region layout which correspond to the locations of different
+# images within the flash device.
+#
+# Regions must be defined in ascending order and may not overlap.
+#
+# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
+# the pipe "|" character, followed by the size of the region, also in hex with the leading
+# "0x" characters. Like:
+# Offset|Size
+# PcdOffsetCName|PcdSizeCName
+# RegionType <FV, DATA, or FILE>
+#
+################################################################################
+0x00000000|0x001D0000    # 1792Kb for the Pei phase boot
+
+gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
+FV = FVMAIN_COMPACT
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file.  This section also defines order the components and modules are positioned
+# within the image.  The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.FvMain]
+BlockSize          = 0x1
+NumBlocks          = 0         # This FV gets compressed so make it just big enough
+FvAlignment        = 8         # FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+  #
+  # ACPI
+  #
+  INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+  INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+  INF RuleOverride=ACPITABLE $(BOARD_DIR)/AcpiTables/AcpiTables.inf
+
+!if $(CONFIG_HEADLESS) == FALSE
+  INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+  INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+  !if $(IMX_FAMILY) == IMX6SX
+    #
+    # Use board-specific GOP for SoloX
+    #
+    INF $(BOARD_DIR)/Drivers/GraphicsOutputDxe/GraphicsOutputDxe.inf
+  !else
+    INF Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
+  !endif
+!endif
+
+  #
+  # SMBIOS Support
+  #
+  INF Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
+  INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+
+!include Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
-- 
2.16.2.gvfs.1.33.gf5370f1



^ permalink raw reply related	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-09-21  8:25 ` [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec Chris Co
@ 2018-10-31 20:43   ` Leif Lindholm
  2018-11-01 10:55     ` Sumit Garg
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-10-31 20:43 UTC (permalink / raw)
  To: Chris Co
  Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney,
	Sumit Garg

+Sumit (just to loop you two together). Is there anything Microsoft
platform specific about what will go in here?

/
    Leif

On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> On Windows IoT Core devices with ARM TrustZone capabilities,
> EDK2 runs in normal world and we use OP-TEE to execute
> secure world operations. The overall package will contain
> client-side support to invoke EDK2 services implemented as
> OP-TEE trusted applications that run in secure world.
> 
> This commit adds the initial dec file to add some PCD settings
> needed by other packages.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49 ++++++++++++++++++++
>  1 file changed, 49 insertions(+)
> 
> diff --git a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> new file mode 100644
> index 000000000000..4752eab39ce3
> --- /dev/null
> +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> @@ -0,0 +1,49 @@
> +## @file
> +#
> +#  OP-TEE client package
> +#
> +#  OP-TEE client package contains the client-side interface to invoke OP-TEE TAs.
> +#  Certain EDKII services are implemented in Trusted Applications running in
> +#  the secure world OP-TEE OS.
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  DEC_SPECIFICATION              = 0x0001001A
> +  PACKAGE_NAME                   = OpteeClientPkg
> +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-1bdd74ec9595
> +  PACKAGE_VERSION                = 0.01
> +
> +[Includes]
> +
> +[LibraryClasses]
> +
> +[Guids]
> +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, { 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> +
> +[PcdsFixedAtBuild]
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x00000005
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x00000006
> +
> +  ## The base address of the Trust Zone OpTEE OS private memory region
> +  # This memory is manager privately by the OpTEE OS.
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD1|UINT64|0x00000001
> +
> +  ## The size of the Trust Zone OpTEE OS private memory region
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UINT64|0x00000002
> +
> +  ## The base address of the Trust Zone OpTEE OS shared memory region
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2|UINT64|0x00000003
> +
> +  ## The size of the Trust Zone OpTEE OS shared memory region
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UINT64|0x00000004
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 03/27] Platform/Microsoft: Add MsPkg
  2018-09-21  8:25 ` [PATCH edk2-platforms 03/27] Platform/Microsoft: Add MsPkg Chris Co
@ 2018-10-31 21:00   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-10-31 21:00 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

(You'll note I'm skipping over the SdMmc bits for now.)

On Fri, Sep 21, 2018 at 08:25:55AM +0000, Chris Co wrote:
> MsPkg is a collection of libraries and drivers that are specific
> to supporting Windows IoT Core but are not Platform/Silicon specific.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Platform/Microsoft/MsPkg.dec | 39 ++++++++++++++++++++
>  Platform/Microsoft/MsPkg.dsc | 31 ++++++++++++++++
>  2 files changed, 70 insertions(+)
> 
> diff --git a/Platform/Microsoft/MsPkg.dec b/Platform/Microsoft/MsPkg.dec
> new file mode 100644
> index 000000000000..c19913603e4f
> --- /dev/null
> +++ b/Platform/Microsoft/MsPkg.dec
> @@ -0,0 +1,39 @@
> +#/** @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> +  DEC_SPECIFICATION              = 0x0001001A
> +  PACKAGE_NAME                   = MsPkg
> +  PACKAGE_GUID                   = DC909FB7-F45E-4D7F-BF10-327BD9BFA21C
> +  PACKAGE_VERSION                = 0.1
> +
> +[Includes.common]
> +  Include                        # Root include for the package
> +
> +[LibraryClasses.common]
> +
> +[Guids.common]
> +  gMsPkgTokenSpaceGuid = { 0x3ecb4bb9, 0xb80a, 0x4efd, { 0x92, 0xb8, 0x3a, 0x16, 0xe0, 0xc8, 0x19, 0xb } }
> +
> +[PcdsFixedAtBuild.common]
> +  gMsPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|0x00

Do we need a Pcd under MsPkg namespace for this?
Many other platforms use a SECURE_BOOT_ENABLE test and set global Pcds
and include components based on that value. See for example
edk2/QuarkPlatformPkg/Quark.dsc

> +
> +  # The DevicePath to a partition on a writeable media used for logging and misc
> +  # storage purposes. SD card DevicePath example:
> +  # gMsPkgTokenSpaceGuid.PcdStorageMediaPartitionDevicePath|L"VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,03000000)/SD(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)"
> +  gMsPkgTokenSpaceGuid.PcdStorageMediaPartitionDevicePath|L""|VOID*|0x03
> +
> +[Protocols.common]
> +  gEfiRpmbIoProtocolGuid = { 0xfbaee5b2, 0x8b0, 0x41b8, { 0xb0, 0xb0, 0x86, 0xb7, 0x2e, 0xed, 0x1b, 0xb6 } }
> +  gEfiSdhcProtocolGuid = { 0x46055b0f, 0x992a, 0x4ad7, { 0x8f, 0x81, 0x14, 0x81, 0x86, 0xff, 0xdf, 0x72 } }
> diff --git a/Platform/Microsoft/MsPkg.dsc b/Platform/Microsoft/MsPkg.dsc
> new file mode 100644
> index 000000000000..fc92208673da
> --- /dev/null
> +++ b/Platform/Microsoft/MsPkg.dsc
> @@ -0,0 +1,31 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#   This program and the accompanying materials
> +#   are licensed and made available under the terms and conditions of the BSD License
> +#   which accompanies this distribution. The full text of the license may be found at
> +#   http://opensource.org/licenses/bsd-license.
> +#
> +#   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  PLATFORM_NAME                  = MsPkg
> +  PLATFORM_GUID                  = 2F78367E-9C74-4FBE-82E7-1D2DAAF18CC6
> +  PLATFORM_VERSION               = 0.01
> +  DSC_SPECIFICATION              = 0x0001001A
> +  OUTPUT_DIRECTORY               = Build/MsPkg
> +  SUPPORTED_ARCHITECTURES        = ARM|AARCH64
> +  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
> +  SKUID_IDENTIFIER               = DEFAULT
> +
> +[PcdsFeatureFlag]
> +
> +[PcdsFixedAtBuild]
> +
> +[LibraryClasses]
> +
> +[Components]
> +  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf

The one thing I'd say here is that we usually set up .dsc files to let
us build individual components. So in this case,
  build -p Platform/Microsoft/MsPkg.dsc -m Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf

This means wiring up a lot of the boilerplate under [LibraryClasses].

/
    Leif


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms
  2018-09-21  8:25 ` [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms Chris Co
@ 2018-11-01  8:59   ` Leif Lindholm
  2018-11-02  1:46     ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-11-01  8:59 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:25:56AM +0000, Chris Co wrote:
> This adds support for interact with the UART controller on
> NXP i.MX platforms.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h                               | 207 +++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c   | 243 ++++++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf |  41 ++++
>  3 files changed, 491 insertions(+)
> 
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
> new file mode 100644
> index 000000000000..ddb61f59c656
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
> @@ -0,0 +1,207 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMXUART_H_
> +#define _IMXUART_H_
> +
> +// UART Receiver Register bit definitions
> +enum MX6UART_RXD {
> +  MX6UART_RXD_RX_DATA_MASK =      (0xff << 0),
> +  MX6UART_RXD_PRERR =             (1 << 10),
> +  MX6UART_RXD_BRK =               (1 << 11),
> +  MX6UART_RXD_FRMERR =            (1 << 12),
> +  MX6UART_RXD_OVRRUN =            (1 << 13),
> +  MX6UART_RXD_ERR =               (1 << 14),
> +  MX6UART_RXD_CHARRDY =           (1 << 15),
> +};
> +
> +// UART Control Register 1 bit definitions
> +enum MX6UART_UCR1 {
> +  MX6UART_UCR1_UARTEN =           (1 << 0),
> +  MX6UART_UCR1_DOZE =             (1 << 1),
> +  MX6UART_UCR1_ATDMAEN =          (1 << 2),
> +  MX6UART_UCR1_TXDMAEN =          (1 << 3),
> +  MX6UART_UCR1_SNDBRK =           (1 << 4),
> +  MX6UART_UCR1_RTSDEN =           (1 << 5),
> +  MX6UART_UCR1_TXMPTYEN =         (1 << 6),
> +  MX6UART_UCR1_IREN =             (1 << 7),
> +  MX6UART_UCR1_RXDMAEN =          (1 << 8),
> +  MX6UART_UCR1_RRDYEN =           (1 << 9),
> +  MX6UART_UCR1_ICD_MASK =         (3 << 10),
> +  MX6UART_UCR1_ICD_4 =            (0 << 10),
> +  MX6UART_UCR1_ICD_8 =            (1 << 10),
> +  MX6UART_UCR1_ICD_16 =           (2 << 10),
> +  MX6UART_UCR1_ICD_32 =           (3 << 10),
> +  MX6UART_UCR1_IDEN =             (1 << 12),
> +  MX6UART_UCR1_TRDYEN =           (1 << 13),
> +  MX6UART_UCR1_ADBR =             (1 << 14),
> +  MX6UART_UCR1_ADEN =             (1 << 15),
> +};
> +
> +// UART Control Register 2 bit definitions
> +enum MX6UART_UCR2 {
> +  MX6UART_UCR2_SRST =             (1 << 0),
> +  MX6UART_UCR2_RXEN =             (1 << 1),
> +  MX6UART_UCR2_TXEN =             (1 << 2),
> +  MX6UART_UCR2_ATEN =             (1 << 3),
> +  MX6UART_UCR2_RTSEN =            (1 << 4),
> +  MX6UART_UCR2_WS =               (1 << 5),
> +  MX6UART_UCR2_STPB =             (1 << 6),
> +  MX6UART_UCR2_PROE =             (1 << 7),
> +  MX6UART_UCR2_PREN =             (1 << 8),
> +  MX6UART_UCR2_RTEC_MASK =        (3 << 9),
> +  MX6UART_UCR2_RTEC_RISING =      (0 << 9),
> +  MX6UART_UCR2_RTEC_FALLING =     (1 << 9),
> +  MX6UART_UCR2_RTEC_BOTH =        (2 << 9),
> +  MX6UART_UCR2_ESCEN =            (1 << 11),
> +  MX6UART_UCR2_CTS =              (1 << 12),
> +  MX6UART_UCR2_CTSC =             (1 << 13),
> +  MX6UART_UCR2_IRTS =             (1 << 14),
> +  MX6UART_UCR2_ESCI =             (1 << 15),
> +};
> +
> +// UART Control Register 3 bit definitions
> +enum MX6UART_UCR3 {
> +  MX6UART_UCR3_ACIEN =            (1 << 0),
> +  MX6UART_UCR3_INVT =             (1 << 1),
> +  MX6UART_UCR3_RXDMUXSEL =        (1 << 2),
> +  MX6UART_UCR3_DTRDEN =           (1 << 3),
> +  MX6UART_UCR3_AWAKEN =           (1 << 4),
> +  MX6UART_UCR3_AIRINTEN =         (1 << 5),
> +  MX6UART_UCR3_RXDSEN =           (1 << 6),
> +  MX6UART_UCR3_ADNIMP =           (1 << 7),
> +  MX6UART_UCR3_RI =               (1 << 8),
> +  MX6UART_UCR3_DCD =              (1 << 9),
> +  MX6UART_UCR3_DSR =              (1 << 10),
> +  MX6UART_UCR3_FRAERREN =         (1 << 11),
> +  MX6UART_UCR3_PARERREN =         (1 << 12),
> +  MX6UART_UCR3_DTREN =            (1 << 13),
> +  MX6UART_UCR3_DPEC_MASK =        (3 << 14),
> +  MX6UART_UCR3_DPEC_RISING =      (0 << 14),
> +  MX6UART_UCR3_DPEC_FALLING =     (1 << 14),
> +  MX6UART_UCR3_DPEC_BOTH =        (2 << 14),
> +};
> +
> +// UART Control Register 4 bit definitions
> +enum MX6UART_UCR4 {
> +  MX6UART_UCR4_DREN =             (1 << 0),
> +  MX6UART_UCR4_OREN =             (1 << 1),
> +  MX6UART_UCR4_BKEN =             (1 << 2),
> +  MX6UART_UCR4_TCEN =             (1 << 3),
> +  MX6UART_UCR4_LPBYP =            (1 << 4),
> +  MX6UART_UCR4_IRSC =             (1 << 5),
> +  MX6UART_UCR4_IDDMAEN =          (1 << 6),
> +  MX6UART_UCR4_WKEN =             (1 << 7),
> +  MX6UART_UCR4_ENIRI =            (1 << 8),
> +  MX6UART_UCR4_INVR =             (1 << 9),
> +  MX6UART_UCR4_CTSTL_MASK =       (0x3f << 10),
> +  MX6UART_UCR4_CTSTL_SHIFT =      10,
> +};
> +
> +// UART FIFO Control Register bit definitions
> +enum MX6UART_UFCR {
> +  MX6UART_UFCR_RXTL_MASK =        (0x3f << 0),
> +  MX6UART_UFCR_RXTL_SHIFT =       0,
> +  MX6UART_UFCR_DCEDTE =           (1 << 6),
> +  MX6UART_UFCR_RFDIV_MASK =       (7 << 7),
> +  MX6UART_UFCR_RFDIV_6 =          (0 << 7),
> +  MX6UART_UFCR_RFDIV_5 =          (1 << 7),
> +  MX6UART_UFCR_RFDIV_4 =          (2 << 7),
> +  MX6UART_UFCR_RFDIV_3 =          (3 << 7),
> +  MX6UART_UFCR_RFDIV_2 =          (4 << 7),
> +  MX6UART_UFCR_RFDIV_1 =          (5 << 7),
> +  MX6UART_UFCR_RFDIV_7 =          (6 << 7),
> +  MX6UART_UFCR_TXTL_MASK =        (0x3f << 10),
> +  MX6UART_UFCR_TXTL_SHIFT =       10,
> +};
> +
> +// UART Status Register 1 bit definitions
> +enum MX6UART_USR1 {
> +  MX6UART_USR1_SAD =              (1 << 3),
> +  MX6UART_USR1_AWAKE =            (1 << 4),
> +  MX6UART_USR1_AIRINT =           (1 << 5),
> +  MX6UART_USR1_RXDS =             (1 << 6),
> +  MX6UART_USR1_DTRD =             (1 << 7),
> +  MX6UART_USR1_AGTIM =            (1 << 8),
> +  MX6UART_USR1_RRDY =             (1 << 9),
> +  MX6UART_USR1_FRAMERR =          (1 << 10),
> +  MX6UART_USR1_ESCF =             (1 << 11),
> +  MX6UART_USR1_RTSD =             (1 << 12),
> +  MX6UART_USR1_TRDY =             (1 << 13),
> +  MX6UART_USR1_RTSS =             (1 << 14),
> +  MX6UART_USR1_PARITYERR =        (1 << 15),
> +};
> +
> +// UART Status Register 2 bit definitions
> +enum MX6UART_USR2 {
> +  MX6UART_USR2_RDR =              (1 << 0),
> +  MX6UART_USR2_ORE =              (1 << 1),
> +  MX6UART_USR2_BRCD =             (1 << 2),
> +  MX6UART_USR2_TXDC =             (1 << 3),
> +  MX6UART_USR2_RTSF =             (1 << 4),
> +  MX6UART_USR2_DCDIN =            (1 << 5),
> +  MX6UART_USR2_DCDDELT =          (1 << 6),
> +  MX6UART_USR2_WAKE =             (1 << 7),
> +  MX6UART_USR2_IRINT =            (1 << 8),
> +  MX6UART_USR2_RIIN =             (1 << 9),
> +  MX6UART_USR2_RIDLET =           (1 << 10),
> +  MX6UART_USR2_ACST =             (1 << 11),
> +  MX6UART_USR2_IDLE =             (1 << 12),
> +  MX6UART_USR2_DTRF =             (1 << 13),
> +  MX6UART_USR2_TXFE =             (1 << 14),
> +  MX6UART_USR2_ADET =             (1 << 15),
> +};
> +
> +// UART Test Register bit definitions
> +enum MX6UART_UTS {
> +  MX6UART_UTS_SOFTRST =           (1 << 0),
> +  MX6UART_UTS_RXFULL =            (1 << 3),
> +  MX6UART_UTS_TXFULL =            (1 << 4),
> +  MX6UART_UTS_RXEMPTY =           (1 << 5),
> +  MX6UART_UTS_TXEMPTY =           (1 << 6),
> +  MX6UART_UTS_RXDBG =             (1 << 9),
> +  MX6UART_UTS_LOOPIR =            (1 << 10),
> +  MX6UART_UTS_DBGEN =             (1 << 11),
> +  MX6UART_UTS_LOOP =              (1 << 12),
> +  MX6UART_UTS_FRCPERR =           (1 << 13),
> +};
> +
> +// Size of RX and TX FIFOs
> +enum {
> +  MX6UART_FIFO_COUNT = 32
> +};
> +
> +typedef struct _MX6UART_REGISTERS {
> +  UINT32 Rxd;                  // 0x00: UART Receiver Register
> +  UINT32 reserved1[15];
> +  UINT32 Txd;                  // 0x40: UART Transmitter Register
> +  UINT32 reserved2[15];
> +  UINT32 Ucr1;                 // 0x80: UART Control Register 1
> +  UINT32 Ucr2;                 // 0x84: UART Control Register 2
> +  UINT32 Ucr3;                 // 0x88: UART Control Register 3
> +  UINT32 Ucr4;                 // 0x8C: UART Control Register 4
> +  UINT32 Ufcr;                 // 0x90: UART FIFO Control Register
> +  UINT32 Usr1;                 // 0x94: UART Status Register 1
> +  UINT32 Usr2;                 // 0x98: UART Status Register 2
> +  UINT32 Uesc;                 // 0x9C: UART Escape Character Register
> +  UINT32 Utim;                 // 0xA0: UART Escape Timer Register
> +  UINT32 Ubir;                 // 0xA4: UART BRM Incremental Register
> +  UINT32 Ubmr;                 // 0xA8: UART BRM Modulator Register (UART1_UBMR)
> +  UINT32 Ubrc;                 // 0xAC: UART Baud Rate Count Register
> +  UINT32 Onems;                // 0xB0: UART One Millisecond Register
> +  UINT32 Uts;                  // 0xB4: UART Test Register
> +  UINT32 Umcr;                 // 0xB8: UART RS-485 Mode Control Register
> +} MX6UART_REGISTERS;

So, these are the actual register names - which means I have no issue
with the struct contents not otherwise following coding style. But...

> +
> +#endif // _IMXUART_H_
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
> new file mode 100644
> index 000000000000..fbe24d98c6aa
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
> @@ -0,0 +1,243 @@
> +/** @file
> +
> +  Copyright (c) 2006 - 2008, Intel Corporation
> +  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +
> +  All rights reserved. This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Library/BaseLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/SerialPortLib.h>
> +#include <iMXUart.h>
> +
> +
> +/**
> +  Initialize the serial device hardware.
> +
> +  If no initialization is required, then return RETURN_SUCCESS.
> +  If the serial device was successfully initialized, then return RETURN_SUCCESS.
> +  If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
> +
> +  @retval RETURN_SUCCESS        The serial device was initialized.
> +  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +SerialPortInitialize (
> +  VOID
> +  )
> +{
> +  MX6UART_REGISTERS   *UartBase;
> +  UINT32              Ucr1;

... once we create variables to hold data from those registers, those
variables should really be FullyCompliantCamelCase.
But really, something like this could just be "Data" or "Value" or
something like that. Or if you want a bit more, "ControlRegister".

Not going to comment on each function, but the pattern repeats
throughout the file.

Other than that, looks good.

/
    Leif

> +
> +  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
> +
> +  Ucr1 = MmioRead32 ((UINTN)&UartBase->Ucr1);
> +  if ((Ucr1 & MX6UART_UCR1_UARTEN) == 0) {
> +    // UART should have been initialized by previous boot stage
> +    return RETURN_DEVICE_ERROR;
> +  }
> +
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Write data from buffer to serial device.
> +
> +  Writes NumberOfBytes data bytes from Buffer to the serial device.
> +  The number of bytes actually written to the serial device is returned.
> +  If the return value is less than NumberOfBytes, then the write operation failed.
> +  If Buffer is NULL, then ASSERT().
> +  If NumberOfBytes is zero, then return 0.
> +
> +  @param  Buffer           Pointer to the data buffer to be written.
> +  @param  NumberOfBytes    Number of bytes to written to the serial device.
> +
> +  @retval 0                NumberOfBytes is 0.
> +  @retval >0               The number of bytes written to the serial device.
> +                           If this value is less than NumberOfBytes, then the
> +                           read operation failed.
> +
> +**/
> +UINTN
> +EFIAPI
> +SerialPortWrite (
> +  IN  UINT8   *Buffer,
> +  IN  UINTN   NumberOfBytes
> +  )
> +{
> +  MX6UART_REGISTERS   *UartBase;
> +  UINTN               BytesSent;
> +
> +  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
> +  BytesSent = 0;
> +  while (BytesSent < NumberOfBytes) {
> +    // Check if FIFO is full and wait if it is.
> +    while ((MmioRead32 ((UINTN)&UartBase->Uts) & MX6UART_UTS_TXFULL) != 0);
> +    MmioWrite32 ((UINTN)&UartBase->Txd, Buffer[BytesSent]);
> +    BytesSent++;
> +  }
> +
> +  return BytesSent;
> +}
> +
> +/**
> +  Read data from serial device and save the datas in buffer.
> +
> +  Reads NumberOfBytes data bytes from a serial device into the buffer
> +  specified by Buffer. The number of bytes actually read is returned.
> +  If the return value is less than NumberOfBytes, then the rest operation failed.
> +  If Buffer is NULL, then ASSERT().
> +  If NumberOfBytes is zero, then return 0.
> +
> +  @param  Buffer            Pointer to the data buffer to store the data read
> +                            from the serial device.
> +  @param  NumberOfBytes     Number of bytes which will be read.
> +
> +  @retval 0                 Read data failed, No data is to be read.
> +  @retval >0                Actual number of bytes read from serial device.
> +
> +**/
> +UINTN
> +EFIAPI
> +SerialPortRead (
> +  OUT UINT8   *Buffer,
> +  IN  UINTN   NumberOfBytes
> +  )
> +{
> +  MX6UART_REGISTERS   *UartBase;
> +  UINTN               BytesRead;
> +  UINT32              Rxd;
> +
> +  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
> +  BytesRead = 0;
> +  while (BytesRead < NumberOfBytes) {
> +    Rxd = MmioRead32 ((UINTN)&UartBase->Rxd);
> +    if ((Rxd & MX6UART_RXD_CHARRDY) == 0) {
> +      break;
> +    }
> +
> +    Buffer[BytesRead] = (UINT8) (Rxd & MX6UART_RXD_RX_DATA_MASK);
> +    BytesRead++;
> +  }
> +
> +  return BytesRead;
> +}
> +
> +/**
> +  Polls a serial device to see if there is any data waiting to be read.
> +
> +  Polls a serial device to see if there is any data waiting to be read.
> +  If there is data waiting to be read from the serial device, then TRUE is
> +  returned.
> +  If there is no data waiting to be read from the serial device, then FALSE is
> +  returned.
> +
> +  @retval TRUE          Data is waiting to be read from the serial device.
> +  @retval FALSE         There is no data waiting to be read from the serial device.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +SerialPortPoll (
> +  VOID
> +  )
> +{
> +  MX6UART_REGISTERS *UartBase;
> +  UINT32 Usr2;
> +
> +  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
> +  Usr2 = MmioRead32 ((UINTN)&UartBase->Usr2);
> +  return (Usr2 & MX6UART_USR2_RDR) != 0;
> +}
> +
> +/**
> +  Sets the control bits on a serial device.
> +
> +  @param Control                Sets the bits of Control that are settable.
> +
> +  @retval RETURN_UNSUPPORTED    The serial device does not support this operation.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +SerialPortSetControl (
> +  IN UINT32   Control
> +  )
> +{
> +  return RETURN_UNSUPPORTED;
> +}
> +
> +/**
> +  Retrieve the status of the control bits on a serial device.
> +
> +  @param Control                A pointer to return the current control signals
> +                                from the serial device.
> +
> +  @retval RETURN_UNSUPPORTED    The serial device does not support this operation.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +SerialPortGetControl (
> +  OUT UINT32  *Control
> +  )
> +{
> +  return RETURN_UNSUPPORTED;
> +}
> +
> +/**
> +  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
> +  data bits, and stop bits on a serial device.
> +
> +  @param BaudRate           The requested baud rate. A BaudRate value of 0 will
> +                            use the device's default interface speed.
> +                            On output, the value actually set.
> +  @param ReveiveFifoDepth   The requested depth of the FIFO on the receive side
> +                            of the serial interface. A ReceiveFifoDepth value
> +                            of 0 will use the device's default FIFO depth.
> +                            On output, the value actually set.
> +  @param Timeout            The requested time out for a single character in
> +                            microseconds. This timeout applies to both the
> +                            transmit and receive side of the interface. A
> +                            Timeout value of 0 will use the device's default
> +                            timeout value.
> +                            On output, the value actually set.
> +  @param Parity             The type of parity to use on this serial device. A
> +                            Parity value of DefaultParity will use the device's
> +                            default parity value.
> +                            On output, the value actually set.
> +  @param DataBits           The number of data bits to use on the serial device.
> +                            A DataBits value of 0 will use the device's default
> +                            data bit setting.
> +                            On output, the value actually set.
> +  @param StopBits           The number of stop bits to use on this serial device.
> +                            A StopBits value of DefaultStopBits will use the
> +                            device's default number of stop bits.
> +                            On output, the value actually set.
> +
> +  @retval RETURN_UNSUPPORTED        The serial device does not support this operation.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +SerialPortSetAttributes (
> +  IN OUT UINT64             *BaudRate,
> +  IN OUT UINT32             *ReceiveFifoDepth,
> +  IN OUT UINT32             *Timeout,
> +  IN OUT EFI_PARITY_TYPE    *Parity,
> +  IN OUT UINT8              *DataBits,
> +  IN OUT EFI_STOP_BITS_TYPE *StopBits
> +  )
> +{
> +  return RETURN_UNSUPPORTED;
> +}
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
> new file mode 100644
> index 000000000000..9f381b199f38
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = SerialPortLib
> +  FILE_GUID                      = C22D85E6-8B3E-4c05-AA5B-5732F3ACD055
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = SerialPortLib
> +
> +[Sources.common]
> +  UartSerialPortLib.c
> +
> +[LibraryClasses]
> +  ArmLib
> +  BaseMemoryLib
> +  CacheMaintenanceLib
> +  IoLib
> +  PcdLib
> +  TimerLib
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[FixedPcd]
> +  giMXPlatformTokenSpaceGuid.PcdSerialRegisterBase
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-10-31 20:43   ` Leif Lindholm
@ 2018-11-01 10:55     ` Sumit Garg
  2018-11-02  0:41       ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Sumit Garg @ 2018-11-01 10:55 UTC (permalink / raw)
  To: Christopher.Co, Leif Lindholm
  Cc: edk2-devel, Ard Biesheuvel, Michael D Kinney

Hi Christopher,

Optee Client library has recently been merged to edk2 source code. It
tries to provide a generic interface [1] to OP-TEE based trusted
applications (pseudo/early).

AFAIK, you don't need any platform specific hook in client interface
to work with upstream OP-TEE. So instead you should use Optee library.

[1] https://github.com/tianocore/edk2/blob/master/ArmPkg/Include/Library/OpteeLib.h

Regards,
Sumit

On Thu, 1 Nov 2018 at 02:13, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>
> +Sumit (just to loop you two together). Is there anything Microsoft
> platform specific about what will go in here?
>
> /
>     Leif
>
> On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > On Windows IoT Core devices with ARM TrustZone capabilities,
> > EDK2 runs in normal world and we use OP-TEE to execute
> > secure world operations. The overall package will contain
> > client-side support to invoke EDK2 services implemented as
> > OP-TEE trusted applications that run in secure world.
> >
> > This commit adds the initial dec file to add some PCD settings
> > needed by other packages.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > ---
> >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49 ++++++++++++++++++++
> >  1 file changed, 49 insertions(+)
> >
> > diff --git a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > new file mode 100644
> > index 000000000000..4752eab39ce3
> > --- /dev/null
> > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > @@ -0,0 +1,49 @@
> > +## @file
> > +#
> > +#  OP-TEE client package
> > +#
> > +#  OP-TEE client package contains the client-side interface to invoke OP-TEE TAs.
> > +#  Certain EDKII services are implemented in Trusted Applications running in
> > +#  the secure world OP-TEE OS.
> > +#
> > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +#
> > +#  This program and the accompanying materials
> > +#  are licensed and made available under the terms and conditions of the BSD License
> > +#  which accompanies this distribution.  The full text of the license may be found at
> > +#  http://opensource.org/licenses/bsd-license.php
> > +#
> > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> > +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> > +#
> > +##
> > +
> > +[Defines]
> > +  DEC_SPECIFICATION              = 0x0001001A
> > +  PACKAGE_NAME                   = OpteeClientPkg
> > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-1bdd74ec9595
> > +  PACKAGE_VERSION                = 0.01
> > +
> > +[Includes]
> > +
> > +[LibraryClasses]
> > +
> > +[Guids]
> > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, { 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > +
> > +[PcdsFixedAtBuild]
> > +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x00000005
> > +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x00000006
> > +
> > +  ## The base address of the Trust Zone OpTEE OS private memory region
> > +  # This memory is manager privately by the OpTEE OS.
> > +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD1|UINT64|0x00000001
> > +
> > +  ## The size of the Trust Zone OpTEE OS private memory region
> > +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UINT64|0x00000002
> > +
> > +  ## The base address of the Trust Zone OpTEE OS shared memory region
> > +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2|UINT64|0x00000003
> > +
> > +  ## The size of the Trust Zone OpTEE OS shared memory region
> > +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UINT64|0x00000004
> > --
> > 2.16.2.gvfs.1.33.gf5370f1
> >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 06/27] Silicon/NXP: Add I2C library support for i.MX platforms
  2018-09-21  8:25 ` [PATCH edk2-platforms 06/27] Silicon/NXP: Add I2C " Chris Co
@ 2018-11-01 17:53   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-11-01 17:53 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:25:57AM +0000, Chris Co wrote:
> This adds support for I2C controller on NXP i.MX platforms.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h             | 162 +++++++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c   | 487 ++++++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf |  35 ++
>  3 files changed, 684 insertions(+)
> 
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
> new file mode 100644
> index 000000000000..de8a1616fe1b
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
> @@ -0,0 +1,162 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX_I2C_H_
> +#define _IMX_I2C_H_
> +
> +#pragma pack(push, 1)

I don't see where below this has any effect.
If not required, please drop.

> +
> +typedef union {
> +  UINT16 AsUint16;

Not super happy with this name.
Could it be just "Raw"? (That pattern is used frequently in EDK2.)
Same applies to similar situations below.

> +  struct {
> +    UINT16 Reserved0 : 1;
> +    UINT16 ADR : 7;
> +    UINT16 Reserved1 : 8;
> +  };
> +} IMX_I2C_IADR_REG;

IADR is the name I guess, but REG should ideally be fully written out
as REGISTER.

> +
> +typedef union {
> +  UINT16 AsUint16;
> +  struct {
> +    UINT16 IC : 6;
> +    UINT16 Reserved0 : 10;
> +  };
> +} IMX_I2C_IFDR_REG;
> +
> +typedef union {
> +  UINT16 AsUint16;
> +  struct {
> +    UINT16 Reserved0 : 2;
> +    UINT16 RSTA : 1;
> +    UINT16 TXAK : 1;
> +    UINT16 MTX : 1;
> +    UINT16 MSTA : 1;
> +    UINT16 IIEN : 1;
> +    UINT16 IEN : 1;
> +    UINT16 Reserved1 : 8;
> +  };
> +} IMX_I2C_I2CR_REG;
> +
> +#define IMX_I2C_I2SR_RXAK        0x0001
> +#define IMX_I2C_I2SR_IIF         0x0002
> +#define IMX_I2C_I2SR_SRW         0x0004
> +#define IMX_I2C_I2SR_IAL         0x0010
> +#define IMX_I2C_I2SR_IBB         0x0020
> +#define IMX_I2C_I2SR_IAAS        0x0040
> +#define IMX_I2C_I2SR_ICF         0x0080
> +
> +typedef union {
> +  UINT16 AsUint16;
> +  struct {
> +    UINT16 RXAK : 1;
> +    UINT16 IIF : 1;
> +    UINT16 SRW : 1;
> +    UINT16 Reserved0 : 1;
> +    UINT16 IAL : 1;
> +    UINT16 IBB : 1;
> +    UINT16 IAAS : 1;
> +    UINT16 ICF : 1;
> +    UINT16 Reserved1 : 8;
> +  };
> +} IMX_I2C_I2SR_REG;
> +
> +typedef union {
> +  UINT16 AsUint16;
> +  struct {
> +    UINT16 DATA : 8;
> +    UINT16 Reserved0 : 8;
> +  };
> +} IMX_I2C_I2DR_REG;
> +
> +typedef struct {
> +  IMX_I2C_IADR_REG IADR;
> +  UINT16 Pad0;
> +  IMX_I2C_IFDR_REG IFDR;
> +  UINT16 Pad1;
> +  IMX_I2C_I2CR_REG I2CR;
> +  UINT16 Pad2;
> +  IMX_I2C_I2DR_REG I2SR;
> +  UINT16 Pad3;
> +  IMX_I2C_I2DR_REG I2DR;
> +  UINT16 Pad4;
> +} IMX_I2C_REGS;

And here, REGISTERS.

> +
> +#pragma pack(pop)
> +
> +typedef struct {
> +  UINT32 ControllerAddress;
> +  UINT32 ControllerSlaveAddress;
> +  UINT32 ReferenceFreq;
> +  UINT32 TargetFreq;
> +  UINT32 SlaveAddress;
> +  UINT32 TimeoutInUs;
> +} IMX_I2C_CONFIG;
> +
> +typedef struct {
> +  UINT32 Divider;
> +  UINT32 IC;

Please expand to CamelCase.
It's not obvious what IC stands for.

> +} IMX_I2C_DIVIDER;
> +
> +/**
> +  Perform I2C read operation.
> +
> +  The iMXI2cRead perform I2C read operation by programming the I2C controller.
> +  The caller is responsible to provide I2C controller configuration.
> +
> +  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
> +                                  I2C controller to be used for I2C operation.
> +  @param[in]    RegisterAddress   Targeted device register address to start read.
> +  @param[out]   ReadBufferPtr     Caller supplied buffer that would be written
> +                                  into with data from the read operation.
> +  @param[in]    ReadBufferSize    Size of caller supplied buffer.
> +
> +  @retval   RETURN_SUCCESS        I2C Read operation succeeded.
> +  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
> +
> +**/
> +RETURN_STATUS
> +iMXI2cRead (
> +  IN IMX_I2C_CONFIG  *I2cConfigPtr,
> +  IN UINT8            RegisterAddress,
> +  OUT UINT8          *ReadBufferPtr,
> +  IN UINT32           ReadBufferSize
> +  );
> +
> +/**
> +  Perform I2C write operation.
> +
> +  The iMXI2cWrite perform I2C write operation by programming the I2C
> +  controller. The caller is responsible to provide I2C controller
> +  configuration.
> +
> +  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
> +                                  I2C controller to be used for I2C operation.
> +  @param[in]    RegisterAddress   Targeted device register address to start write.
> +  @param[out]   WriteBufferPtr    Caller supplied buffer that contained data that
> +                                  would be read from for I2C write operation.
> +  @param[in]    WriteBufferSize   Size of caller supplied buffer.
> +
> +  @retval   RETURN_SUCCESS        I2C Write operation succeeded.
> +  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
> +
> +**/
> +RETURN_STATUS
> +iMXI2cWrite (
> +  IN IMX_I2C_CONFIG  *I2cConfigPtr,
> +  IN UINT8            RegisterAddress,
> +  IN UINT8           *WriteBufferPtr,
> +  IN UINT32           WriteBufferSize
> +  );
> +
> +#endif
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
> new file mode 100644
> index 000000000000..6cfe04dba571
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
> @@ -0,0 +1,487 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Base.h>
> +#include <Uefi.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include <iMXI2cLib.h>
> +
> +IMX_I2C_DIVIDER DividerValue[] = {

Global variable should have 'm' prefix if scope is this module or 'g'
if external visibility. If only this file, please also make it STATIC.

I'm not super happy about these live-coded values, but I guess adding
a bunch of defines wouldn't help much. But could you add a comment
block explaining roughly what the fields mean?

> +  { 22, 0x20, },

Please drop the second ',' on all lines - IMX_I2C_DIVIDER only has two
structure members.

> +  { 24, 0x21, },
> +  { 26, 0x22, },
> +  { 28, 0x23, },
> +  { 30, 0x00, },
> +  { 32, 0x24, },
> +  { 36, 0x25, },
> +  { 40, 0x26, },
> +  { 42, 0x03, },
> +  { 44, 0x27, },
> +  { 48, 0x28, },
> +  { 52, 0x05, },
> +  { 56, 0x29, },
> +  { 60, 0x06, },
> +  { 64, 0x2A, },
> +  { 72, 0x2B, },
> +  { 80, 0x2C, },
> +  { 88, 0x09, },
> +  { 96, 0x2D, },
> +  { 104, 0x0A, },
> +  { 112, 0x2E, },
> +  { 128, 0x2F, },
> +  { 144, 0x0C, },
> +  { 160, 0x30, },
> +  { 192, 0x31, },
> +  { 224, 0x32, },
> +  { 240, 0x0F, },
> +  { 256, 0x33, },
> +  { 288, 0x10, },
> +  { 320, 0x34, },
> +  { 384, 0x35, },
> +  { 448, 0x36, },
> +  { 480, 0x13, },
> +  { 512, 0x37, },
> +  { 576, 0x14, },
> +  { 640, 0x38, },
> +  { 768, 0x39, },
> +  { 896, 0x3A, },
> +  { 960, 0x17, },
> +  { 1024, 0x3B, },
> +  { 1152, 0x18, },
> +  { 1280, 0x3C, },
> +  { 1536, 0x3D, },
> +  { 1792, 0x3E, },
> +  { 1920, 0x1B, },
> +  { 2048, 0x3F, },
> +  { 2304, 0x1C, },
> +  { 2560, 0x1D, },
> +  { 3072, 0x1E, },
> +  { 3840, 0x1F, },
> +};
> +
> +#define DIVIDER_VALUE_TOTAL (sizeof(DividerValue) / sizeof(DividerValue[0]))

Can use BaseLib ARRAY_SIZE macro instead of adding this custom one.

> +
> +BOOLEAN
> +iMXI2cWaitStatusSet (
> +  IN  IMX_I2C_CONFIG   *I2cConfigPtr,
> +  IN  UINT16           StatusBits
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  UINT32            Counter;
> +  IMX_I2C_I2SR_REG  I2srReg;

Same as for previous patch - no need to name the variable after the
register it's initialised from.

> +
> +  Counter = I2cConfigPtr->TimeoutInUs;
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +  while (Counter) {
> +    I2srReg = (IMX_I2C_I2SR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2SR);
> +    if ((I2srReg.AsUint16 & StatusBits) == StatusBits) {
> +      return TRUE;
> +    }
> +    MicroSecondDelay (1);
> +    --Counter;
> +  }
> +
> +  return FALSE;
> +}
> +
> +BOOLEAN
> +iMXI2cWaitStatusUnSet (
> +  IN  IMX_I2C_CONFIG   *I2cConfigPtr,
> +  IN  UINT16           StatusBits
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  UINT32            Counter;
> +  IMX_I2C_I2SR_REG  I2srReg;
> +
> +  Counter = I2cConfigPtr->TimeoutInUs;
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +  while (Counter) {
> +    I2srReg = (IMX_I2C_I2SR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2SR);
> +    if ((I2srReg.AsUint16 & StatusBits) == 0) {
> +      return TRUE;
> +    }
> +    MicroSecondDelay (1);
> +    --Counter;
> +  }
> +
> +  return FALSE;
> +}
> +
> +BOOLEAN
> +iMXI2cSendByte (
> +  IN  IMX_I2C_CONFIG  *I2cConfigPtr,
> +  IN  UINT8           Data
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  UINT32            Counter;
> +  IMX_I2C_I2SR_REG  I2srReg;
> +  UINT16            SendData;
> +
> +  SendData = Data;
> +  Counter = I2cConfigPtr->TimeoutInUs;
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +
> +  // Clear status and transfer byte
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2DR, SendData);
> +
> +  while (Counter) {
> +    I2srReg = (IMX_I2C_I2SR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2SR);
> +    if (I2srReg.IIF == 1) {

What does it mean if it's == 1? Can that 1 be given a descriptively
named #define?

> +      return TRUE;
> +    } else if (I2srReg.IAL == 1) {

What does it mean if it's == 1? Can that 1 be given a descriptively
named #define?

> +      DEBUG ((DEBUG_ERROR, "iMXI2cSendByte: fail 0x%04x\n", I2srReg.AsUint16));
> +      return FALSE;
> +    }
> +    MicroSecondDelay (1);
> +    --Counter;
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "iMXI2cSendByte: Fail timeout\n"));
> +  return FALSE;
> +}
> +
> +RETURN_STATUS
> +iMXI2cSetupController (
> +  IN  IMX_I2C_CONFIG *I2cConfigPtr
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  UINT32            Divider;
> +  UINT32            DividerCount;
> +  UINT32            IfdrDiv;
> +  IMX_I2C_I2CR_REG  I2crReg;
> +
> +  I2cRegsPtr = (IMX_I2C_REGS *)I2cConfigPtr->ControllerAddress;
> +
> +  // Disable controller and clear any pending interrupt
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, 0);
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);

A comment as to which operation does which?

> +
> +  // Setup Divider if reference freq is provided. If no, use value setup by
> +  // 1st boot loader

first

> +  if (I2cConfigPtr->ReferenceFreq != 0) {
> +    IfdrDiv = 0;
> +    Divider = I2cConfigPtr->ReferenceFreq / I2cConfigPtr->TargetFreq;
> +
> +    for (DividerCount = 0; DividerCount < DIVIDER_VALUE_TOTAL; ++DividerCount) {
> +      if (DividerValue[DividerCount].Divider >= Divider) {
> +        DEBUG ((
> +                 DEBUG_INFO,
> +                 "iMXI2cSetupController: Divider %d IC 0x%02x\n",
> +                 DividerValue[DividerCount].Divider,
> +                 DividerValue[DividerCount].IC));
> +        IfdrDiv = DividerValue[DividerCount].IC;
> +        break;
> +      }
> +    }
> +
> +    if (IfdrDiv == 0) {
> +      DEBUG ((
> +               DEBUG_ERROR,
> +               "iMXI2cSetupController: could not find Divider for %d\n",
> +               Divider));
> +      return RETURN_INVALID_PARAMETER;
> +    }
> +
> +    MmioWrite16 ((UINTN)&I2cRegsPtr->IFDR, IfdrDiv);
> +  }
> +
> +  // Setup slave address
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->IADR,
> +               (I2cConfigPtr->ControllerSlaveAddress << 1));

Why the shift by 1? Could this use a macro?

> +
> +  // Enable controller and set to master mode.
> +  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
> +
> +  // This bit must be set before any other I2C_I2CR bits have an effect

Why?

> +  I2crReg.IEN = 1;
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);

What does this write do?

> +  MicroSecondDelay (100);
> +
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);

Why this write of 0?

> +
> +  // Wait for bus to be idle
> +  if (iMXI2cWaitStatusUnSet (I2cConfigPtr, IMX_I2C_I2SR_IBB) == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStart: Controller remains busy\n"));
> +    return RETURN_DEVICE_ERROR;
> +  }
> +
> +  I2crReg.MSTA = 1;

What does 1 mean?

> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);

What does this write do?

> +
> +  // Now wait for bus to be busy
> +  if (iMXI2cWaitStatusSet (I2cConfigPtr, IMX_I2C_I2SR_IBB) == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStart: Controller remains idle\n"));
> +    return RETURN_DEVICE_ERROR;
> +  }
> +
> +  return RETURN_SUCCESS;
> +}
> +
> +RETURN_STATUS
> +iMXI2cGenerateStart (
> +  IN  IMX_I2C_CONFIG  *I2cConfigPtr,
> +  IN  UINT8           RegisterAddress
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  IMX_I2C_I2CR_REG  I2crReg;
> +  BOOLEAN           Result;
> +  RETURN_STATUS     Status;
> +
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +  Status = iMXI2cSetupController (I2cConfigPtr);
> +  if (RETURN_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStart: Fail to setup controller %r\n",
> +            Status));
> +    return Status;
> +  }
> +
> +  // Set controller to transmit mode
> +  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
> +  I2crReg.MTX = 1;
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
> +
> +  Result = iMXI2cSendByte (I2cConfigPtr, (I2cConfigPtr->SlaveAddress << 1));

Shift? Macro?

> +  if (Result == FALSE) {
> +    DEBUG ((
> +             DEBUG_ERROR,
> +             "iMXI2cGenerateStart: Slave address transfer fail 0x%04x\n",
> +             MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
> +    return RETURN_DEVICE_ERROR;
> +  }
> +
> +  // Send slave register address
> +  Result = iMXI2cSendByte (I2cConfigPtr, RegisterAddress);
> +  if (Result == FALSE) {
> +    DEBUG ((
> +             DEBUG_ERROR,
> +             "iMXI2cGenerateStart: Slave register address transfer fail 0x%04x\n",
> +             MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
> +    return RETURN_DEVICE_ERROR;
> +  }
> +
> +  return RETURN_SUCCESS;
> +}
> +
> +RETURN_STATUS
> +iMXI2cGenerateStop (
> +  IN  IMX_I2C_CONFIG *I2cConfigPtr
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  IMX_I2C_I2CR_REG  I2crReg;
> +
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
> +  I2crReg.MSTA = 0;

I'm getting to the point where I am wanting these fields to be given
useful names. An awful lot of #defines and comments will be necessary
otherwise.

> +  I2crReg.MTX = 0;
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
> +
> +  // Bus should go idle
> +  if (iMXI2cWaitStatusUnSet (I2cConfigPtr, IMX_I2C_I2SR_IBB) == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cGenerateStop: Controller remains busy\n"));
> +    return RETURN_DEVICE_ERROR;
> +  }
> +
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Perform I2C read operation.
> +
> +  The iMXI2cRead perform I2C read operation by programming the I2C controller.
> +  The caller is responsible to provide I2C controller configuration.
> +
> +  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
> +                                  I2C controller to be used for I2C operation.
> +  @param[in]    RegisterAddress   Targeted device register address to start read.
> +  @param[out]   ReadBufferPtr     Caller supplied buffer that would be written
> +                                  into with data from the read operation.
> +  @param[in]    ReadBufferSize    Size of caller supplied buffer.
> +
> +  @retval   RETURN_SUCCESS        I2C Read operation succeeded.
> +  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
> +
> +**/
> +RETURN_STATUS
> +iMXI2cRead (
> +  IN IMX_I2C_CONFIG  *I2cConfigPtr,
> +  IN UINT8            RegisterAddress,
> +  OUT UINT8          *ReadBufferPtr,
> +  IN UINT32           ReadBufferSize
> +  )
> +{
> +  IMX_I2C_REGS      *I2cRegsPtr;
> +  IMX_I2C_I2CR_REG  I2crReg;
> +  BOOLEAN           Result;
> +  RETURN_STATUS     Status;
> +
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +  Status = iMXI2cGenerateStart (I2cConfigPtr, RegisterAddress);
> +  if (RETURN_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cRead: iMXI2cGenerateStart failed %r\n", Status));
> +    goto Exit;
> +  }
> +
> +  // Send slave address again to begin read
> +  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
> +  I2crReg.RSTA = 1; // Repeated start
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
> +  Result = iMXI2cSendByte (
> +              I2cConfigPtr,
> +              (I2cConfigPtr->SlaveAddress << 1 | 1));

| 1 - the plot thickens.
Macro please.

> +  if (Result == FALSE) {
> +    DEBUG ((
> +              DEBUG_ERROR,
> +              "iMXI2cRead: 2nd Slave address transfer failed 0x%04x\n",
> +              MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
> +    Status = RETURN_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Disable master mode
> +  I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
> +
> +  // NXP application note AN4481 - Only one byte so do not send acknowledge
> +  if (ReadBufferSize == 1) {
> +    I2crReg.TXAK = 1;
> +  } else {
> +    I2crReg.TXAK = 0;
> +  }
> +
> +  I2crReg.MTX = 0;
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
> +
> +  // A data transfer can now be initiated by a read from I2C_I2DR in Slave
> +  // Receive mode.
> +  MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);
> +  MmioRead16 ((UINTN)&I2cRegsPtr->I2DR);
> +
> +  do {
> +    // Wait for transfer to complete
> +    if (iMXI2cWaitStatusSet (I2cConfigPtr, IMX_I2C_I2SR_IIF) == FALSE) {
> +      DEBUG ((DEBUG_ERROR, "iMXI2cRead: waiting for read fail\n"));
> +      Status = RETURN_DEVICE_ERROR;
> +      goto Exit;
> +    }
> +
> +    if (iMXI2cWaitStatusSet (I2cConfigPtr, IMX_I2C_I2SR_ICF) == FALSE) {
> +      DEBUG ((DEBUG_ERROR, "iMXI2cRead: waiting for read fail\n"));
> +      Status = RETURN_DEVICE_ERROR;
> +      goto Exit;
> +    }
> +
> +    // Before the last byte is read, a Stop signal must be generated
> +    if (ReadBufferSize == 1) {
> +      Status = iMXI2cGenerateStop (
> +                 I2cConfigPtr);

No need to wrap this line.

> +      if (RETURN_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "iMXI2cRead: iMXI2cGenerateStop fail %r\n", Status));
> +        goto Exit;
> +      }
> +    }
> +
> +    if (ReadBufferSize == 2) {

For second to last byte?
Could use a comment. And possibly comment above at == 1 could be
expanded to explain why.

> +      I2crReg = (IMX_I2C_I2CR_REG)MmioRead16 ((UINTN)&I2cRegsPtr->I2CR);
> +      I2crReg.TXAK = 1;

What does this 1 mean? #define?

> +      MmioWrite16 ((UINTN)&I2cRegsPtr->I2CR, I2crReg.AsUint16);
> +    }
> +
> +    MmioWrite16 ((UINTN)&I2cRegsPtr->I2SR, 0);

Why write 0?

> +
> +    *ReadBufferPtr = MmioRead8 ((UINTN)&I2cRegsPtr->I2DR);
> +    ++ReadBufferPtr;
> +    --ReadBufferSize;
> +  } while (ReadBufferSize > 0);
> +
> +Exit:
> +  Status = iMXI2cGenerateStop (I2cConfigPtr);
> +  if (RETURN_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cRead: Final iMXI2cGenerateStop fail %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Perform I2C write operation.
> +
> +  The iMXI2cWrite perform I2C write operation by programming the I2C
> +  controller. The caller is responsible to provide I2C controller
> +  configuration.
> +
> +  @param[in]    IMX_I2C_CONFIG    Pointer to structure containing the targeted
> +                                  I2C controller to be used for I2C operation.
> +  @param[in]    RegisterAddress   Targeted device register address to start write.
> +  @param[out]   WriteBufferPtr    Caller supplied buffer that contained data that
> +                                  would be read from for I2C write operation.
> +  @param[in]    WriteBufferSize   Size of caller supplied buffer.
> +
> +  @retval   RETURN_SUCCESS        I2C Write operation succeeded.
> +  @retval   RETURN_DEVICE_ERROR   The I2C device is not functioning correctly.
> +
> +**/
> +RETURN_STATUS
> +iMXI2cWrite (
> +  IN IMX_I2C_CONFIG  *I2cConfigPtr,
> +  IN UINT8            RegisterAddress,
> +  IN UINT8           *WriteBufferPtr,
> +  IN UINT32           WriteBufferSize
> +  )
> +{
> +  IMX_I2C_REGS    *I2cRegsPtr;
> +  BOOLEAN         Result;
> +  RETURN_STATUS   Status;
> +
> +  I2cRegsPtr = (IMX_I2C_REGS*)I2cConfigPtr->ControllerAddress;
> +  Status = iMXI2cGenerateStart (I2cConfigPtr, RegisterAddress);
> +  if (RETURN_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cWrite: iMXI2cGenerateStart fail %r\n", Status));
> +    goto Exit;
> +  }
> +
> +  while (WriteBufferSize > 0) {
> +    Result = iMXI2cSendByte (I2cConfigPtr, *WriteBufferPtr);
> +    if (Result == FALSE) {
> +      DEBUG ((
> +               DEBUG_ERROR,

Could skip that line break.

/
    Leif

> +               "iMXI2cWrite: Slave address transfer fail 0x%04x\n",
> +               MmioRead16 ((UINTN)&I2cRegsPtr->I2SR)));
> +      Status = RETURN_DEVICE_ERROR;
> +      goto Exit;
> +    }
> +
> +    ++WriteBufferPtr;
> +    --WriteBufferSize;
> +  }
> +
> +Exit:
> +  Status = iMXI2cGenerateStop (I2cConfigPtr);
> +  if (RETURN_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "iMXI2cWrite: iMXI2cGenerateStop fail %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
> new file mode 100644
> index 000000000000..ad968e88b1da
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = iMXI2cLib
> +  FILE_GUID                      = C4E4A003-8AEB-4C9B-8E72-D2BAD2134BDE
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = iMXI2cLib
> +
> +[Packages]
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  IoLib
> +  TimerLib
> +
> +[Sources.common]
> +  iMXI2cLib.c
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support
  2018-09-21  8:25 ` [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support Chris Co
@ 2018-11-01 18:05   ` Leif Lindholm
  2018-11-29  0:55     ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-11-01 18:05 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:25:58AM +0000, Chris Co wrote:
> This adds support for processing EDID data on NXP i.MX platforms.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h                    | 114 +++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c   | 152 ++++++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf |  31 ++++
>  3 files changed, 297 insertions(+)
> 
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
> new file mode 100644
> index 000000000000..70ef8d0af97f
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
> @@ -0,0 +1,114 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef __IMX_DISPLAY_H__
> +#define __IMX_DISPLAY_H__
> +
> +#define EDID_MIN_SIZE       128
> +#define EDID_I2C_ADDRESS    0x50

Are all of these #defines and functions called only from within iMX
platform code?

> +
> +// The first DTD is the preferred timing, refer to 3.1 VESA EDID spec.
> +#define EDID_DTD_1_OFFSET   0x36
> +#define EDID_DTD_2_OFFSET   0x48
> +#define EDID_DTD_3_OFFSET   0x5A
> +#define EDID_DTD_4_OFFSET   0x6C
> +
> +typedef enum {
> +  PIXEL_FORMAT_ARGB32,
> +  PIXEL_FORMAT_BGRA32,
> +} PIXEL_FORMAT;
> +
> +typedef struct _DISPLAY_TIMING {
> +  UINT32 PixelClock;
> +  UINT32 HActive;
> +  UINT32 HBlank;
> +  UINT32 VActive;
> +  UINT32 VBlank;
> +  UINT32 HSync;
> +  UINT32 VSync;
> +  UINT32 HSyncOffset;
> +  UINT32 VSyncOffset;
> +  UINT32 HImageSize;
> +  UINT32 VImageSize;
> +  UINT32 HBorder;
> +  UINT32 VBorder;
> +  UINT32 EdidFlags;
> +  UINT32 Flags;
> +  UINT32 PixelRepetition;
> +  UINT32 Bpp;
> +  PIXEL_FORMAT PixelFormat;
> +} DISPLAY_TIMING, *PDISPLAY_TIMING, DTD;
> +
> +typedef struct _DETAILED_TIMING_DESCRIPTOR {
> +  UINT8 PixelClock[2];
> +  UINT8 HActive;
> +  UINT8 HBlank;
> +  UINT8 HActiveBlank;
> +  UINT8 VActive;
> +  UINT8 VBlank;
> +  UINT8 VActiveBlank;
> +  UINT8 HSyncOffset;
> +  UINT8 HSyncWidth;
> +  UINT8 VSyncOffsetWidth;
> +  UINT8 HVOffsetWidth;
> +  UINT8 HImageSize;
> +  UINT8 VImageSize;
> +  UINT8 HVImageSize;
> +  UINT8 HBorder;
> +  UINT8 VBorder;
> +  UINT8 EdidFlags;
> +} DETAILED_TIMING_DESCRIPTOR, *PDETAILED_TIMING_DESCRIPTOR;
> +
> +/**
> +  Convert detailed timing descriptor to display timing format
> +
> +  @param[in]    DTDPtr            Pointer to detailed timing descriptor.
> +  @param[out]   DisplayTimingPtr  Pointer to display timing structure.
> +
> +  @retval   EFI_SUCCESS   Detailed timing descriptor data was converted.
> +
> +**/
> +EFI_STATUS
> +ConvertDTDToDisplayTiming (
> +  IN DETAILED_TIMING_DESCRIPTOR   *DTDPtr,
> +  OUT DISPLAY_TIMING              *DisplayTimingPtr
> +  );
> +
> +/**
> +  Debug dump of Display Timing structure
> +
> +  @param[in]    DisplayTimingNamePtr  Name of display timing structure.
> +  @param[in]    DisplayTimingPtr      Pointer to display timing structure.
> +**/
> +VOID
> +PrintDisplayTiming (
> +  IN CHAR8            *DisplayTimingNamePtr,
> +  IN DISPLAY_TIMING   *DisplayTimingPtr
> +  );
> +
> +/**
> +  Check if EDID is valid
> +
> +  @param[in]    EdidDataPtr  Pointer to EDID data.
> +
> +  @retval   EFI_SUCCESS             EDID data is a valid EDID.
> +  @retval   EFI_INVALID_PARAMETER   EDID data is invalid.
> +
> +**/
> +EFI_STATUS
> +ValidateEdidData (
> +  IN UINT8 *EdidDataPtr
> +  );
> +
> +#endif // __IMX_DISPLAY_H__
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
> new file mode 100644
> index 000000000000..9e90ece96260
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
> @@ -0,0 +1,152 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/DebugLib.h>
> +
> +#include <iMXDisplay.h>
> +
> +/**
> +  Convert detailed timing descriptor to display timing format
> +
> +  @param[in]    DTDPtr            Pointer to detailed timing descriptor.
> +  @param[out]   DisplayTimingPtr  Pointer to display timing structure.
> +
> +  @retval   EFI_SUCCESS   Detailed timing descriptor data was converted.
> +
> +**/
> +EFI_STATUS
> +ConvertDTDToDisplayTiming (
> +  IN DETAILED_TIMING_DESCRIPTOR   *DTDPtr,
> +  OUT DISPLAY_TIMING              *DisplayTimingPtr
> +  )
> +{
> +  UINT32  edidPixelClock;

e -> E.

> +
> +  DEBUG ((DEBUG_INFO, "++ConvertDTDToDisplayTiming()\r\n"));

Please use %a and __FUNCTION__ instead of hard-coding function name.

> +  // Refer to 3.10.2 VESA EDID spec
> +  edidPixelClock = (DTDPtr->PixelClock[0] | (DTDPtr->PixelClock[1] << 8));
> +  DisplayTimingPtr->PixelClock = edidPixelClock * 10000;
> +  DisplayTimingPtr->HActive = (DTDPtr->HActiveBlank & 0xF0);
> +  DisplayTimingPtr->HActive = (DisplayTimingPtr->HActive << 4) | DTDPtr->HActive;
> +  DisplayTimingPtr->HBlank = (DTDPtr->HActiveBlank & 0x0F);
> +  DisplayTimingPtr->HBlank = (DisplayTimingPtr->HBlank << 8) | DTDPtr->HBlank;
> +  DisplayTimingPtr->VActive = (DTDPtr->VActiveBlank & 0xF0);
> +  DisplayTimingPtr->VActive = (DisplayTimingPtr->VActive << 4) | DTDPtr->VActive;
> +  DisplayTimingPtr->VBlank = (DTDPtr->VActiveBlank & 0x0F);
> +  DisplayTimingPtr->VBlank = (DisplayTimingPtr->VBlank << 8) | DTDPtr->VBlank;
> +  DisplayTimingPtr->HSyncOffset = (DTDPtr->HVOffsetWidth & 0xC0);
> +  DisplayTimingPtr->HSyncOffset = (DisplayTimingPtr->HSyncOffset << 2) |
> +                                  DTDPtr->HSyncOffset;
> +  DisplayTimingPtr->VSyncOffset = (DTDPtr->HVOffsetWidth & 0x0C);
> +  DisplayTimingPtr->VSyncOffset = (DisplayTimingPtr->VSyncOffset << 2) |
> +                                  ((DTDPtr->VSyncOffsetWidth & 0xF0) >> 4);
> +  DisplayTimingPtr->HSync = (DTDPtr->HVOffsetWidth & 0x30);
> +  DisplayTimingPtr->HSync = (DisplayTimingPtr->HSync << 4) | DTDPtr->HSyncWidth;
> +  DisplayTimingPtr->VSync = (DTDPtr->HVOffsetWidth & 0x03);
> +  DisplayTimingPtr->VSync = (DisplayTimingPtr->VSync << 4) |
> +                            (DTDPtr->VSyncOffsetWidth & 0x0F);
> +  DisplayTimingPtr->HImageSize = ((DTDPtr->HVImageSize & 0xF0) << 4) |
> +                                 DTDPtr->HImageSize;
> +  DisplayTimingPtr->VImageSize = ((DTDPtr->HVImageSize & 0x0F) << 8) |
> +                                 DTDPtr->VImageSize;

A lot of these above transforms are a fairly unreadable, but maybe
they need to be?

> +  DisplayTimingPtr->HBorder = DTDPtr->HBorder;
> +  DisplayTimingPtr->VBorder = DTDPtr->VBorder;
> +  DisplayTimingPtr->EdidFlags = DTDPtr->EdidFlags;
> +  DisplayTimingPtr->Flags = 0;

A #define for that 0?

> +
> +  DEBUG ((DEBUG_INFO, "--ConvertDTDToDisplayTiming()=ok\r\n"));

__FUNCTION__

> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Debug dump of Display Timing structure
> +
> +  @param[in]    DisplayTimingNamePtr  Name of display timing structure.
> +  @param[in]    DisplayTimingPtr      Pointer to display timing structure.
> +**/
> +VOID
> +PrintDisplayTiming (
> +  IN CHAR8            *DisplayTimingNamePtr,
> +  IN DISPLAY_TIMING   *DisplayTimingPtr
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "**********************\n"));
> +  DEBUG ((DEBUG_INFO, "%a\n", DisplayTimingNamePtr));
> +  DEBUG ((DEBUG_INFO, "**********************\n"));
> +  DEBUG ((DEBUG_INFO, "PixelClock %d\n", DisplayTimingPtr->PixelClock));
> +  DEBUG ((DEBUG_INFO, "HActive %d\n", DisplayTimingPtr->HActive));
> +  DEBUG ((DEBUG_INFO, "HBlank %d\n", DisplayTimingPtr->HBlank));
> +  DEBUG ((DEBUG_INFO, "VActive %d\n", DisplayTimingPtr->VActive));
> +  DEBUG ((DEBUG_INFO, "VBlank %d\n", DisplayTimingPtr->VBlank));
> +  DEBUG ((DEBUG_INFO, "HSync %d\n", DisplayTimingPtr->HSync));
> +  DEBUG ((DEBUG_INFO, "VSync %d\n", DisplayTimingPtr->VSync));
> +  DEBUG ((DEBUG_INFO, "HSyncOffset %d\n", DisplayTimingPtr->HSyncOffset));
> +  DEBUG ((DEBUG_INFO, "VSyncOffset %d\n", DisplayTimingPtr->VSyncOffset));
> +  DEBUG ((DEBUG_INFO, "HBorder %d\n", DisplayTimingPtr->HBorder));
> +  DEBUG ((DEBUG_INFO, "VBorder %d\n", DisplayTimingPtr->VBorder));
> +  DEBUG ((DEBUG_INFO, "EdidFlags %d\n", DisplayTimingPtr->EdidFlags));
> +  DEBUG ((DEBUG_INFO, "Flags %d\n", DisplayTimingPtr->Flags));
> +  DEBUG ((DEBUG_INFO, "PixelRepetition %d\n", DisplayTimingPtr->PixelRepetition));
> +  DEBUG ((DEBUG_INFO, "BPP %d\n", DisplayTimingPtr->Bpp));
> +  DEBUG ((DEBUG_INFO, "PixelFormat %d\n", DisplayTimingPtr->PixelFormat));
> +  DEBUG ((DEBUG_INFO, "**********************\n"));
> +}
> +
> +/**
> +  Check if EDID is valid
> +
> +  @param[in]    EdidDataPtr  Pointer to EDID data.
> +
> +  @retval   EFI_SUCCESS             EDID data is a valid EDID.
> +  @retval   EFI_INVALID_PARAMETER   EDID data is invalid.
> +
> +**/
> +EFI_STATUS
> +ValidateEdidData (
> +  IN UINT8 *EdidDataPtr
> +  )
> +{
> +  UINT8   Checksum;
> +  UINT8   Index;
> +
> +  DEBUG ((DEBUG_INFO, "++ValidateEdidData()\r\n"));

__FUNCTION__

> +
> +  if (EdidDataPtr[0] != 0x00 ||
> +      EdidDataPtr[1] != 0xFF ||
> +      EdidDataPtr[2] != 0xFF ||
> +      EdidDataPtr[3] != 0xFF ||
> +      EdidDataPtr[4] != 0xFF ||
> +      EdidDataPtr[5] != 0xFF ||
> +      EdidDataPtr[6] != 0xFF ||
> +      EdidDataPtr[7] != 0x00) {
> +    DEBUG ((DEBUG_ERROR, "Invalid EDID header\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Validate EDID checksum
> +  Checksum = 0;
> +  for (Index = 0; Index < EDID_MIN_SIZE; Index++) {
> +    Checksum += EdidDataPtr[Index];
> +  }
> +
> +  if (Checksum != 0) {
> +    DEBUG ((DEBUG_ERROR, "Invalid EDID checksum\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "--ValidateEdidData()=ok\r\n"));

__FUNCTION__

/
    Leif

> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
> new file mode 100644
> index 000000000000..bd77d4159639
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
> @@ -0,0 +1,31 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = iMXDisplayLib
> +  FILE_GUID                      = C0408490-F09B-4CFA-9A2F-5159F2705323
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = iMXDisplayLib
> +
> +[Packages]
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +
> +[Sources.common]
> +  iMXDisplayLib.c
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-09-21  8:26 ` [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use Chris Co
@ 2018-11-01 18:20   ` Leif Lindholm
  2018-12-01  0:22     ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-11-01 18:20 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:00AM +0000, Chris Co wrote:
> This adds common headers for other NXP i.MX SoC packages.
> More specifically, this adds i.MX-generic GPIO, IoMux, and
> Platform definitions.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMXPlatformPkg/Include/Platform.h | 67 ++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h  | 92 ++++++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h | 24 +++++
>  3 files changed, 183 insertions(+)
> 
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/Platform.h b/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
> new file mode 100644
> index 000000000000..8a1e828f68ea
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
> @@ -0,0 +1,67 @@
> +/** @file
> +*
> +*  i.MX Platform specific defines for constructing ACPI tables
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _PLATFORM_IMX_H_
> +#define _PLATFORM_IMX_H_
> +
> +#include <IndustryStandard/Acpi50.h>
> +
> +#define EFI_ACPI_OEM_ID               {'M','C','R','S','F','T'} // OEMID 6 bytes
> +#define EFI_ACPI_VENDOR_ID            SIGNATURE_32('N','X','P','I')
> +#define EFI_ACPI_CSRT_REVISION        0x00000005
> +#define EFI_ACPI_5_0_CSRT_REVISION    0x00000000
> +
> +// Resource Descriptor Types
> +#define EFI_ACPI_CSRT_RD_TYPE_INTERRUPT 1
> +#define EFI_ACPI_CSRT_RD_TYPE_TIMER 2
> +#define EFI_ACPI_CSRT_RD_TYPE_DMA 3
> +#define EFI_ACPI_CSRT_RD_TYPE_CACHE 4
> +
> +// Resource Descriptor Subtypes
> +#define EFI_ACPI_CSRT_RD_SUBTYPE_INTERRUPT_LINES 0
> +#define EFI_ACPI_CSRT_RD_SUBTYPE_INTERRUPT_CONTROLLER 1
> +#define EFI_ACPI_CSRT_RD_SUBTYPE_TIMER 0
> +#define EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CHANNEL 0
> +#define EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CONTROLLER 1
> +#define EFI_ACPI_CSRT_RD_SUBTYPE_CACHE 0

If using EFI_ACPI prefix, these #defines really should be in edk2
MdePkg. And CSRT itself is, so that might not be a bad idea.

> +
> +#pragma pack(push, 1)

I don't see this #pragma making any difference to the structs below,
can it be dropped?

> +//------------------------------------------------------------------------
> +// CSRT Resource Group header 24 bytes long
> +//------------------------------------------------------------------------
> +typedef struct {
> +  UINT32 Length;
> +  UINT32 VendorID;
> +  UINT32 SubVendorId;
> +  UINT16 DeviceId;
> +  UINT16 SubdeviceId;
> +  UINT16 Revision;
> +  UINT16 Reserved;
> +  UINT32 SharedInfoLength;
> +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER;
> +
> +//------------------------------------------------------------------------
> +// CSRT Resource Descriptor 12 bytes total
> +//------------------------------------------------------------------------
> +typedef struct {
> +  UINT32 Length;
> +  UINT16 ResourceType;
> +  UINT16 ResourceSubType;
> +  UINT32 UID;
> +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER;
> +#pragma pack (pop)
> +
> +#endif // !_PLATFORM_IMX_H_
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
> new file mode 100644
> index 000000000000..dce01f789058
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
> @@ -0,0 +1,92 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX_GPIO_H_
> +#define _IMX_GPIO_H_
> +
> +#include <Library/PcdLib.h>
> +
> +typedef enum {
> +  IMX_GPIO_LOW = 0,
> +  IMX_GPIO_HIGH = 1
> +} IMX_GPIO_VALUE;
> +
> +typedef enum {
> +  IMX_GPIO_DIR_INPUT,
> +  IMX_GPIO_DIR_OUTPUT
> +} IMX_GPIO_DIR;
> +
> +typedef enum {
> +  IMX_GPIO_BANK1 = 1,
> +  IMX_GPIO_BANK2,
> +  IMX_GPIO_BANK3,
> +  IMX_GPIO_BANK4,
> +  IMX_GPIO_BANK5,
> +  IMX_GPIO_BANK6,
> +  IMX_GPIO_BANK7,
> +} IMX_GPIO_BANK;
> +
> +#pragma pack(push, 1)

I don't see what effect this is supposed to have, can it be dropped?

> +
> +#define GPIO_RESERVED_SIZE \
> +    ((FixedPcdGet32(PcdGpioBankMemoryRange) / 4) - 8)
> +
> +typedef struct {
> +  UINT32 DR;                            // 0x00 GPIO data register (GPIO1_DR)
> +  UINT32 GDIR;                          // 0x04 GPIO direction register (GPIO1_GDIR)
> +  UINT32 PSR;                           // 0x08 GPIO pad status register (GPIO1_PSR)
> +  UINT32 ICR1;                          // 0x0C GPIO interrupt configuration register1 (GPIO1_ICR1)
> +  UINT32 ICR2;                          // 0x10 GPIO interrupt configuration register2 (GPIO1_ICR2)
> +  UINT32 IMR;                           // 0x14 GPIO interrupt mask register (GPIO1_IMR)
> +  UINT32 ISR;                           // 0x18 GPIO interrupt status register (GPIO1_ISR)
> +  UINT32 EDGE_SEL;                      // 0x1C GPIO edge select register (GPIO1_EDGE_SEL)
> +  UINT32 reserved[GPIO_RESERVED_SIZE];
> +} IMX_GPIO_BANK_REGISTERS;
> +
> +#pragma pack(pop)
> +
> +typedef struct {
> +  IMX_GPIO_BANK_REGISTERS Banks[7];
> +} IMX_GPIO_REGISTERS;
> +
> +/**
> +    Set the specified GPIO to the specified direction.
> +**/
> +VOID
> +ImxGpioDirection (
> +  IMX_GPIO_BANK Bank,
> +  UINT32 IoNumber,
> +  IMX_GPIO_DIR Direction
> +  );
> +
> +/**
> +    Write a value to a GPIO pin.
> +**/
> +VOID
> +ImxGpioWrite (
> +  IMX_GPIO_BANK Bank,
> +  UINT32 IoNumber,
> +  IMX_GPIO_VALUE Value
> +  );
> +
> +/**
> +    Read a GPIO pin input value.
> +**/
> +IMX_GPIO_VALUE
> +ImxGpioRead (
> +  IMX_GPIO_BANK Bank,
> +  UINT32 IoNumber
> +  );
> +
> +#endif
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
> new file mode 100644
> index 000000000000..7696af57d7ea
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
> @@ -0,0 +1,24 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX_IO_MUX_H_
> +#define _IMX_IO_MUX_H_
> +
> +#define _IMX_PAD(CtlRegOffset, MuxRegOffset) \

No _ for macros. Why does one pad an iMX? Can the name be more
descriptive? (applies to next few macros too).

/
    Leif

> +  ((((CtlRegOffset) & 0xffff) << 16) | ((MuxRegOffset) & 0xffff))
> +
> +#define _IMX_PAD_CTL_OFFSET(ImxPadVal) ((ImxPadVal) >> 16)
> +#define _IMX_PAD_MUX_OFFSET(ImxPadVal) ((ImxPadVal) & 0xffff)
> +
> +#endif // _IMX_IO_MUX_H_
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 10/27] Silicon/NXP: Add iMX6Pkg dec
  2018-09-21  8:26 ` [PATCH edk2-platforms 10/27] Silicon/NXP: Add iMX6Pkg dec Chris Co
@ 2018-11-01 18:25   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-11-01 18:25 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:00AM +0000, Chris Co wrote:
> This adds PCD declarations common across NXP i.MX6 SoCs
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec | 143 ++++++++++++++++++++
>  1 file changed, 143 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/iMX6Pkg.dec b/Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> new file mode 100644
> index 000000000000..99e1c7e6a4b8
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> @@ -0,0 +1,143 @@
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +
> +[Defines]
> +  DEC_SPECIFICATION              = 0x0001001A
> +  PACKAGE_NAME                   = iMX6Pkg
> +  PACKAGE_GUID                   = 6eba6648-d853-4eb3-9761-528b82d5ab04
> +  PACKAGE_VERSION                = 0.1
> +
> +################################################################################
> +#
> +# Include Section - list of Include Paths that are provided by this package.
> +#                   Comments are used for Keywords and Module Types.
> +#
> +# Supported Module Types:
> +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
> +#  DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
> +#
> +################################################################################
> +[Includes.common]
> +  Include                        # Root include for the package
> +  Silicon/NXP/iMXPlatformPkg/Include      # Root include for the iMXPlatform package
> +
> +[LibraryClasses]
> +  iMXIoMuxLib|Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
> +  iMX6ClkPwrLib|Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
> +  iMX6UsbPhyLib|Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
> +
> +[Protocols.common]
> +  gEfiSdhcProtocolGuid = { 0x46055b0f, 0x992a, 0x4ad7, { 0x8f, 0x81, 0x14, 0x81, 0x86, 0xff, 0xdf, 0x72 } }

This is too generic a name to belong to a protocol GUID defined in a
platform-specific package. (But the Sdhc implementation is a bit up in
the air, so...)

> +
> +[Guids.common]
> +  giMX6TokenSpaceGuid = { 0x24b09abe, 0x4e47, 0x481c, { 0xa9, 0xad, 0xce, 0xf1, 0x2c, 0x39, 0x23, 0x27} }
> +
> +[PcdsFixedAtBuild.common]
> +  #
> +  # Frame buffer is set to the first addressable memory on the i.MX6
> +  # Sabre board for convenience.
> +  # Keep in mind that this chunk of memory is the only one that remains fixed
> +  # through the various boot stages (primary boot->UEFI->Windows.
> +  #
> +  giMX6TokenSpaceGuid.PcdFrameBufferBase|0x10000000|UINT32|0x0000000A
> +  giMX6TokenSpaceGuid.PcdFrameBufferSize|0x00800000|UINT32|0x0000000B
> +
> +  #
> +  # Performance counter
> +  #
> +  gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterFrequencyInHz|1000000|UINT32 |0xC
> +  gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|1000|UINT32 |0xD

These would need to be defined in EmbeddedPkg.dec.
Can't hijack other packages' namespace.

/
    Leif

> +
> +  #
> +  # USB EHCI Controller
> +  #
> +  giMX6TokenSpaceGuid.PcdEHCIBase|0x02184000|UINT32|0xE
> +  giMX6TokenSpaceGuid.PcdEHCILength|0x4000|UINT32|0xF
> +  giMX6TokenSpaceGuid.PcdIsUsbPortOTG|TRUE|BOOLEAN|0x10
> +  giMX6TokenSpaceGuid.PcdUSBOTGBase|0x02184000|UINT32|0x11
> +
> +  #
> +  # ARM System Reset Controller (SRC)
> +  #
> +  giMX6TokenSpaceGuid.PcdSrcBase|0x020D8000|UINT32|0x2B
> +
> +  #
> +  # PCIE
> +  #
> +  # PCI Host config space is fixed at 0x01FFC000. The memory range from
> +  # 0x01000000 - 0x01FFBFFF is assigned for PCIe. The memory layout defined
> +  # by the boot loader is as below
> +  #
> +  # PCIe Device Config Space : 0x01F00000 - 0x01F80000
> +  # PCIe IO (unsupported) : 0x01100000 - 0x011FFFFF
> +  # PCIe Memory : 0x01200000 - 0x012FFFFF
> +  #
> +  giMX6TokenSpaceGuid.PcdPcieDeviceConfigBase|0x01F00000|UINT32|0x2C
> +  giMX6TokenSpaceGuid.PcdPcieDeviceConfigSize|0x00080000|UINT32|0x2D
> +  giMX6TokenSpaceGuid.PcdPcieHostConfigBase|0x01FFC000|UINT32|0x2E
> +  giMX6TokenSpaceGuid.PcdPcieIOBase|0x00000000|UINT32|0x2F
> +  giMX6TokenSpaceGuid.PcdPcieIOSize|0x00000000|UINT32|0x30
> +  giMX6TokenSpaceGuid.PcdPciMemoryBase|0x01100000|UINT32|0x31
> +  giMX6TokenSpaceGuid.PcdPciMemorySize|0x00D00000|UINT32|0x32
> +  giMX6TokenSpaceGuid.PcdPciPrefetchMemoryBase|0x00000000|UINT32|0x33
> +  giMX6TokenSpaceGuid.PcdPciPrefetchMemorySize|0x00000000|UINT32|0x34
> +  giMX6TokenSpaceGuid.PcdPcieResetGpio|FALSE|BOOLEAN|0x35
> +  giMX6TokenSpaceGuid.PcdPcieResetGpioBankNumber|0|UINT32|0x36
> +  giMX6TokenSpaceGuid.PcdPcieResetGpioIoNumber|0|UINT32|0x37
> +
> +  #
> +  # SMBIOS Type1
> +  #
> +  giMX6TokenSpaceGuid.PcdSystemFamily|L""|VOID*|0x38
> +  giMX6TokenSpaceGuid.PcdSystemManufacturer|L""|VOID*|0x39
> +  giMX6TokenSpaceGuid.PcdSystemProductName|L""|VOID*|0x3A
> +  giMX6TokenSpaceGuid.PcdSystemSkuNumber|L""|VOID*|0x3B
> +  giMX6TokenSpaceGuid.PcdSystemVersionNumber|L""|VOID*|0x3C
> +  giMX6TokenSpaceGuid.PcdSystemUuid|{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}|VOID*|0x3D
> +
> +  #
> +  # SMBIOS Type2
> +  #
> +  giMX6TokenSpaceGuid.PcdBoardAssetTag|L""|VOID*|0x3E
> +  giMX6TokenSpaceGuid.PcdBoardLocationInChassis|L""|VOID*|0x3F
> +  giMX6TokenSpaceGuid.PcdBoardManufacturer|L""|VOID*|0x40
> +  giMX6TokenSpaceGuid.PcdBoardProductName|L""|VOID*|0x41
> +  giMX6TokenSpaceGuid.PcdBoardVersionNumber|L""|VOID*|0x42
> +
> +  #
> +  # SMBIOS Type3
> +  #
> +  giMX6TokenSpaceGuid.PcdChassisAssetTag|L""|VOID*|0x43
> +  giMX6TokenSpaceGuid.PcdChassisManufacturer|L""|VOID*|0x44
> +  giMX6TokenSpaceGuid.PcdChassisVersionNumber|L""|VOID*|0x45
> +
> +  # SMBIOS Type4
> +  giMX6TokenSpaceGuid.PcdProcessorAssetTag|L""|VOID*|0x46
> +  giMX6TokenSpaceGuid.PcdProcessorManufacturer|L""|VOID*|0x47
> +  giMX6TokenSpaceGuid.PcdProcessorPartNumber|L""|VOID*|0x48
> +  giMX6TokenSpaceGuid.PcdProcessorSocketDesignation|L""|VOID*|0x49
> +  giMX6TokenSpaceGuid.PcdProcessorVersionNumber|L""|VOID*|0x4A
> +
> +  # SMBIOS Type16
> +  giMX6TokenSpaceGuid.PcdPhysicalMemoryMaximumCapacity|0x0|UINT32|0x4B
> +
> +  # SMBIOS Type17
> +  giMX6TokenSpaceGuid.PcdMemoryBankLocation|L""|VOID*|0x4C
> +  giMX6TokenSpaceGuid.PcdMemoryDeviceLocation|L""|VOID*|0x4D
> +
> +  # SMBIOS Type19
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x0|UINT32|0x4E
> +  giMX6TokenSpaceGuid.PcdMemoryStartAddress|0x0|UINT32|0x4F
> +
> +[PcdsFeatureFlag.common]
> +  giMX6TokenSpaceGuid.PcdGpuEnable|FALSE|BOOLEAN|0x00001000
> +  giMX6TokenSpaceGuid.PcdLvdsEnable|FALSE|BOOLEAN|0x00001001
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-11-01 10:55     ` Sumit Garg
@ 2018-11-02  0:41       ` Chris Co
  2018-11-02  5:24         ` Sumit Garg
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-11-02  0:41 UTC (permalink / raw)
  To: Sumit Garg, Leif Lindholm
  Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Sumit,

Our full OpteeClientPkg has:
- Our OpteeClientAPI implementation. I was monitoring the merge progress on OpteeLib and will look into moving over now that it is available.
- The fTPM and AuthVar TA binaries. In our current design, the TA binaries are loaded at runtime. We could host the binaries themselves elsewhere on the filesystem, but we do not want these binaries as early/pseudo TAs. Is there a plan for OpteeLib to support loading full TAs?
- We have two client drivers: a firmware TPM TA driver and an authenticated variable TA driver. These talk through the tee-supplicant to their respective TAs.

Chris

> -----Original Message-----
> From: Sumit Garg <sumit.garg@linaro.org>
> Sent: Thursday, November 1, 2018 3:55 AM
> To: Chris Co <Christopher.Co@microsoft.com>; Leif Lindholm
> <leif.lindholm@linaro.org>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add
> OpteeClientPkg dec
> 
> Hi Christopher,
> 
> Optee Client library has recently been merged to edk2 source code. It tries to
> provide a generic interface [1] to OP-TEE based trusted applications
> (pseudo/early).
> 
> AFAIK, you don't need any platform specific hook in client interface to work
> with upstream OP-TEE. So instead you should use Optee library.
> 
> [1]
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.c
> om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FInclude%2FLibrary
> %2FOpteeLib.h&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C
> c19b84ef7f8f4213424108d63fe88f66%7C72f988bf86f141af91ab2d7cd011db47
> %7C1%7C0%7C636766665404786500&amp;sdata=m24akbKtoyCERVN77meoSU
> H6E%2Bpf8W2P5MF7nvU5y7I%3D&amp;reserved=0
> 
> Regards,
> Sumit
> 
> On Thu, 1 Nov 2018 at 02:13, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> >
> > +Sumit (just to loop you two together). Is there anything Microsoft
> > platform specific about what will go in here?
> >
> > /
> >     Leif
> >
> > On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > > On Windows IoT Core devices with ARM TrustZone capabilities,
> > > EDK2 runs in normal world and we use OP-TEE to execute secure world
> > > operations. The overall package will contain client-side support to
> > > invoke EDK2 services implemented as OP-TEE trusted applications that
> > > run in secure world.
> > >
> > > This commit adds the initial dec file to add some PCD settings
> > > needed by other packages.
> > >
> > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > ---
> > >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49
> > > ++++++++++++++++++++
> > >  1 file changed, 49 insertions(+)
> > >
> > > diff --git a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > new file mode 100644
> > > index 000000000000..4752eab39ce3
> > > --- /dev/null
> > > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > @@ -0,0 +1,49 @@
> > > +## @file
> > > +#
> > > +#  OP-TEE client package
> > > +#
> > > +#  OP-TEE client package contains the client-side interface to invoke OP-
> TEE TAs.
> > > +#  Certain EDKII services are implemented in Trusted Applications
> > > +running in #  the secure world OP-TEE OS.
> > > +#
> > > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +#
> > > +#  This program and the accompanying materials #  are licensed and
> > > +made available under the terms and conditions of the BSD License #
> > > +which accompanies this distribution.  The full text of the license
> > > +may be found at #
> > > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> > > +nsource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristo
> > >
> +pher.Co%40microsoft.com%7Cc19b84ef7f8f4213424108d63fe88f66%7C72f988
> > >
> +bf86f141af91ab2d7cd011db47%7C1%7C0%7C636766665404786500&amp;sda
> ta=1
> > > +MxFvlsMPhk19grEexBXo5VqRd0jZaCSRjxZCi87A2w%3D&amp;reserved=0
> > > +#
> > > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> EITHER EXPRESS OR IMPLIED.
> > > +#
> > > +##
> > > +
> > > +[Defines]
> > > +  DEC_SPECIFICATION              = 0x0001001A
> > > +  PACKAGE_NAME                   = OpteeClientPkg
> > > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-1bdd74ec9595
> > > +  PACKAGE_VERSION                = 0.01
> > > +
> > > +[Includes]
> > > +
> > > +[LibraryClasses]
> > > +
> > > +[Guids]
> > > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, {
> 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > > +
> > > +[PcdsFixedAtBuild]
> > > +
> > >
> +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x0000
> > > +0005
> > > +
> > >
> +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x0000
> > > +0006
> > > +
> > > +  ## The base address of the Trust Zone OpTEE OS private memory
> > > + region  # This memory is manager privately by the OpTEE OS.
> > > +
> > > +
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD
> > > + 1|UINT64|0x00000001
> > > +
> > > +  ## The size of the Trust Zone OpTEE OS private memory region
> > > +
> > > +
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UIN
> > > + T64|0x00000002
> > > +
> > > +  ## The base address of the Trust Zone OpTEE OS shared memory
> > > + region
> > > +
> > > +
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2
> > > + |UINT64|0x00000003
> > > +
> > > +  ## The size of the Trust Zone OpTEE OS shared memory region
> > > +
> > > +
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UI
> > > + NT64|0x00000004
> > > --
> > > 2.16.2.gvfs.1.33.gf5370f1
> > >

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms
  2018-11-01  8:59   ` Leif Lindholm
@ 2018-11-02  1:46     ` Chris Co
  0 siblings, 0 replies; 75+ messages in thread
From: Chris Co @ 2018-11-02  1:46 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Leif,

> -----Original Message-----
> From: Leif Lindholm <leif.lindholm@linaro.org>
> Sent: Thursday, November 1, 2018 2:00 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library
> support for i.MX platforms
> 
> On Fri, Sep 21, 2018 at 08:25:56AM +0000, Chris Co wrote:
> > This adds support for interact with the UART controller on NXP i.MX
> > platforms.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > ---
> > +
> > +**/
> > +RETURN_STATUS
> > +EFIAPI
> > +SerialPortInitialize (
> > +  VOID
> > +  )
> > +{
> > +  MX6UART_REGISTERS   *UartBase;
> > +  UINT32              Ucr1;
> 
> ... once we create variables to hold data from those registers, those variables
> should really be FullyCompliantCamelCase.
> But really, something like this could just be "Data" or "Value" or something
> like that. Or if you want a bit more, "ControlRegister".
> 
> Not going to comment on each function, but the pattern repeats throughout
> the file.
> 
Noted. I'll change variable names throughout all of the files.

Chris


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-11-02  0:41       ` Chris Co
@ 2018-11-02  5:24         ` Sumit Garg
  2018-11-02 23:55           ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Sumit Garg @ 2018-11-02  5:24 UTC (permalink / raw)
  To: Christopher.Co
  Cc: Leif Lindholm, edk2-devel, Ard Biesheuvel, Michael D Kinney,
	tee-dev

+ OP-TEE ML.

On Fri, 2 Nov 2018 at 06:11, Chris Co <Christopher.Co@microsoft.com> wrote:
>
> Hi Sumit,
>
> Our full OpteeClientPkg has:
> - Our OpteeClientAPI implementation. I was monitoring the merge progress on OpteeLib and will look into moving over now that it is available.
> - The fTPM and AuthVar TA binaries. In our current design, the TA binaries are loaded at runtime. We could host the binaries themselves elsewhere on the filesystem, but we do not want these binaries as early/pseudo TAs. Is there a plan for OpteeLib to support loading full TAs?

Early TAs [1] are basically full TAs only, running in Secure EL0 mode.
So instead of loading TA from normal world file-system, they are
linked into a special data section in the OP-TEE core blob.

Also I don't think loading TAs dynamically especially during boot
makes much sense due to following reasons:
1. Increased boot time.
2. Fixed TAs like in your case which could be linked as early TAs as well.

And you mentioned filesystem, are you referring to root filesystem?

> - We have two client drivers: a firmware TPM TA driver and an authenticated variable TA driver. These talk through the tee-supplicant to their respective TAs.
>

Here from tee-supplicant apart from loading TAs, what other services
are you expecting? If you are looking for secure storage via RPMB,
that could be an enhancement to OpteeLib adding corresponding RPC
handling here [2].

[1] https://github.com/OP-TEE/optee_os/blob/master/documentation/optee_design.md#early-trusted-applications
[2] https://github.com/tianocore/edk2/blob/master/ArmPkg/Library/OpteeLib/Optee.c#L147

Regards,
Sumit

> Chris
>
> > -----Original Message-----
> > From: Sumit Garg <sumit.garg@linaro.org>
> > Sent: Thursday, November 1, 2018 3:55 AM
> > To: Chris Co <Christopher.Co@microsoft.com>; Leif Lindholm
> > <leif.lindholm@linaro.org>
> > Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> > Michael D Kinney <michael.d.kinney@intel.com>
> > Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add
> > OpteeClientPkg dec
> >
> > Hi Christopher,
> >
> > Optee Client library has recently been merged to edk2 source code. It tries to
> > provide a generic interface [1] to OP-TEE based trusted applications
> > (pseudo/early).
> >
> > AFAIK, you don't need any platform specific hook in client interface to work
> > with upstream OP-TEE. So instead you should use Optee library.
> >
> > [1]
> > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.c
> > om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FInclude%2FLibrary
> > %2FOpteeLib.h&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C
> > c19b84ef7f8f4213424108d63fe88f66%7C72f988bf86f141af91ab2d7cd011db47
> > %7C1%7C0%7C636766665404786500&amp;sdata=m24akbKtoyCERVN77meoSU
> > H6E%2Bpf8W2P5MF7nvU5y7I%3D&amp;reserved=0
> >
> > Regards,
> > Sumit
> >
> > On Thu, 1 Nov 2018 at 02:13, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> > >
> > > +Sumit (just to loop you two together). Is there anything Microsoft
> > > platform specific about what will go in here?
> > >
> > > /
> > >     Leif
> > >
> > > On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > > > On Windows IoT Core devices with ARM TrustZone capabilities,
> > > > EDK2 runs in normal world and we use OP-TEE to execute secure world
> > > > operations. The overall package will contain client-side support to
> > > > invoke EDK2 services implemented as OP-TEE trusted applications that
> > > > run in secure world.
> > > >
> > > > This commit adds the initial dec file to add some PCD settings
> > > > needed by other packages.
> > > >
> > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > > ---
> > > >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49
> > > > ++++++++++++++++++++
> > > >  1 file changed, 49 insertions(+)
> > > >
> > > > diff --git a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > new file mode 100644
> > > > index 000000000000..4752eab39ce3
> > > > --- /dev/null
> > > > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > @@ -0,0 +1,49 @@
> > > > +## @file
> > > > +#
> > > > +#  OP-TEE client package
> > > > +#
> > > > +#  OP-TEE client package contains the client-side interface to invoke OP-
> > TEE TAs.
> > > > +#  Certain EDKII services are implemented in Trusted Applications
> > > > +running in #  the secure world OP-TEE OS.
> > > > +#
> > > > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > > +#
> > > > +#  This program and the accompanying materials #  are licensed and
> > > > +made available under the terms and conditions of the BSD License #
> > > > +which accompanies this distribution.  The full text of the license
> > > > +may be found at #
> > > > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> > > > +nsource.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristo
> > > >
> > +pher.Co%40microsoft.com%7Cc19b84ef7f8f4213424108d63fe88f66%7C72f988
> > > >
> > +bf86f141af91ab2d7cd011db47%7C1%7C0%7C636766665404786500&amp;sda
> > ta=1
> > > > +MxFvlsMPhk19grEexBXo5VqRd0jZaCSRjxZCi87A2w%3D&amp;reserved=0
> > > > +#
> > > > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > > > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> > EITHER EXPRESS OR IMPLIED.
> > > > +#
> > > > +##
> > > > +
> > > > +[Defines]
> > > > +  DEC_SPECIFICATION              = 0x0001001A
> > > > +  PACKAGE_NAME                   = OpteeClientPkg
> > > > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-1bdd74ec9595
> > > > +  PACKAGE_VERSION                = 0.01
> > > > +
> > > > +[Includes]
> > > > +
> > > > +[LibraryClasses]
> > > > +
> > > > +[Guids]
> > > > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, {
> > 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > > > +
> > > > +[PcdsFixedAtBuild]
> > > > +
> > > >
> > +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x0000
> > > > +0005
> > > > +
> > > >
> > +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x0000
> > > > +0006
> > > > +
> > > > +  ## The base address of the Trust Zone OpTEE OS private memory
> > > > + region  # This memory is manager privately by the OpTEE OS.
> > > > +
> > > > +
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD
> > > > + 1|UINT64|0x00000001
> > > > +
> > > > +  ## The size of the Trust Zone OpTEE OS private memory region
> > > > +
> > > > +
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UIN
> > > > + T64|0x00000002
> > > > +
> > > > +  ## The base address of the Trust Zone OpTEE OS shared memory
> > > > + region
> > > > +
> > > > +
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2
> > > > + |UINT64|0x00000003
> > > > +
> > > > +  ## The size of the Trust Zone OpTEE OS shared memory region
> > > > +
> > > > +
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UI
> > > > + NT64|0x00000004
> > > > --
> > > > 2.16.2.gvfs.1.33.gf5370f1
> > > >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-11-02  5:24         ` Sumit Garg
@ 2018-11-02 23:55           ` Chris Co
  2018-11-05 10:07             ` Sumit Garg
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-11-02 23:55 UTC (permalink / raw)
  To: Sumit Garg
  Cc: Leif Lindholm, edk2-devel@lists.01.org, Ard Biesheuvel,
	Michael D Kinney, tee-dev@lists.linaro.org

Hi Sumit,

> -----Original Message-----
> From: Sumit Garg <sumit.garg@linaro.org>
> Sent: Thursday, November 1, 2018 10:24 PM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>; edk2-devel@lists.01.org; Ard
> Biesheuvel <ard.biesheuvel@linaro.org>; Michael D Kinney
> <michael.d.kinney@intel.com>; tee-dev@lists.linaro.org
> Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add
> OpteeClientPkg dec
> 
> + OP-TEE ML.
> 
> On Fri, 2 Nov 2018 at 06:11, Chris Co <Christopher.Co@microsoft.com> wrote:
> >
> > Hi Sumit,
> >
> > Our full OpteeClientPkg has:
> > - Our OpteeClientAPI implementation. I was monitoring the merge progress
> on OpteeLib and will look into moving over now that it is available.
> > - The fTPM and AuthVar TA binaries. In our current design, the TA binaries
> are loaded at runtime. We could host the binaries themselves elsewhere on
> the filesystem, but we do not want these binaries as early/pseudo TAs. Is
> there a plan for OpteeLib to support loading full TAs?
> 
> Early TAs [1] are basically full TAs only, running in Secure EL0 mode.
> So instead of loading TA from normal world file-system, they are linked into a
> special data section in the OP-TEE core blob.
> 
> Also I don't think loading TAs dynamically especially during boot makes much
> sense due to following reasons:
> 1. Increased boot time.
> 2. Fixed TAs like in your case which could be linked as early TAs as well.
> 

We prefer to load TAs dynamically for a more flexible servicing story. My understanding is that Early TAs are coupled with the OP-TEE binary itself, so to update an Early TA, a new OP-TEE binary would need to be created and pushed. We want to avoid rolling a new OP-TEE and only update the TA binary in this scenario.

> And you mentioned filesystem, are you referring to root filesystem?
> 

We have not implemented this yet, but we were thinking to have the TA binaries present in the EFI partition.

> > - We have two client drivers: a firmware TPM TA driver and an
> authenticated variable TA driver. These talk through the tee-supplicant to
> their respective TAs.
> >
> 
> Here from tee-supplicant apart from loading TAs, what other services are you
> expecting? If you are looking for secure storage via RPMB, that could be an
> enhancement to OpteeLib adding corresponding RPC handling here [2].
> 

For RPC handling, we are looking for the following callback support:
- OPTEE_SMC_RPC_FUNC_ALLOC
- OPTEE_SMC_RPC_FUNC_FREE
- OPTEE_SMC_RPC_FUNC_CMD
	- OPTEE_MSG_RPC_CMD_LOAD_TA
	- OPTEE_MSG_RPC_CMD_RPMB
	- OPTEE_MSG_RPC_CMD_GET_TIME
	- OPTEE_MSG_RPC_CMD_SHM_ALLOC
	- OPTEE_MSG_RPC_CMD_SHM_FREE
	- OPTEE_MSG_RPC_CMD_WAIT_QUEUE

Thanks,
Chris

> [1]
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.c
> om%2FOP-
> TEE%2Foptee_os%2Fblob%2Fmaster%2Fdocumentation%2Foptee_design.md
> %23early-trusted-
> applications&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C4a
> 7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd011db47%
> 7C1%7C0%7C636767330779998429&amp;sdata=yaDWw5Z6yuux1o89kxzbknVp
> b%2B1OHUagbB%2FOGS4dAcU%3D&amp;reserved=0
> [2]
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.c
> om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FLibrary%2FOpteeL
> ib%2FOptee.c%23L147&amp;data=02%7C01%7CChristopher.Co%40microsoft.c
> om%7C4a7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd
> 011db47%7C1%7C0%7C636767330779998429&amp;sdata=Lsplb1L7Ugd2C6cXG
> 8gBo40Ei8UQPtIA7fNEDL1t%2Fbg%3D&amp;reserved=0
> 
> Regards,
> Sumit
> 
> > Chris
> >
> > > -----Original Message-----
> > > From: Sumit Garg <sumit.garg@linaro.org>
> > > Sent: Thursday, November 1, 2018 3:55 AM
> > > To: Chris Co <Christopher.Co@microsoft.com>; Leif Lindholm
> > > <leif.lindholm@linaro.org>
> > > Cc: edk2-devel@lists.01.org; Ard Biesheuvel
> > > <ard.biesheuvel@linaro.org>; Michael D Kinney
> > > <michael.d.kinney@intel.com>
> > > Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add
> > > OpteeClientPkg dec
> > >
> > > Hi Christopher,
> > >
> > > Optee Client library has recently been merged to edk2 source code.
> > > It tries to provide a generic interface [1] to OP-TEE based trusted
> > > applications (pseudo/early).
> > >
> > > AFAIK, you don't need any platform specific hook in client interface
> > > to work with upstream OP-TEE. So instead you should use Optee library.
> > >
> > > [1]
> > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> > > hub.c
> > >
> om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FInclude%2FLibrary
> > >
> %2FOpteeLib.h&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C
> > >
> c19b84ef7f8f4213424108d63fe88f66%7C72f988bf86f141af91ab2d7cd011db47
> > >
> %7C1%7C0%7C636766665404786500&amp;sdata=m24akbKtoyCERVN77meoSU
> > > H6E%2Bpf8W2P5MF7nvU5y7I%3D&amp;reserved=0
> > >
> > > Regards,
> > > Sumit
> > >
> > > On Thu, 1 Nov 2018 at 02:13, Leif Lindholm <leif.lindholm@linaro.org>
> wrote:
> > > >
> > > > +Sumit (just to loop you two together). Is there anything
> > > > +Microsoft
> > > > platform specific about what will go in here?
> > > >
> > > > /
> > > >     Leif
> > > >
> > > > On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > > > > On Windows IoT Core devices with ARM TrustZone capabilities,
> > > > > EDK2 runs in normal world and we use OP-TEE to execute secure
> > > > > world operations. The overall package will contain client-side
> > > > > support to invoke EDK2 services implemented as OP-TEE trusted
> > > > > applications that run in secure world.
> > > > >
> > > > > This commit adds the initial dec file to add some PCD settings
> > > > > needed by other packages.
> > > > >
> > > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > > > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > > > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > > > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > > > ---
> > > > >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49
> > > > > ++++++++++++++++++++
> > > > >  1 file changed, 49 insertions(+)
> > > > >
> > > > > diff --git
> > > > > a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > new file mode 100644
> > > > > index 000000000000..4752eab39ce3
> > > > > --- /dev/null
> > > > > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > @@ -0,0 +1,49 @@
> > > > > +## @file
> > > > > +#
> > > > > +#  OP-TEE client package
> > > > > +#
> > > > > +#  OP-TEE client package contains the client-side interface to
> > > > > +invoke OP-
> > > TEE TAs.
> > > > > +#  Certain EDKII services are implemented in Trusted
> > > > > +Applications running in #  the secure world OP-TEE OS.
> > > > > +#
> > > > > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > > > +#
> > > > > +#  This program and the accompanying materials #  are licensed
> > > > > +and made available under the terms and conditions of the BSD
> > > > > +License # which accompanies this distribution.  The full text
> > > > > +of the license may be found at #
> > > > > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2
> > > > > +Fope
> > > > > +nsource.org%2Flicenses%2Fbsd-
> > > license.php&amp;data=02%7C01%7CChristo
> > > > >
> > >
> +pher.Co%40microsoft.com%7Cc19b84ef7f8f4213424108d63fe88f66%7C72f988
> > > > >
> > >
> +bf86f141af91ab2d7cd011db47%7C1%7C0%7C636766665404786500&amp;sda
> > > ta=1
> > > > >
> +MxFvlsMPhk19grEexBXo5VqRd0jZaCSRjxZCi87A2w%3D&amp;reserved=0
> > > > > +#
> > > > > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS
> IS"
> > > > > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> > > EITHER EXPRESS OR IMPLIED.
> > > > > +#
> > > > > +##
> > > > > +
> > > > > +[Defines]
> > > > > +  DEC_SPECIFICATION              = 0x0001001A
> > > > > +  PACKAGE_NAME                   = OpteeClientPkg
> > > > > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-
> 1bdd74ec9595
> > > > > +  PACKAGE_VERSION                = 0.01
> > > > > +
> > > > > +[Includes]
> > > > > +
> > > > > +[LibraryClasses]
> > > > > +
> > > > > +[Guids]
> > > > > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, {
> > > 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > > > > +
> > > > > +[PcdsFixedAtBuild]
> > > > > +
> > > > >
> > >
> +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x0000
> > > > > +0005
> > > > > +
> > > > >
> > >
> +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x0000
> > > > > +0006
> > > > > +
> > > > > +  ## The base address of the Trust Zone OpTEE OS private memory
> > > > > + region  # This memory is manager privately by the OpTEE OS.
> > > > > +
> > > > > +
> > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD
> > > > > + 1|UINT64|0x00000001
> > > > > +
> > > > > +  ## The size of the Trust Zone OpTEE OS private memory region
> > > > > +
> > > > > +
> > > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UIN
> > > > > + T64|0x00000002
> > > > > +
> > > > > +  ## The base address of the Trust Zone OpTEE OS shared memory
> > > > > + region
> > > > > +
> > > > > +
> > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2
> > > > > + |UINT64|0x00000003
> > > > > +
> > > > > +  ## The size of the Trust Zone OpTEE OS shared memory region
> > > > > +
> > > > > +
> > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UI
> > > > > + NT64|0x00000004
> > > > > --
> > > > > 2.16.2.gvfs.1.33.gf5370f1
> > > > >

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-11-02 23:55           ` Chris Co
@ 2018-11-05 10:07             ` Sumit Garg
  2018-11-06  1:53               ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Sumit Garg @ 2018-11-05 10:07 UTC (permalink / raw)
  To: Christopher.Co
  Cc: Leif Lindholm, edk2-devel, Ard Biesheuvel, Michael D Kinney,
	tee-dev

Hi Chris,

On Sat, 3 Nov 2018 at 05:25, Chris Co <Christopher.Co@microsoft.com> wrote:
>
> Hi Sumit,
>
> > -----Original Message-----
> > From: Sumit Garg <sumit.garg@linaro.org>
> > Sent: Thursday, November 1, 2018 10:24 PM
> > To: Chris Co <Christopher.Co@microsoft.com>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>; edk2-devel@lists.01.org; Ard
> > Biesheuvel <ard.biesheuvel@linaro.org>; Michael D Kinney
> > <michael.d.kinney@intel.com>; tee-dev@lists.linaro.org
> > Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add
> > OpteeClientPkg dec
> >
> > + OP-TEE ML.
> >
> > On Fri, 2 Nov 2018 at 06:11, Chris Co <Christopher.Co@microsoft.com> wrote:
> > >
> > > Hi Sumit,
> > >
> > > Our full OpteeClientPkg has:
> > > - Our OpteeClientAPI implementation. I was monitoring the merge progress
> > on OpteeLib and will look into moving over now that it is available.
> > > - The fTPM and AuthVar TA binaries. In our current design, the TA binaries
> > are loaded at runtime. We could host the binaries themselves elsewhere on
> > the filesystem, but we do not want these binaries as early/pseudo TAs. Is
> > there a plan for OpteeLib to support loading full TAs?
> >
> > Early TAs [1] are basically full TAs only, running in Secure EL0 mode.
> > So instead of loading TA from normal world file-system, they are linked into a
> > special data section in the OP-TEE core blob.
> >
> > Also I don't think loading TAs dynamically especially during boot makes much
> > sense due to following reasons:
> > 1. Increased boot time.
> > 2. Fixed TAs like in your case which could be linked as early TAs as well.
> >
>
> We prefer to load TAs dynamically for a more flexible servicing story. My understanding is that Early TAs are coupled with the OP-TEE binary itself, so to update an Early TA, a new OP-TEE binary would need to be created and pushed. We want to avoid rolling a new OP-TEE and only update the TA binary in this scenario.
>

Are you referring to run-time updates on the device in the field? If
this is the case then how do you think to update TAs, is it via some
custom capsule update method?

I do consider these TAs used during boot as essential secure services
provided by the secure firmware (OP-TEE in this case). So these TAs
should be part of firmware itself and updates for them should come
through firmware capsule updates only.

> > And you mentioned filesystem, are you referring to root filesystem?
> >
>
> We have not implemented this yet, but we were thinking to have the TA binaries present in the EFI partition.
>

AFAIK, EFI partition is shared among Linux and UEFI. This provides
Linux access to secure firmware TAs that could be a security concern
(denial of service could be one of them).

> > > - We have two client drivers: a firmware TPM TA driver and an
> > authenticated variable TA driver. These talk through the tee-supplicant to
> > their respective TAs.
> > >
> >
> > Here from tee-supplicant apart from loading TAs, what other services are you
> > expecting? If you are looking for secure storage via RPMB, that could be an
> > enhancement to OpteeLib adding corresponding RPC handling here [2].
> >
>
> For RPC handling, we are looking for the following callback support:
> - OPTEE_SMC_RPC_FUNC_ALLOC
> - OPTEE_SMC_RPC_FUNC_FREE
> - OPTEE_SMC_RPC_FUNC_CMD
>         - OPTEE_MSG_RPC_CMD_LOAD_TA

Please see above comments for this.

>         - OPTEE_MSG_RPC_CMD_RPMB
>         - OPTEE_MSG_RPC_CMD_GET_TIME

Can you share the usage of OPTEE_MSG_RPC_CMD_GET_TIME? AFAIK, this is
used to get REE time from OP-TEE.

>         - OPTEE_MSG_RPC_CMD_SHM_ALLOC
>         - OPTEE_MSG_RPC_CMD_SHM_FREE
>         - OPTEE_MSG_RPC_CMD_WAIT_QUEUE

I don't think we need OPTEE_MSG_RPC_CMD_WAIT_QUEUE implementation in
UEFI as its a single threaded execution flow on boot core.

BTW, I am not sure if I could get time to work on RPC handling anytime
soon. So patches are welcome and I am happy to review them.

Regards,
Sumit

>
> Thanks,
> Chris
>
> > [1]
> > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.c
> > om%2FOP-
> > TEE%2Foptee_os%2Fblob%2Fmaster%2Fdocumentation%2Foptee_design.md
> > %23early-trusted-
> > applications&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C4a
> > 7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd011db47%
> > 7C1%7C0%7C636767330779998429&amp;sdata=yaDWw5Z6yuux1o89kxzbknVp
> > b%2B1OHUagbB%2FOGS4dAcU%3D&amp;reserved=0
> > [2]
> > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.c
> > om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FLibrary%2FOpteeL
> > ib%2FOptee.c%23L147&amp;data=02%7C01%7CChristopher.Co%40microsoft.c
> > om%7C4a7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd
> > 011db47%7C1%7C0%7C636767330779998429&amp;sdata=Lsplb1L7Ugd2C6cXG
> > 8gBo40Ei8UQPtIA7fNEDL1t%2Fbg%3D&amp;reserved=0
> >
> > Regards,
> > Sumit
> >
> > > Chris
> > >
> > > > -----Original Message-----
> > > > From: Sumit Garg <sumit.garg@linaro.org>
> > > > Sent: Thursday, November 1, 2018 3:55 AM
> > > > To: Chris Co <Christopher.Co@microsoft.com>; Leif Lindholm
> > > > <leif.lindholm@linaro.org>
> > > > Cc: edk2-devel@lists.01.org; Ard Biesheuvel
> > > > <ard.biesheuvel@linaro.org>; Michael D Kinney
> > > > <michael.d.kinney@intel.com>
> > > > Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add
> > > > OpteeClientPkg dec
> > > >
> > > > Hi Christopher,
> > > >
> > > > Optee Client library has recently been merged to edk2 source code.
> > > > It tries to provide a generic interface [1] to OP-TEE based trusted
> > > > applications (pseudo/early).
> > > >
> > > > AFAIK, you don't need any platform specific hook in client interface
> > > > to work with upstream OP-TEE. So instead you should use Optee library.
> > > >
> > > > [1]
> > > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> > > > hub.c
> > > >
> > om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FInclude%2FLibrary
> > > >
> > %2FOpteeLib.h&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C
> > > >
> > c19b84ef7f8f4213424108d63fe88f66%7C72f988bf86f141af91ab2d7cd011db47
> > > >
> > %7C1%7C0%7C636766665404786500&amp;sdata=m24akbKtoyCERVN77meoSU
> > > > H6E%2Bpf8W2P5MF7nvU5y7I%3D&amp;reserved=0
> > > >
> > > > Regards,
> > > > Sumit
> > > >
> > > > On Thu, 1 Nov 2018 at 02:13, Leif Lindholm <leif.lindholm@linaro.org>
> > wrote:
> > > > >
> > > > > +Sumit (just to loop you two together). Is there anything
> > > > > +Microsoft
> > > > > platform specific about what will go in here?
> > > > >
> > > > > /
> > > > >     Leif
> > > > >
> > > > > On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > > > > > On Windows IoT Core devices with ARM TrustZone capabilities,
> > > > > > EDK2 runs in normal world and we use OP-TEE to execute secure
> > > > > > world operations. The overall package will contain client-side
> > > > > > support to invoke EDK2 services implemented as OP-TEE trusted
> > > > > > applications that run in secure world.
> > > > > >
> > > > > > This commit adds the initial dec file to add some PCD settings
> > > > > > needed by other packages.
> > > > > >
> > > > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > > > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > > > > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > > > > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > > > > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > > > > ---
> > > > > >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49
> > > > > > ++++++++++++++++++++
> > > > > >  1 file changed, 49 insertions(+)
> > > > > >
> > > > > > diff --git
> > > > > > a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > new file mode 100644
> > > > > > index 000000000000..4752eab39ce3
> > > > > > --- /dev/null
> > > > > > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > @@ -0,0 +1,49 @@
> > > > > > +## @file
> > > > > > +#
> > > > > > +#  OP-TEE client package
> > > > > > +#
> > > > > > +#  OP-TEE client package contains the client-side interface to
> > > > > > +invoke OP-
> > > > TEE TAs.
> > > > > > +#  Certain EDKII services are implemented in Trusted
> > > > > > +Applications running in #  the secure world OP-TEE OS.
> > > > > > +#
> > > > > > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > > > > +#
> > > > > > +#  This program and the accompanying materials #  are licensed
> > > > > > +and made available under the terms and conditions of the BSD
> > > > > > +License # which accompanies this distribution.  The full text
> > > > > > +of the license may be found at #
> > > > > > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2
> > > > > > +Fope
> > > > > > +nsource.org%2Flicenses%2Fbsd-
> > > > license.php&amp;data=02%7C01%7CChristo
> > > > > >
> > > >
> > +pher.Co%40microsoft.com%7Cc19b84ef7f8f4213424108d63fe88f66%7C72f988
> > > > > >
> > > >
> > +bf86f141af91ab2d7cd011db47%7C1%7C0%7C636766665404786500&amp;sda
> > > > ta=1
> > > > > >
> > +MxFvlsMPhk19grEexBXo5VqRd0jZaCSRjxZCi87A2w%3D&amp;reserved=0
> > > > > > +#
> > > > > > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS
> > IS"
> > > > > > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> > > > EITHER EXPRESS OR IMPLIED.
> > > > > > +#
> > > > > > +##
> > > > > > +
> > > > > > +[Defines]
> > > > > > +  DEC_SPECIFICATION              = 0x0001001A
> > > > > > +  PACKAGE_NAME                   = OpteeClientPkg
> > > > > > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-
> > 1bdd74ec9595
> > > > > > +  PACKAGE_VERSION                = 0.01
> > > > > > +
> > > > > > +[Includes]
> > > > > > +
> > > > > > +[LibraryClasses]
> > > > > > +
> > > > > > +[Guids]
> > > > > > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25, 0x4156, {
> > > > 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > > > > > +
> > > > > > +[PcdsFixedAtBuild]
> > > > > > +
> > > > > >
> > > >
> > +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x0000
> > > > > > +0005
> > > > > > +
> > > > > >
> > > >
> > +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x0000
> > > > > > +0006
> > > > > > +
> > > > > > +  ## The base address of the Trust Zone OpTEE OS private memory
> > > > > > + region  # This memory is manager privately by the OpTEE OS.
> > > > > > +
> > > > > > +
> > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD
> > > > > > + 1|UINT64|0x00000001
> > > > > > +
> > > > > > +  ## The size of the Trust Zone OpTEE OS private memory region
> > > > > > +
> > > > > > +
> > > > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|UIN
> > > > > > + T64|0x00000002
> > > > > > +
> > > > > > +  ## The base address of the Trust Zone OpTEE OS shared memory
> > > > > > + region
> > > > > > +
> > > > > > +
> > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2
> > > > > > + |UINT64|0x00000003
> > > > > > +
> > > > > > +  ## The size of the Trust Zone OpTEE OS shared memory region
> > > > > > +
> > > > > > +
> > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UI
> > > > > > + NT64|0x00000004
> > > > > > --
> > > > > > 2.16.2.gvfs.1.33.gf5370f1
> > > > > >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-11-05 10:07             ` Sumit Garg
@ 2018-11-06  1:53               ` Chris Co
  2018-11-06 11:09                 ` Sumit Garg
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-11-06  1:53 UTC (permalink / raw)
  To: Sumit Garg
  Cc: Leif Lindholm, edk2-devel@lists.01.org, Ard Biesheuvel,
	Michael D Kinney, tee-dev@lists.linaro.org

Hi Sumit,

> -----Original Message-----
> From: Sumit Garg <sumit.garg@linaro.org>
> 
> Hi Chris,
> 
> On Sat, 3 Nov 2018 at 05:25, Chris Co <Christopher.Co@microsoft.com> wrote:
> >
> > Hi Sumit,
> >
> > > -----Original Message-----
> > > From: Sumit Garg <sumit.garg@linaro.org>
> > >
> > > + OP-TEE ML.
> > >
> > > On Fri, 2 Nov 2018 at 06:11, Chris Co <Christopher.Co@microsoft.com>
> wrote:
> > > >
> > > > Hi Sumit,
> > > >
> > > > Our full OpteeClientPkg has:
> > > > - Our OpteeClientAPI implementation. I was monitoring the merge
> > > > progress
> > > on OpteeLib and will look into moving over now that it is available.
> > > > - The fTPM and AuthVar TA binaries. In our current design, the TA
> > > > binaries
> > > are loaded at runtime. We could host the binaries themselves
> > > elsewhere on the filesystem, but we do not want these binaries as
> > > early/pseudo TAs. Is there a plan for OpteeLib to support loading full TAs?
> > >
> > > Early TAs [1] are basically full TAs only, running in Secure EL0 mode.
> > > So instead of loading TA from normal world file-system, they are
> > > linked into a special data section in the OP-TEE core blob.
> > >
> > > Also I don't think loading TAs dynamically especially during boot
> > > makes much sense due to following reasons:
> > > 1. Increased boot time.
> > > 2. Fixed TAs like in your case which could be linked as early TAs as well.
> > >
> >
> > We prefer to load TAs dynamically for a more flexible servicing story. My
> understanding is that Early TAs are coupled with the OP-TEE binary itself, so
> to update an Early TA, a new OP-TEE binary would need to be created and
> pushed. We want to avoid rolling a new OP-TEE and only update the TA
> binary in this scenario.
> >
> 
> Are you referring to run-time updates on the device in the field? If this is the
> case then how do you think to update TAs, is it via some custom capsule
> update method?
> 

Yes, run-time TA updates. Currently, our fTPM and Authvar TAs get packaged inside our UEFI binary. So an update to a TA means a UEFI update via firmware capsule.
The discussion of these TA binaries living on the filesystem were ideas we were discussing internally but are not fully baked or committed to.

> I do consider these TAs used during boot as essential secure services provided
> by the secure firmware (OP-TEE in this case). So these TAs should be part of
> firmware itself and updates for them should come through firmware capsule
> updates only.
> 

I agree in principle and I think I see where the misalignment is, mostly coming from my end.
The security guarantees (termed TCPS) we want to provide on the current hardware we support (NXP i.MX6), mean OP-TEE becomes prohibitively difficult to update. This is due to a hardware resource limitation (not enough fuse space). If this limitation were not present, we could freely update OP-TEE and package these TAs as EarlyTAs.

Info on TCPS (whitepaper at bottom of post) - https://www.microsoft.com/en-us/microsoft-365/blog/2018/04/24/trusted-cyber-physical-systems-looks-to-protect-your-critical-infrastructure-from-modern-threats-in-the-world-of-iot/

I'm not sure how you want to handle this from an OpteeLib vs custom platform package perspective.

> > > And you mentioned filesystem, are you referring to root filesystem?
> > >
> >
> > We have not implemented this yet, but we were thinking to have the TA
> binaries present in the EFI partition.
> >
> 
> AFAIK, EFI partition is shared among Linux and UEFI. This provides Linux
> access to secure firmware TAs that could be a security concern (denial of
> service could be one of them).
> 

Note - we are booting Windows, though your point here is still valid. The TAs living in the filesystem is not what is implemented today. It was an idea we were discussing internally.

> > > > - We have two client drivers: a firmware TPM TA driver and an
> > > authenticated variable TA driver. These talk through the
> > > tee-supplicant to their respective TAs.
> > > >
> > >
> > > Here from tee-supplicant apart from loading TAs, what other services
> > > are you expecting? If you are looking for secure storage via RPMB,
> > > that could be an enhancement to OpteeLib adding corresponding RPC
> handling here [2].
> > >
> >
> > For RPC handling, we are looking for the following callback support:
> > - OPTEE_SMC_RPC_FUNC_ALLOC
> > - OPTEE_SMC_RPC_FUNC_FREE
> > - OPTEE_SMC_RPC_FUNC_CMD
> >         - OPTEE_MSG_RPC_CMD_LOAD_TA
> 
> Please see above comments for this.
> 
> >         - OPTEE_MSG_RPC_CMD_RPMB
> >         - OPTEE_MSG_RPC_CMD_GET_TIME
> 
> Can you share the usage of OPTEE_MSG_RPC_CMD_GET_TIME? AFAIK, this is
> used to get REE time from OP-TEE.
> 

I dug further and found that this was being used in our fTPM TA for debug logs. It has since been deprecated so we do not need this RPC command.

> >         - OPTEE_MSG_RPC_CMD_SHM_ALLOC
> >         - OPTEE_MSG_RPC_CMD_SHM_FREE
> >         - OPTEE_MSG_RPC_CMD_WAIT_QUEUE
> 
> I don't think we need OPTEE_MSG_RPC_CMD_WAIT_QUEUE implementation
> in UEFI as its a single threaded execution flow on boot core.
> 

Agreed. Our implementation is effectively a no-op. We don't need this either.

> BTW, I am not sure if I could get time to work on RPC handling anytime soon.
> So patches are welcome and I am happy to review them.
> 

I'll see if I can find time to port over our RPC handlers. Will add you to any patches for review.

Thanks,
Chris

> Regards,
> Sumit
> 
> >
> > Thanks,
> > Chris
> >
> > > [1]
> > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> > > hub.c
> > > om%2FOP-
> > >
> TEE%2Foptee_os%2Fblob%2Fmaster%2Fdocumentation%2Foptee_design.md
> > > %23early-trusted-
> > >
> applications&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C4a
> > >
> 7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd011db47%
> > >
> 7C1%7C0%7C636767330779998429&amp;sdata=yaDWw5Z6yuux1o89kxzbknVp
> > > b%2B1OHUagbB%2FOGS4dAcU%3D&amp;reserved=0
> > > [2]
> > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> > > hub.c
> > >
> om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FLibrary%2FOpteeL
> > >
> ib%2FOptee.c%23L147&amp;data=02%7C01%7CChristopher.Co%40microsoft.c
> > >
> om%7C4a7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd
> > >
> 011db47%7C1%7C0%7C636767330779998429&amp;sdata=Lsplb1L7Ugd2C6cXG
> > > 8gBo40Ei8UQPtIA7fNEDL1t%2Fbg%3D&amp;reserved=0
> > >
> > > Regards,
> > > Sumit
> > >
> > > > Chris
> > > >
> > > > > -----Original Message-----
> > > > > From: Sumit Garg <sumit.garg@linaro.org>
> > > > > Sent: Thursday, November 1, 2018 3:55 AM
> > > > > To: Chris Co <Christopher.Co@microsoft.com>; Leif Lindholm
> > > > > <leif.lindholm@linaro.org>
> > > > > Cc: edk2-devel@lists.01.org; Ard Biesheuvel
> > > > > <ard.biesheuvel@linaro.org>; Michael D Kinney
> > > > > <michael.d.kinney@intel.com>
> > > > > Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft:
> > > > > Add OpteeClientPkg dec
> > > > >
> > > > > Hi Christopher,
> > > > >
> > > > > Optee Client library has recently been merged to edk2 source code.
> > > > > It tries to provide a generic interface [1] to OP-TEE based
> > > > > trusted applications (pseudo/early).
> > > > >
> > > > > AFAIK, you don't need any platform specific hook in client
> > > > > interface to work with upstream OP-TEE. So instead you should use
> Optee library.
> > > > >
> > > > > [1]
> > > > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> > > > > Fgit
> > > > > hub.c
> > > > >
> > >
> om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FInclude%2FLibrary
> > > > >
> > >
> %2FOpteeLib.h&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C
> > > > >
> > >
> c19b84ef7f8f4213424108d63fe88f66%7C72f988bf86f141af91ab2d7cd011db47
> > > > >
> > >
> %7C1%7C0%7C636766665404786500&amp;sdata=m24akbKtoyCERVN77meoSU
> > > > > H6E%2Bpf8W2P5MF7nvU5y7I%3D&amp;reserved=0
> > > > >
> > > > > Regards,
> > > > > Sumit
> > > > >
> > > > > On Thu, 1 Nov 2018 at 02:13, Leif Lindholm
> > > > > <leif.lindholm@linaro.org>
> > > wrote:
> > > > > >
> > > > > > +Sumit (just to loop you two together). Is there anything
> > > > > > +Microsoft
> > > > > > platform specific about what will go in here?
> > > > > >
> > > > > > /
> > > > > >     Leif
> > > > > >
> > > > > > On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > > > > > > On Windows IoT Core devices with ARM TrustZone capabilities,
> > > > > > > EDK2 runs in normal world and we use OP-TEE to execute
> > > > > > > secure world operations. The overall package will contain
> > > > > > > client-side support to invoke EDK2 services implemented as
> > > > > > > OP-TEE trusted applications that run in secure world.
> > > > > > >
> > > > > > > This commit adds the initial dec file to add some PCD
> > > > > > > settings needed by other packages.
> > > > > > >
> > > > > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > > > > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > > > > > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > > > > > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > > > > > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > > > > > ---
> > > > > > >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49
> > > > > > > ++++++++++++++++++++
> > > > > > >  1 file changed, 49 insertions(+)
> > > > > > >
> > > > > > > diff --git
> > > > > > > a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > > b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..4752eab39ce3
> > > > > > > --- /dev/null
> > > > > > > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > > @@ -0,0 +1,49 @@
> > > > > > > +## @file
> > > > > > > +#
> > > > > > > +#  OP-TEE client package
> > > > > > > +#
> > > > > > > +#  OP-TEE client package contains the client-side interface
> > > > > > > +to invoke OP-
> > > > > TEE TAs.
> > > > > > > +#  Certain EDKII services are implemented in Trusted
> > > > > > > +Applications running in #  the secure world OP-TEE OS.
> > > > > > > +#
> > > > > > > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > > > > > +#
> > > > > > > +#  This program and the accompanying materials #  are
> > > > > > > +licensed and made available under the terms and conditions
> > > > > > > +of the BSD License # which accompanies this distribution.
> > > > > > > +The full text of the license may be found at #
> > > > > > > +https://na01.safelinks.protection.outlook.com/?url=http%3A%
> > > > > > > +2F%2
> > > > > > > +Fope
> > > > > > > +nsource.org%2Flicenses%2Fbsd-
> > > > > license.php&amp;data=02%7C01%7CChristo
> > > > > > >
> > > > >
> > >
> +pher.Co%40microsoft.com%7Cc19b84ef7f8f4213424108d63fe88f66%7C72f988
> > > > > > >
> > > > >
> > >
> +bf86f141af91ab2d7cd011db47%7C1%7C0%7C636766665404786500&amp;sda
> > > > > ta=1
> > > > > > >
> > > +MxFvlsMPhk19grEexBXo5VqRd0jZaCSRjxZCi87A2w%3D&amp;reserved=0
> > > > > > > +#
> > > > > > > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN
> > > > > > > +"AS
> > > IS"
> > > > > > > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> > > > > > > +KIND,
> > > > > EITHER EXPRESS OR IMPLIED.
> > > > > > > +#
> > > > > > > +##
> > > > > > > +
> > > > > > > +[Defines]
> > > > > > > +  DEC_SPECIFICATION              = 0x0001001A
> > > > > > > +  PACKAGE_NAME                   = OpteeClientPkg
> > > > > > > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-
> > > 1bdd74ec9595
> > > > > > > +  PACKAGE_VERSION                = 0.01
> > > > > > > +
> > > > > > > +[Includes]
> > > > > > > +
> > > > > > > +[LibraryClasses]
> > > > > > > +
> > > > > > > +[Guids]
> > > > > > > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25,
> 0x4156, {
> > > > > 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > > > > > > +
> > > > > > > +[PcdsFixedAtBuild]
> > > > > > > +
> > > > > > >
> > > > >
> > >
> +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x0000
> > > > > > > +0005
> > > > > > > +
> > > > > > >
> > > > >
> > >
> +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x0000
> > > > > > > +0006
> > > > > > > +
> > > > > > > +  ## The base address of the Trust Zone OpTEE OS private
> > > > > > > + memory region  # This memory is manager privately by the OpTEE
> OS.
> > > > > > > +
> > > > > > > +
> > > > >
> > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD
> > > > > > > + 1|UINT64|0x00000001
> > > > > > > +
> > > > > > > +  ## The size of the Trust Zone OpTEE OS private memory
> > > > > > > + region
> > > > > > > +
> > > > > > > +
> > > > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|U
> > > > > IN
> > > > > > > + T64|0x00000002
> > > > > > > +
> > > > > > > +  ## The base address of the Trust Zone OpTEE OS shared
> > > > > > > + memory region
> > > > > > > +
> > > > > > > +
> > > > >
> > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2
> > > > > > > + |UINT64|0x00000003
> > > > > > > +
> > > > > > > +  ## The size of the Trust Zone OpTEE OS shared memory
> > > > > > > + region
> > > > > > > +
> > > > > > > +
> > > > >
> > >
> gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UI
> > > > > > > + NT64|0x00000004
> > > > > > > --
> > > > > > > 2.16.2.gvfs.1.33.gf5370f1
> > > > > > >

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec
  2018-11-06  1:53               ` Chris Co
@ 2018-11-06 11:09                 ` Sumit Garg
  0 siblings, 0 replies; 75+ messages in thread
From: Sumit Garg @ 2018-11-06 11:09 UTC (permalink / raw)
  To: Christopher.Co
  Cc: Leif Lindholm, edk2-devel, Ard Biesheuvel, Michael D Kinney,
	tee-dev

Hi Chris,

On Tue, 6 Nov 2018 at 07:23, Chris Co <Christopher.Co@microsoft.com> wrote:
>
> Hi Sumit,
>
> > -----Original Message-----
> > From: Sumit Garg <sumit.garg@linaro.org>
> >
> > Hi Chris,
> >
> > On Sat, 3 Nov 2018 at 05:25, Chris Co <Christopher.Co@microsoft.com> wrote:
> > >
> > > Hi Sumit,
> > >
> > > > -----Original Message-----
> > > > From: Sumit Garg <sumit.garg@linaro.org>
> > > >
> > > > + OP-TEE ML.
> > > >
> > > > On Fri, 2 Nov 2018 at 06:11, Chris Co <Christopher.Co@microsoft.com>
> > wrote:
> > > > >
> > > > > Hi Sumit,
> > > > >
> > > > > Our full OpteeClientPkg has:
> > > > > - Our OpteeClientAPI implementation. I was monitoring the merge
> > > > > progress
> > > > on OpteeLib and will look into moving over now that it is available.
> > > > > - The fTPM and AuthVar TA binaries. In our current design, the TA
> > > > > binaries
> > > > are loaded at runtime. We could host the binaries themselves
> > > > elsewhere on the filesystem, but we do not want these binaries as
> > > > early/pseudo TAs. Is there a plan for OpteeLib to support loading full TAs?
> > > >
> > > > Early TAs [1] are basically full TAs only, running in Secure EL0 mode.
> > > > So instead of loading TA from normal world file-system, they are
> > > > linked into a special data section in the OP-TEE core blob.
> > > >
> > > > Also I don't think loading TAs dynamically especially during boot
> > > > makes much sense due to following reasons:
> > > > 1. Increased boot time.
> > > > 2. Fixed TAs like in your case which could be linked as early TAs as well.
> > > >
> > >
> > > We prefer to load TAs dynamically for a more flexible servicing story. My
> > understanding is that Early TAs are coupled with the OP-TEE binary itself, so
> > to update an Early TA, a new OP-TEE binary would need to be created and
> > pushed. We want to avoid rolling a new OP-TEE and only update the TA
> > binary in this scenario.
> > >
> >
> > Are you referring to run-time updates on the device in the field? If this is the
> > case then how do you think to update TAs, is it via some custom capsule
> > update method?
> >
>
> Yes, run-time TA updates. Currently, our fTPM and Authvar TAs get packaged inside our UEFI binary. So an update to a TA means a UEFI update via firmware capsule.
> The discussion of these TA binaries living on the filesystem were ideas we were discussing internally but are not fully baked or committed to.
>

I would suggest you to keep TAs as part of firmware only (UEFI binary
in your case).

> > I do consider these TAs used during boot as essential secure services provided
> > by the secure firmware (OP-TEE in this case). So these TAs should be part of
> > firmware itself and updates for them should come through firmware capsule
> > updates only.
> >
>
> I agree in principle and I think I see where the misalignment is, mostly coming from my end.
> The security guarantees (termed TCPS) we want to provide on the current hardware we support (NXP i.MX6), mean OP-TEE becomes prohibitively difficult to update. This is due to a hardware resource limitation (not enough fuse space). If this limitation were not present, we could freely update OP-TEE and package these TAs as EarlyTAs.
>

Now I understand where this requirement came from. It seems to be a
valid scenario where secure non-volatile memory is limited on a
particular platform.

> Info on TCPS (whitepaper at bottom of post) - https://www.microsoft.com/en-us/microsoft-365/blog/2018/04/24/trusted-cyber-physical-systems-looks-to-protect-your-critical-infrastructure-from-modern-threats-in-the-world-of-iot/
>
> I'm not sure how you want to handle this from an OpteeLib vs custom platform package perspective.
>

We could add this dynamic TA loading support in OpteeLib as optional,
enabled in a platform specific way.

Regards,
Sumit

> > > > And you mentioned filesystem, are you referring to root filesystem?
> > > >
> > >
> > > We have not implemented this yet, but we were thinking to have the TA
> > binaries present in the EFI partition.
> > >
> >
> > AFAIK, EFI partition is shared among Linux and UEFI. This provides Linux
> > access to secure firmware TAs that could be a security concern (denial of
> > service could be one of them).
> >
>
> Note - we are booting Windows, though your point here is still valid. The TAs living in the filesystem is not what is implemented today. It was an idea we were discussing internally.
>
> > > > > - We have two client drivers: a firmware TPM TA driver and an
> > > > authenticated variable TA driver. These talk through the
> > > > tee-supplicant to their respective TAs.
> > > > >
> > > >
> > > > Here from tee-supplicant apart from loading TAs, what other services
> > > > are you expecting? If you are looking for secure storage via RPMB,
> > > > that could be an enhancement to OpteeLib adding corresponding RPC
> > handling here [2].
> > > >
> > >
> > > For RPC handling, we are looking for the following callback support:
> > > - OPTEE_SMC_RPC_FUNC_ALLOC
> > > - OPTEE_SMC_RPC_FUNC_FREE
> > > - OPTEE_SMC_RPC_FUNC_CMD
> > >         - OPTEE_MSG_RPC_CMD_LOAD_TA
> >
> > Please see above comments for this.
> >
> > >         - OPTEE_MSG_RPC_CMD_RPMB
> > >         - OPTEE_MSG_RPC_CMD_GET_TIME
> >
> > Can you share the usage of OPTEE_MSG_RPC_CMD_GET_TIME? AFAIK, this is
> > used to get REE time from OP-TEE.
> >
>
> I dug further and found that this was being used in our fTPM TA for debug logs. It has since been deprecated so we do not need this RPC command.
>
> > >         - OPTEE_MSG_RPC_CMD_SHM_ALLOC
> > >         - OPTEE_MSG_RPC_CMD_SHM_FREE
> > >         - OPTEE_MSG_RPC_CMD_WAIT_QUEUE
> >
> > I don't think we need OPTEE_MSG_RPC_CMD_WAIT_QUEUE implementation
> > in UEFI as its a single threaded execution flow on boot core.
> >
>
> Agreed. Our implementation is effectively a no-op. We don't need this either.
>
> > BTW, I am not sure if I could get time to work on RPC handling anytime soon.
> > So patches are welcome and I am happy to review them.
> >
>
> I'll see if I can find time to port over our RPC handlers. Will add you to any patches for review.
>
> Thanks,
> Chris
>
> > Regards,
> > Sumit
> >
> > >
> > > Thanks,
> > > Chris
> > >
> > > > [1]
> > > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> > > > hub.c
> > > > om%2FOP-
> > > >
> > TEE%2Foptee_os%2Fblob%2Fmaster%2Fdocumentation%2Foptee_design.md
> > > > %23early-trusted-
> > > >
> > applications&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C4a
> > > >
> > 7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd011db47%
> > > >
> > 7C1%7C0%7C636767330779998429&amp;sdata=yaDWw5Z6yuux1o89kxzbknVp
> > > > b%2B1OHUagbB%2FOGS4dAcU%3D&amp;reserved=0
> > > > [2]
> > > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> > > > hub.c
> > > >
> > om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FLibrary%2FOpteeL
> > > >
> > ib%2FOptee.c%23L147&amp;data=02%7C01%7CChristopher.Co%40microsoft.c
> > > >
> > om%7C4a7d8c01e4804365f4eb08d640837a15%7C72f988bf86f141af91ab2d7cd
> > > >
> > 011db47%7C1%7C0%7C636767330779998429&amp;sdata=Lsplb1L7Ugd2C6cXG
> > > > 8gBo40Ei8UQPtIA7fNEDL1t%2Fbg%3D&amp;reserved=0
> > > >
> > > > Regards,
> > > > Sumit
> > > >
> > > > > Chris
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Sumit Garg <sumit.garg@linaro.org>
> > > > > > Sent: Thursday, November 1, 2018 3:55 AM
> > > > > > To: Chris Co <Christopher.Co@microsoft.com>; Leif Lindholm
> > > > > > <leif.lindholm@linaro.org>
> > > > > > Cc: edk2-devel@lists.01.org; Ard Biesheuvel
> > > > > > <ard.biesheuvel@linaro.org>; Michael D Kinney
> > > > > > <michael.d.kinney@intel.com>
> > > > > > Subject: Re: [PATCH edk2-platforms 01/27] Platform/Microsoft:
> > > > > > Add OpteeClientPkg dec
> > > > > >
> > > > > > Hi Christopher,
> > > > > >
> > > > > > Optee Client library has recently been merged to edk2 source code.
> > > > > > It tries to provide a generic interface [1] to OP-TEE based
> > > > > > trusted applications (pseudo/early).
> > > > > >
> > > > > > AFAIK, you don't need any platform specific hook in client
> > > > > > interface to work with upstream OP-TEE. So instead you should use
> > Optee library.
> > > > > >
> > > > > > [1]
> > > > > > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> > > > > > Fgit
> > > > > > hub.c
> > > > > >
> > > >
> > om%2Ftianocore%2Fedk2%2Fblob%2Fmaster%2FArmPkg%2FInclude%2FLibrary
> > > > > >
> > > >
> > %2FOpteeLib.h&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C
> > > > > >
> > > >
> > c19b84ef7f8f4213424108d63fe88f66%7C72f988bf86f141af91ab2d7cd011db47
> > > > > >
> > > >
> > %7C1%7C0%7C636766665404786500&amp;sdata=m24akbKtoyCERVN77meoSU
> > > > > > H6E%2Bpf8W2P5MF7nvU5y7I%3D&amp;reserved=0
> > > > > >
> > > > > > Regards,
> > > > > > Sumit
> > > > > >
> > > > > > On Thu, 1 Nov 2018 at 02:13, Leif Lindholm
> > > > > > <leif.lindholm@linaro.org>
> > > > wrote:
> > > > > > >
> > > > > > > +Sumit (just to loop you two together). Is there anything
> > > > > > > +Microsoft
> > > > > > > platform specific about what will go in here?
> > > > > > >
> > > > > > > /
> > > > > > >     Leif
> > > > > > >
> > > > > > > On Fri, Sep 21, 2018 at 08:25:53AM +0000, Chris Co wrote:
> > > > > > > > On Windows IoT Core devices with ARM TrustZone capabilities,
> > > > > > > > EDK2 runs in normal world and we use OP-TEE to execute
> > > > > > > > secure world operations. The overall package will contain
> > > > > > > > client-side support to invoke EDK2 services implemented as
> > > > > > > > OP-TEE trusted applications that run in secure world.
> > > > > > > >
> > > > > > > > This commit adds the initial dec file to add some PCD
> > > > > > > > settings needed by other packages.
> > > > > > > >
> > > > > > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > > > > > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > > > > > > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > > > > > > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > > > > > > > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > > > > > > > ---
> > > > > > > >  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec | 49
> > > > > > > > ++++++++++++++++++++
> > > > > > > >  1 file changed, 49 insertions(+)
> > > > > > > >
> > > > > > > > diff --git
> > > > > > > > a/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > > > b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..4752eab39ce3
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> > > > > > > > @@ -0,0 +1,49 @@
> > > > > > > > +## @file
> > > > > > > > +#
> > > > > > > > +#  OP-TEE client package
> > > > > > > > +#
> > > > > > > > +#  OP-TEE client package contains the client-side interface
> > > > > > > > +to invoke OP-
> > > > > > TEE TAs.
> > > > > > > > +#  Certain EDKII services are implemented in Trusted
> > > > > > > > +Applications running in #  the secure world OP-TEE OS.
> > > > > > > > +#
> > > > > > > > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > > > > > > +#
> > > > > > > > +#  This program and the accompanying materials #  are
> > > > > > > > +licensed and made available under the terms and conditions
> > > > > > > > +of the BSD License # which accompanies this distribution.
> > > > > > > > +The full text of the license may be found at #
> > > > > > > > +https://na01.safelinks.protection.outlook.com/?url=http%3A%
> > > > > > > > +2F%2
> > > > > > > > +Fope
> > > > > > > > +nsource.org%2Flicenses%2Fbsd-
> > > > > > license.php&amp;data=02%7C01%7CChristo
> > > > > > > >
> > > > > >
> > > >
> > +pher.Co%40microsoft.com%7Cc19b84ef7f8f4213424108d63fe88f66%7C72f988
> > > > > > > >
> > > > > >
> > > >
> > +bf86f141af91ab2d7cd011db47%7C1%7C0%7C636766665404786500&amp;sda
> > > > > > ta=1
> > > > > > > >
> > > > +MxFvlsMPhk19grEexBXo5VqRd0jZaCSRjxZCi87A2w%3D&amp;reserved=0
> > > > > > > > +#
> > > > > > > > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN
> > > > > > > > +"AS
> > > > IS"
> > > > > > > > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> > > > > > > > +KIND,
> > > > > > EITHER EXPRESS OR IMPLIED.
> > > > > > > > +#
> > > > > > > > +##
> > > > > > > > +
> > > > > > > > +[Defines]
> > > > > > > > +  DEC_SPECIFICATION              = 0x0001001A
> > > > > > > > +  PACKAGE_NAME                   = OpteeClientPkg
> > > > > > > > +  PACKAGE_GUID                   = 77416fcb-10ec-4693-bdc0-
> > > > 1bdd74ec9595
> > > > > > > > +  PACKAGE_VERSION                = 0.01
> > > > > > > > +
> > > > > > > > +[Includes]
> > > > > > > > +
> > > > > > > > +[LibraryClasses]
> > > > > > > > +
> > > > > > > > +[Guids]
> > > > > > > > +  gOpteeClientPkgTokenSpaceGuid   = { 0x04ad34ca, 0xdd25,
> > 0x4156, {
> > > > > > 0x90, 0xf5, 0x16, 0xf9, 0x40, 0xd0, 0x49, 0xe3 }}
> > > > > > > > +
> > > > > > > > +[PcdsFixedAtBuild]
> > > > > > > > +
> > > > > > > >
> > > > > >
> > > >
> > +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0|UINT64|0x0000
> > > > > > > > +0005
> > > > > > > > +
> > > > > > > >
> > > > > >
> > > >
> > +gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0|UINT32|0x0000
> > > > > > > > +0006
> > > > > > > > +
> > > > > > > > +  ## The base address of the Trust Zone OpTEE OS private
> > > > > > > > + memory region  # This memory is manager privately by the OpTEE
> > OS.
> > > > > > > > +
> > > > > > > > +
> > > > > >
> > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0xDEAD
> > > > > > > > + 1|UINT64|0x00000001
> > > > > > > > +
> > > > > > > > +  ## The size of the Trust Zone OpTEE OS private memory
> > > > > > > > + region
> > > > > > > > +
> > > > > > > > +
> > > > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|55|U
> > > > > > IN
> > > > > > > > + T64|0x00000002
> > > > > > > > +
> > > > > > > > +  ## The base address of the Trust Zone OpTEE OS shared
> > > > > > > > + memory region
> > > > > > > > +
> > > > > > > > +
> > > > > >
> > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0xDEAD2
> > > > > > > > + |UINT64|0x00000003
> > > > > > > > +
> > > > > > > > +  ## The size of the Trust Zone OpTEE OS shared memory
> > > > > > > > + region
> > > > > > > > +
> > > > > > > > +
> > > > > >
> > > >
> > gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0xAA|UI
> > > > > > > > + NT64|0x00000004
> > > > > > > > --
> > > > > > > > 2.16.2.gvfs.1.33.gf5370f1
> > > > > > > >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library
  2018-09-21  8:26 ` [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library Chris Co
@ 2018-11-08 18:00   ` Leif Lindholm
  2018-12-04  1:41     ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-11-08 18:00 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:03AM +0000, Chris Co wrote:
> This adds support for initializing and manipulating the I/O Pads
> on NXP i.MX6 SoCs.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c      | 151 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf |  41 ++++++
>  2 files changed, 192 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
> new file mode 100644
> index 000000000000..7c0c7b54a2fe
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
> @@ -0,0 +1,151 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6IoMux.h>
> +
> +// Muxing functions
> +VOID
> +ImxPadConfig (
> +  IN  IMX_PAD     Pad,
> +  IN  IMX_PADCFG  PadConfig

I'll get back to reviewing patch 11 at some point, but that one is
hard going. So I'll point out here what I'll mention then:
Please just use UINT64. Typedefs are useful to reduce pointless
repetition for structs, but here it just obscures what is
programatically going on.

> +  )
> +{
> +  // Configure Mux Control
> +  MmioWrite32 (
> +    IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad),
> +    _IMX_PADCFG_MUX_CTL (PadConfig));

It would be worth adding macros or simple accessor functions for these -
there's a lot of text in this file that has no semantic value and
needs to be manually filtered when reading.

I.e. IomuxWrite32 (Pad, ...), IomuxRead32 (Pad), ...

Other comment really belonging to 11:
Please drop leading _ from macros. Such macros are intended for
internal use by toolchains.

> +
> +  // Configure Select Input Control
> +  if (_IMX_PADCFG_SEL_INP (PadConfig) != 0) {
> +    DEBUG ((DEBUG_INFO, "Setting INPUT_SELECT %x value %x\n",
> +            _IMX_SEL_INP_REGISTER (_IMX_PADCFG_SEL_INP (PadConfig)),
> +            _IMX_SEL_INP_VALUE (_IMX_PADCFG_SEL_INP (PadConfig))));
> +
> +    MmioWrite32 (
> +      _IMX_SEL_INP_REGISTER (_IMX_PADCFG_SEL_INP (PadConfig)),
> +      _IMX_SEL_INP_VALUE (_IMX_PADCFG_SEL_INP (PadConfig)));
> +  }
> +
> +  // Configure Pad Control
> +  MmioWrite32 (
> +    IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad),
> +    _IMX_PADCFG_PAD_CTL (PadConfig));
> +}
> +
> +VOID
> +ImxPadDumpConfig (
> +  IN  CHAR8 *SignalFriendlyName,
> +  IN  IMX_PAD Pad
> +  )
> +{
> +  IMX_IOMUXC_MUX_CTL  MuxCtl;
> +  IMX_IOMUXC_PAD_CTL  PadCtl;
> +
> +  MuxCtl.AsUint32 = MmioRead32 (
> +                      IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad));
> +
> +  DEBUG ((
> +           DEBUG_INIT,
> +           "- %a MUX_CTL(0x%p)=0x%08x: MUX_MODE:%d SION:%d | ",
> +           SignalFriendlyName,
> +           IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad),
> +           MuxCtl.AsUint32,
> +           MuxCtl.Fields.MUX_MODE,
> +           MuxCtl.Fields.SION));
> +
> +  PadCtl.AsUint32 = MmioRead32 (
> +                      IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad));
> +
> +  DEBUG ((
> +           DEBUG_INIT,
> +           "PAD_CTL(0x%p)=0x%08x: SRE:%d DSE:%d SPEED:%d ODE:%d PKE:%d PUE:%d PUS:%d HYS:%d\n",
> +           IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad),
> +           PadCtl.AsUint32,
> +           PadCtl.Fields.SRE,
> +           PadCtl.Fields.DSE,
> +           PadCtl.Fields.SPEED,
> +           PadCtl.Fields.ODE,
> +           PadCtl.Fields.PKE,
> +           PadCtl.Fields.PUE,
> +           PadCtl.Fields.PUS,
> +           PadCtl.Fields.HYS));
> +}
> +
> +// GPIO functions
> +VOID
> +ImxGpioDirection (
> +  IN  IMX_GPIO_BANK   Bank,
> +  IN  UINT32          IoNumber,
> +  IN  IMX_GPIO_DIR    Direction
> +  )
> +{
> +  volatile IMX_GPIO_REGISTERS   *gpioRegisters;

What makes this pointer volatile?
(Hint: drop it, it does nothing useful here.)

That initial 'g', following EDK2 naming rules, says that this is a
variable in the global namespace, exported from this module. It should
be GpioRegisters.

> +
> +  ASSERT (IoNumber < 32);

That 32 needs a #define.

> +
> +  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;
> +  if (Direction == IMX_GPIO_DIR_INPUT) {
> +    MmioAnd32 ((UINTN) &gpioRegisters->Banks[Bank - 1].GDIR, ~ (1 << IoNumber));

This 'Bank - 1' stuff looks a bit scary. Why aren't we passing the
inde to use? A comment block before the function could explain what
the inputs are meant to be.

> +  } else {
> +    MmioOr32 ((UINTN) &gpioRegisters->Banks[Bank - 1].GDIR, 1 << IoNumber);

Since we're doing 1 << IoNumber on all possible routes through this
function, could we assign it to a temporary variable? And we're doing
it to the same bank.

If I wrote this function, I'd probably do something more like

  UINTN DirectionRegister;
  UINT32 Pin;
  DirectionRegister = (UINTN)&((IMX_GPIO_REGISTERS *)IMX_GPIO_BASE)->Banks[Bank - 1].GDIR;
  Pin = 1 << IoNumber;

  if (Direction == IMX_GPIO_DIR_INPUT) {
    MmioAnd32 (DirectionRegister, ~Pin);
  } else {
    MmioOr32 (DirectionRegister, Pin);
  }

> +  }
> +}
> +
> +VOID
> +ImxGpioWrite (
> +  IN  IMX_GPIO_BANK   Bank,
> +  IN  UINT32          IoNumber,
> +  IN  IMX_GPIO_VALUE  Value
> +  )
> +{
> +  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
> +
> +  ASSERT (IoNumber < 32);
> +
> +  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;
> +  if (Value == IMX_GPIO_LOW) {
> +    MmioAnd32 ((UINTN) &gpioRegisters->Banks[Bank - 1].DR, ~ (1 << IoNumber));
> +  } else {
> +    MmioOr32 ((UINTN) &gpioRegisters->Banks[Bank - 1].DR, 1 << IoNumber);
> +  }

All the same comments as above.

> +}
> +
> +IMX_GPIO_VALUE
> +ImxGpioRead (
> +  IN  IMX_GPIO_BANK   Bank,
> +  IN  UINT32          IoNumber
> +  )
> +{
> +  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
> +  UINT32                        Mask;
> +  UINT32                        Psr;
> +
> +  ASSERT (IoNumber < 32);
> +
> +  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;
> +  Mask = (1 << IoNumber);
> +  Psr = MmioRead32 ((UINTN) &gpioRegisters->Banks[Bank - 1].PSR);
> +
> +  if (Psr & Mask) {
> +    return IMX_GPIO_HIGH;
> +  } else {
> +    return IMX_GPIO_LOW;
> +  }

Some of the same comments as above :)
(I.e., those that apply.)

/
    Leif

> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
> new file mode 100644
> index 000000000000..84bbbee5c1db
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = iMX6IoMuxLib
> +  FILE_GUID                      = FA41BEF0-0666-4C07-9EC3-47F61C36EDBE
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = iMX6IoMuxLib
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  IoLib
> +  TimerLib
> +
> +[Sources.common]
> +  iMX6IoMux.c
> +
> + [FixedPcd]
> +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
  2018-09-21  8:26 ` [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers Chris Co
@ 2018-11-08 18:14   ` Leif Lindholm
  2018-12-04  2:06     ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-11-08 18:14 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:05AM +0000, Chris Co wrote:
> This adds the definitions for the NXP i.MX6 General Purpose Timer
> and the Enhanced Periodic Interrupt Timer modules.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Include/common_epit.h | 118 +++++++++
>  Silicon/NXP/iMX6Pkg/Include/common_gpt.h  | 271 ++++++++++++++++++++
>  2 files changed, 389 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Include/common_epit.h b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> new file mode 100644
> index 000000000000..485d6ccbc51e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/common_epit.h

Rename to CamelCase?

> @@ -0,0 +1,118 @@
> +/** @file
> +*
> +*  Provides definitions for the EPIT (Enhanced Periodic Interrupt Timer)
> +*  module that are common to Freescale SoCs.
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright (c) 2004-2010, Freescale Semiconductor, Inc. All Rights Reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef __COMMON_EPIT_H
> +#define __COMMON_EPIT_H

COMMON is a bit too common. Can we at least stick an IMX on the front?

This is really also a problem for all of the structs and #defines
below as well.

> +
> +typedef struct {
> +  UINT32 CR;
> +  UINT32 SR;
> +  UINT32 LR;
> +  UINT32 CMPR;
> +  UINT32 CNT;
> +} CSP_EPIT_REG, *PCSP_EPIT_REG;

I'm really not a fan of typedef pointers. Please drop the *PSCP one.

> +
> +#define EPIT_CR_OFFSET          0x0000
> +#define EPIT_SR_OFFSET          0x0004
> +#define EPIT_LR_OFFSET          0x0008
> +#define EPIT_CMPR_OFFSET        0x000C
> +#define EPIT_CNR_OFFSET         0x0010
> +
> +#define EPIT_CR_EN_LSH          0

What is LSH?

> +#define EPIT_CR_ENMOD_LSH       1
> +#define EPIT_CR_OCIEN_LSH       2
> +#define EPIT_CR_RLD_LSH         3
> +#define EPIT_CR_PRESCALAR_LSH   4
> +#define EPIT_CR_SWR_LSH         16
> +#define EPIT_CR_IOVW_LSH        17
> +#define EPIT_CR_DBGEN_LSH       18
> +#define EPIT_CR_WAITEN_LSH      19
> +#define EPIT_CR_DOZEN_LSH       20
> +#define EPIT_CR_STOPEN_LSH      21
> +#define EPIT_CR_OM_LSH          22
> +#define EPIT_CR_CLKSRC_LSH      24
> +
> +#define EPIT_SR_OCIF_LSH        0
> +#define EPIT_LR_LOAD_LSH        0
> +#define EPIT_CMPR_COMPARE_LSH   0
> +#define EPIT_CNT_COUNT_LSH      0
> +
> +#define EPIT_CR_EN_WID          1

What is WID?

> +#define EPIT_CR_ENMOD_WID       1
> +#define EPIT_CR_OCIEN_WID       2
> +#define EPIT_CR_RLD_WID         1
> +#define EPIT_CR_PRESCALAR_WID   12
> +#define EPIT_CR_SWR_WID         1
> +#define EPIT_CR_IOVW_WID        1
> +#define EPIT_CR_DBGEN_WID       1
> +#define EPIT_CR_WAITEN_WID      1
> +#define EPIT_CR_DOZEN_WID       1
> +#define EPIT_CR_STOPEN_WID      1
> +#define EPIT_CR_OM_WID          2
> +#define EPIT_CR_CLKSRC_WID      2
> +
> +#define EPIT_SR_OCIF_WID        1
> +#define EPIT_LR_LOAD_WID        32
> +#define EPIT_CMPR_COMPARE_WID   32
> +#define EPIT_CNT_COUNT_WID      32
> +
> +// CR
> +#define EPIT_CR_EN_DISABLE          0
> +#define EPIT_CR_EN_ENABLE           1
> +
> +#define EPIT_CR_ENMOD_RESUME        0
> +#define EPIT_CR_ENMOD_LOAD          1
> +
> +#define EPIT_CR_OCIEN_DISABLE       0
> +#define EPIT_CR_OCIEN_ENABLE        1
> +
> +#define EPIT_CR_RLD_ROLLOVER        0
> +#define EPIT_CR_RLD_RELOAD          1
> +
> +#define EPIT_CR_SWR_NORESET         0
> +#define EPIT_CR_SWR_RESET           1
> +
> +#define EPIT_CR_IOVW_NOOVR          0
> +#define EPIT_CR_IOVW_OVR            1
> +
> +#define EPIT_CR_DBGEN_INACTIVE      0
> +#define EPIT_CR_DBGEN_ACTIVE        1
> +
> +#define EPIT_CR_WAITEN_DISABLE      0
> +#define EPIT_CR_WAITEN_ENABLE       1
> +
> +#define EPIT_CR_DOZEN_DISABLE       0
> +#define EPIT_CR_DOZEN_ENABLE        1
> +
> +#define EPIT_CR_STOPEN_DISABLE      0
> +#define EPIT_CR_STOPEN_ENABLE       1
> +
> +#define EPIT_CR_OM_DICONNECT        0
> +#define EPIT_CR_OM_TOGGLE           1
> +#define EPIT_CR_OM_CLEAR            2
> +#define EPIT_CR_OM_SET              3
> +
> +#define EPIT_CR_CLKSRC_OFF          0
> +#define EPIT_CR_CLKSRC_IPGCLK       1
> +#define EPIT_CR_CLKSRC_HIGHFREQ     2   // High freq is sourcing from PERCLK
> +#define EPIT_CR_CLKSRC_CKIL         3
> +
> +// CNT
> +#define EPIT_CNT_COUNT_MAX          0xFFFFFFFF

MAX_UINT32?

> +
> +#endif // __COMMON_EPIT_H
> diff --git a/Silicon/NXP/iMX6Pkg/Include/common_gpt.h b/Silicon/NXP/iMX6Pkg/Include/common_gpt.h
> new file mode 100644
> index 000000000000..7fdfc25d819f
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/common_gpt.h

Rename to CamelCase.

> @@ -0,0 +1,271 @@
> +/** @file
> +*
> +*  Provides definitions for the GPT (General Purpose Timer) module
> +*  that are common to Freescale SoCs.
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright (c) 2004-2010, Freescale Semiconductor, Inc. All Rights Reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef __COMMON_GPT_H
> +#define __COMMON_GPT_H

+IMX.

> +
> +typedef struct {
> +  UINT32 CR;
> +  UINT32 PR;
> +  UINT32 SR;
> +  UINT32 IR;
> +  UINT32 OCR1;
> +  UINT32 OCR2;
> +  UINT32 OCR3;
> +  UINT32 ICR1;
> +  UINT32 ICR2;
> +  UINT32 CNT;
> +} CSP_GPT_REGS, *PCSP_GPT_REGS;

Drop *PCSP.

> +
> +#define GPT_CR_OFFSET          0x0000
> +#define GPT_PR_OFFSET          0x0004
> +#define GPT_SR_OFFSET          0x0008
> +#define GPT_IR_OFFSET          0x000C
> +#define GPT_OCR1_OFFSET        0x0010
> +#define GPT_OCR2_OFFSET        0x0014
> +#define GPT_OCR3_OFFSET        0x0018
> +#define GPT_ICR1_OFFSET        0x001C
> +#define GPT_ICR2_OFFSET        0x0020
> +#define GPT_CNT_OFFSET         0x0024
> +
> +
> +#define GPT_CR_EN_LSH          0

What is LSH?

> +#define GPT_CR_ENMOD_LSH       1
> +#define GPT_CR_DBGEN_LSH       2
> +#define GPT_CR_WAITEN_LSH      3
> +#define GPT_CR_STOPEN_LSH      5
> +#define GPT_CR_CLKSRC_LSH      6
> +#define GPT_CR_FRR_LSH         9
> +#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
> +#define GPT_CR_EN_24M_LSH      10
> +#endif
> +#define GPT_CR_SWR_LSH         15
> +#define GPT_CR_IM1_LSH         16
> +#define GPT_CR_IM2_LSH         18
> +#define GPT_CR_OM1_LSH         20
> +#define GPT_CR_OM2_LSH         23
> +#define GPT_CR_OM3_LSH         26
> +#define GPT_CR_FO1_LSH         29
> +#define GPT_CR_FO2_LSH         30
> +#define GPT_CR_FO3_LSH         31
> +
> +#define GPT_PR_PRESCALER_LSH   0
> +
> +#define GPT_SR_OF1_LSH         0
> +#define GPT_SR_OF2_LSH         1
> +#define GPT_SR_OF3_LSH         2
> +#define GPT_SR_IF1_LSH         3
> +#define GPT_SR_IF2_LSH         4
> +#define GPT_SR_ROV_LSH         5
> +
> +#define GPT_IR_OF1IE_LSH       0
> +#define GPT_IR_OF2IE_LSH       1
> +#define GPT_IR_OF3IE_LSH       2
> +#define GPT_IR_IF1IE_LSH       3
> +#define GPT_IR_IF2IE_LSH       4
> +#define GPT_IR_ROVIE_LSH       5
> +
> +#define GPT_OCR1_COMP_LSH      0
> +#define GPT_OCR2_COMP_LSH      0
> +#define GPT_OCR3_COMP_LSH      0
> +#define GPT_ICR1_CAPT_LSH      0
> +#define GPT_ICR2_CAPT_LSH      0
> +#define GPT_CNT_COUNT_LSH      0
> +
> +#define GPT_CR_EN_WID          1

What is WID?

/
    Leif

> +#define GPT_CR_ENMOD_WID       1
> +#define GPT_CR_DBGEN_WID       1
> +#define GPT_CR_WAITEN_WID      1
> +#define GPT_CR_STOPEN_WID      1
> +#define GPT_CR_CLKSRC_WID      3
> +#define GPT_CR_FRR_WID         1
> +#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
> +#define GPT_CR_EN_24M_WID      1
> +#endif
> +#define GPT_CR_SWR_WID         1
> +#define GPT_CR_IM1_WID         2
> +#define GPT_CR_IM2_WID         2
> +#define GPT_CR_OM1_WID         3
> +#define GPT_CR_OM2_WID         3
> +#define GPT_CR_OM3_WID         3
> +#define GPT_CR_FO1_WID         1
> +#define GPT_CR_FO2_WID         1
> +#define GPT_CR_FO3_WID         1
> +
> +#define GPT_PR_PRESCALER_WID   12
> +
> +#define GPT_SR_OF1_WID         1
> +#define GPT_SR_OF2_WID         1
> +#define GPT_SR_OF3_WID         1
> +#define GPT_SR_IF1_WID         1
> +#define GPT_SR_IF2_WID         1
> +#define GPT_SR_ROV_WID         1
> +
> +#define GPT_IR_OF1IE_WID       1
> +#define GPT_IR_OF2IE_WID       1
> +#define GPT_IR_OF3IE_WID       1
> +#define GPT_IR_IF1IE_WID       1
> +#define GPT_IR_IF2IE_WID       1
> +#define GPT_IR_ROVIE_WID       1
> +
> +#define GPT_OCR1_COMP_WID      32
> +#define GPT_OCR2_COMP_WID      32
> +#define GPT_OCR3_COMP_WID      32
> +#define GPT_ICR1_CAPT_WID      32
> +#define GPT_ICR2_CAPT_WID      32
> +#define GPT_CNT_COUNT_WID      32
> +
> +
> +//------------------------------------------------------------------------------
> +// REGISTER BIT WRITE VALUES
> +//------------------------------------------------------------------------------
> +
> +// GPTCR
> +#define GPT_CR_EN_ENABLE                1 // GPT enabled
> +#define GPT_CR_EN_DISABLE               0 // GPT disabled
> +
> +#define GPT_CR_ENMOD_RESET              1 // GPT counter reset to
> +                                          //   0 when disabled
> +#define GPT_CR_ENMOD_RETAIN             0 // GPT counter retains
> +                                          //   value when disabled
> +
> +#define GPT_CR_DBGEN_ENABLE             1 // GPT enabled in debug mode
> +#define GPT_CR_DBGEN_DISABLE            0 // GPT disabled in debug mode
> +
> +#define GPT_CR_WAITEN_ENABLE            1 // GPT enabled in wait mode
> +#define GPT_CR_WAITEN_DISABLE           0 // GPT disabled in wait mode
> +
> +#define GPT_CR_STOPEN_ENABLE            1 // GPT enabled in stopdoze mode
> +#define GPT_CR_STOPEN_DISABLE           0 // GPT disabled in stopoze mode
> +
> +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> +#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
> +#define GPT_CR_CLKSRC_IPGCLK            1 // ipg_clk is the clock source
> +#define GPT_CR_CLKSRC_HIGHFREQ          2 // ipg_clk_highfreq
> +#define GPT_CR_CLKSRC_EXTCLK            3 // ipp_gpt_clkin (external clock
> +// from pad) is the clock source
> +#define GPT_CR_CLKSRC_CLK32K            4 // ipg_clk_32k is clock source
> +#define GPT_CR_CLKSRC_CLK8M             5 // crystal oscillator divided by 8 is clock source
> +#define GPT_CR_CLKSRC_CLK24M            7 // crystal oscillator (24 Mhz) is clock source
> +#elif defined(CPU_IMX6SDL)
> +#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
> +#define GPT_CR_CLKSRC_IPGCLK            1 // Peripheral Clock
> +#define GPT_CR_CLKSRC_HIGHFREQ          2 // High Frequency Reference Clock
> +#define GPT_CR_CLKSRC_EXTCLK            3 // External Clock (CLKIN)
> +#define GPT_CR_CLKSRC_LOWFREQ           4 // Low Frequency Reference Clock
> +#define GPT_CR_CLKSRC_CLK24M            5 // Crystal oscillator as Reference Clock
> +#elif defined(CPU_IMX6SX)
> +#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
> +#define GPT_CR_CLKSRC_PERIPHCLK         1 // Peripheral Clock
> +#define GPT_CR_CLKSRC_HIGHFREQ          2 // High Frequency Reference Clock
> +#define GPT_CR_CLKSRC_EXTCLK            3 // External Clock (CLKIN)
> +#define GPT_CR_CLKSRC_LOWFREQ           4 // Low Frequency Reference Clock
> +#define GPT_CR_CLKSRC_CLK24M            5 // Crystal oscillator as Reference Clock
> +#else
> +#error CPU Preprocessor Flag Not Defined
> +#endif
> +
> +#define GPT_CR_FRR_FREERUN              1 // Freerun mode (counter
> +                                          //   continues after compare)
> +#define GPT_CR_FRR_RESTART              0 // Restart mode (counter set
> +                                          //   to zero after compare)
> +#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
> +#define GPT_CR_EN_24M_DISABLE           0  // 24M clock disabled
> +#define GPT_CR_EN_24M_ENABLE            1  // 24M clock enabled
> +#endif
> +
> +#define GPT_CR_SWR_RESET                1 // Self-clearing software reset
> +#define GPT_CR_SWR_NORESET              0 // Do not activate software reset
> +
> +#define GPT_CR_IM1_DISABLE              0 // Capture Disabled
> +#define GPT_CR_IM1_EDGE_RISE            1 // Capture on rising edge
> +#define GPT_CR_IM1_EDGE_FALL            2 // Capture on falling edge
> +#define GPT_CR_IM1_EDGE_BOTH            3 // Capture on both edges
> +
> +#define GPT_CR_IM2_DISABLE              0 // Capture Disabled
> +#define GPT_CR_IM2_EDGE_RISE            1 // Capture on rising edge
> +#define GPT_CR_IM2_EDGE_FALL            2 // Capture on falling edge
> +#define GPT_CR_IM2_EDGE_BOTH            3 // Capture on both edges
> +
> +#define GPT_CR_OM1_DISABLE              0 // Compare generates no response
> +#define GPT_CR_OM1_TOGGLE               1 // Compare toggles output pin
> +#define GPT_CR_OM1_CLEAR                2 // Compare clears output pin
> +#define GPT_CR_OM1_SET                  3 // Compare sets output pin
> +#define GPT_CR_OM1_PULSE                4 // Compare event generates a
> +                                          //   single count duration pulse
> +                                          //   on output pin
> +
> +#define GPT_CR_OM2_DISABLE              0 // Compare generates no response
> +#define GPT_CR_OM2_TOGGLE               1 // Compare toggles output pin
> +#define GPT_CR_OM2_CLEAR                2 // Compare clears output pin
> +#define GPT_CR_OM2_SET                  3 // Compare sets output pin
> +#define GPT_CR_OM2_PULSE                4 // Compare event generates a
> +                                          //   single count duration pulse
> +                                          //   on output pin
> +
> +#define GPT_CR_OM3_DISABLE              0 // Compare generates no response
> +#define GPT_CR_OM3_TOGGLE               1 // Compare toggles output pin
> +#define GPT_CR_OM3_CLEAR                2 // Compare clears output pin
> +#define GPT_CR_OM3_SET                  3 // Compare sets output pin
> +#define GPT_CR_OM3_PULSE                4 // Compare event generates a
> +                                          //   single count duration pulse
> +                                          //   on output pin
> +
> +#define GPT_CR_FO1_FORCE                1 // Force pin action programmed
> +                                          //   for output compare 1 pin.
> +                                          //   Pin is self-negating.
> +#define GPT_CR_FO1_NOFORCE              0 // Do not force pin
> +
> +#define GPT_CR_FO2_FORCE                1 // Force pin action programmed
> +                                          //   for output compare 1 pin
> +                                          //   Pin is self-negating.
> +#define GPT_CR_FO2_NOFORCE              0 // Do not force pin
> +
> +#define GPT_CR_FO3_FORCE                1 // Force pin action programmed
> +                                          //   for output compare 1 pin
> +                                          //   Pin is self-negating.
> +#define GPT_CR_FO3_NOFORCE              0 // Do not force pin
> +
> +// GPTSR
> +#define GPT_SR_OF1_STATUS_CLEAR         1 // Output compare 1 status clear
> +#define GPT_SR_OF2_STATUS_CLEAR         1 // Output compare 2 status clear
> +#define GPT_SR_OF3_STATUS_CLEAR         1 // Output compare 3 status clear
> +#define GPT_SR_IF1_STATUS_CLEAR         1 // Input capture 1 status clear
> +#define GPT_SR_IF2_STATUS_CLEAR         1 // Input capture 2 status clear
> +#define GPT_SR_ROV_STATUS_CLEAR         1 // Rollover status clear
> +
> +// GPTIR
> +#define GPT_IR_OF1IE_INT_ENABLE         1 // Output compare 1 int enabled
> +#define GPT_IR_OF1IE_INT_DISABLE        0 // Output compare 1 int disabled
> +
> +#define GPT_IR_OF2IE_INT_ENABLE         1 // Output compare 2 int enabled
> +#define GPT_IR_OF2IE_INT_DISABLE        0 // Output compare 2 int disabled
> +
> +#define GPT_IR_OF3IE_INT_ENABLE         1 // Output compare 3 int enabled
> +#define GPT_IR_OF3IE_INT_DISABLE        0 // Output compare 3 int disabled
> +
> +#define GPT_IR_IF1IE_INT_ENABLE         1 // Input capture 1 int enabled
> +#define GPT_IR_IF1IE_INT_DISABLE        0 // Input capture 1 int disabled
> +
> +#define GPT_IR_IF2IE_INT_ENABLE         1 // Input capture 2 int enabled
> +#define GPT_IR_IF2IE_INT_DISABLE        0 // Input capture 2 int disabled
> +
> +#define GPT_IR_ROVIE_INT_ENABLE         1 // Rollover int enabled
> +#define GPT_IR_ROVIE_INT_DISABLE        0 // Rollover int disabled
> +
> +#endif // __COMMON_GPT_H
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support
  2018-11-01 18:05   ` Leif Lindholm
@ 2018-11-29  0:55     ` Chris Co
  0 siblings, 0 replies; 75+ messages in thread
From: Chris Co @ 2018-11-29  0:55 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Leif,

> -----Original Message-----
> From: Leif Lindholm <leif.lindholm@linaro.org>
> Sent: Thursday, November 1, 2018 11:05 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display
> library support
> 
> On Fri, Sep 21, 2018 at 08:25:58AM +0000, Chris Co wrote:
> > This adds support for processing EDID data on NXP i.MX platforms.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > ---
> >  Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h                    | 114
> +++++++++++++++
> >  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c   | 152
> ++++++++++++++++++++
> >  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf |
> > 31 ++++
> >  3 files changed, 297 insertions(+)
> >
> > diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
> > b/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
> > new file mode 100644
> > index 000000000000..70ef8d0af97f
> > --- /dev/null
> > +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
> > @@ -0,0 +1,114 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C06e5c1f1adef43f79f9008d6402494f7%7C72f988bf86
> f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636766923203571004&amp;sdata=6GJ
> qphnDZ
> > +gT%2FGOiEeSSnPeTRGiRn%2B9CB%2Fi4A0ilq3MA%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#ifndef __IMX_DISPLAY_H__
> > +#define __IMX_DISPLAY_H__
> > +
> > +#define EDID_MIN_SIZE       128
> > +#define EDID_I2C_ADDRESS    0x50
> 
> Are all of these #defines and functions called only from within iMX platform
> code?
> 
These defines and functions are called by iMX platform and silicon (iMX6Pkg) code. Should I prefix these defines with "IMX_" and function names with "Imx"?

I made changes to address the rest of the feedback.

Chris

> > +
> > +// The first DTD is the preferred timing, refer to 3.1 VESA EDID spec.
> > +#define EDID_DTD_1_OFFSET   0x36
> > +#define EDID_DTD_2_OFFSET   0x48
> > +#define EDID_DTD_3_OFFSET   0x5A
> > +#define EDID_DTD_4_OFFSET   0x6C
> > +
> > +typedef enum {
> > +  PIXEL_FORMAT_ARGB32,
> > +  PIXEL_FORMAT_BGRA32,
> > +} PIXEL_FORMAT;
> > +
> > +typedef struct _DISPLAY_TIMING {
> > +  UINT32 PixelClock;
> > +  UINT32 HActive;
> > +  UINT32 HBlank;
> > +  UINT32 VActive;
> > +  UINT32 VBlank;
> > +  UINT32 HSync;
> > +  UINT32 VSync;
> > +  UINT32 HSyncOffset;
> > +  UINT32 VSyncOffset;
> > +  UINT32 HImageSize;
> > +  UINT32 VImageSize;
> > +  UINT32 HBorder;
> > +  UINT32 VBorder;
> > +  UINT32 EdidFlags;
> > +  UINT32 Flags;
> > +  UINT32 PixelRepetition;
> > +  UINT32 Bpp;
> > +  PIXEL_FORMAT PixelFormat;
> > +} DISPLAY_TIMING, *PDISPLAY_TIMING, DTD;
> > +
> > +typedef struct _DETAILED_TIMING_DESCRIPTOR {
> > +  UINT8 PixelClock[2];
> > +  UINT8 HActive;
> > +  UINT8 HBlank;
> > +  UINT8 HActiveBlank;
> > +  UINT8 VActive;
> > +  UINT8 VBlank;
> > +  UINT8 VActiveBlank;
> > +  UINT8 HSyncOffset;
> > +  UINT8 HSyncWidth;
> > +  UINT8 VSyncOffsetWidth;
> > +  UINT8 HVOffsetWidth;
> > +  UINT8 HImageSize;
> > +  UINT8 VImageSize;
> > +  UINT8 HVImageSize;
> > +  UINT8 HBorder;
> > +  UINT8 VBorder;
> > +  UINT8 EdidFlags;
> > +} DETAILED_TIMING_DESCRIPTOR, *PDETAILED_TIMING_DESCRIPTOR;
> > +
> > +/**
> > +  Convert detailed timing descriptor to display timing format
> > +
> > +  @param[in]    DTDPtr            Pointer to detailed timing descriptor.
> > +  @param[out]   DisplayTimingPtr  Pointer to display timing structure.
> > +
> > +  @retval   EFI_SUCCESS   Detailed timing descriptor data was converted.
> > +
> > +**/
> > +EFI_STATUS
> > +ConvertDTDToDisplayTiming (
> > +  IN DETAILED_TIMING_DESCRIPTOR   *DTDPtr,
> > +  OUT DISPLAY_TIMING              *DisplayTimingPtr
> > +  );
> > +
> > +/**
> > +  Debug dump of Display Timing structure
> > +
> > +  @param[in]    DisplayTimingNamePtr  Name of display timing structure.
> > +  @param[in]    DisplayTimingPtr      Pointer to display timing structure.
> > +**/
> > +VOID
> > +PrintDisplayTiming (
> > +  IN CHAR8            *DisplayTimingNamePtr,
> > +  IN DISPLAY_TIMING   *DisplayTimingPtr
> > +  );
> > +
> > +/**
> > +  Check if EDID is valid
> > +
> > +  @param[in]    EdidDataPtr  Pointer to EDID data.
> > +
> > +  @retval   EFI_SUCCESS             EDID data is a valid EDID.
> > +  @retval   EFI_INVALID_PARAMETER   EDID data is invalid.
> > +
> > +**/
> > +EFI_STATUS
> > +ValidateEdidData (
> > +  IN UINT8 *EdidDataPtr
> > +  );
> > +
> > +#endif // __IMX_DISPLAY_H__
> > diff --git
> > a/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
> > b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
> > new file mode 100644
> > index 000000000000..9e90ece96260
> > --- /dev/null
> > +++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
> > @@ -0,0 +1,152 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C06e5c1f1adef43f79f9008d6402494f7%7C72f988bf86
> f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636766923203571004&amp;sdata=6GJ
> qphnDZ
> > +gT%2FGOiEeSSnPeTRGiRn%2B9CB%2Fi4A0ilq3MA%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#include <Uefi.h>
> > +
> > +#include <Library/DebugLib.h>
> > +
> > +#include <iMXDisplay.h>
> > +
> > +/**
> > +  Convert detailed timing descriptor to display timing format
> > +
> > +  @param[in]    DTDPtr            Pointer to detailed timing descriptor.
> > +  @param[out]   DisplayTimingPtr  Pointer to display timing structure.
> > +
> > +  @retval   EFI_SUCCESS   Detailed timing descriptor data was converted.
> > +
> > +**/
> > +EFI_STATUS
> > +ConvertDTDToDisplayTiming (
> > +  IN DETAILED_TIMING_DESCRIPTOR   *DTDPtr,
> > +  OUT DISPLAY_TIMING              *DisplayTimingPtr
> > +  )
> > +{
> > +  UINT32  edidPixelClock;
> 
> e -> E.
> 
> > +
> > +  DEBUG ((DEBUG_INFO, "++ConvertDTDToDisplayTiming()\r\n"));
> 
> Please use %a and __FUNCTION__ instead of hard-coding function name.
> 
> > +  // Refer to 3.10.2 VESA EDID spec
> > +  edidPixelClock = (DTDPtr->PixelClock[0] | (DTDPtr->PixelClock[1] <<
> > + 8));  DisplayTimingPtr->PixelClock = edidPixelClock * 10000;
> > + DisplayTimingPtr->HActive = (DTDPtr->HActiveBlank & 0xF0);
> > + DisplayTimingPtr->HActive = (DisplayTimingPtr->HActive << 4) |
> > + DTDPtr->HActive;  DisplayTimingPtr->HBlank = (DTDPtr->HActiveBlank &
> > + 0x0F);  DisplayTimingPtr->HBlank = (DisplayTimingPtr->HBlank << 8) |
> > + DTDPtr->HBlank;  DisplayTimingPtr->VActive = (DTDPtr->VActiveBlank &
> > + 0xF0);  DisplayTimingPtr->VActive = (DisplayTimingPtr->VActive << 4)
> > + | DTDPtr->VActive;  DisplayTimingPtr->VBlank = (DTDPtr->VActiveBlank
> > + & 0x0F);  DisplayTimingPtr->VBlank = (DisplayTimingPtr->VBlank << 8)
> > + | DTDPtr->VBlank;  DisplayTimingPtr->HSyncOffset =
> > + (DTDPtr->HVOffsetWidth & 0xC0);  DisplayTimingPtr->HSyncOffset =
> (DisplayTimingPtr->HSyncOffset << 2) |
> > +                                  DTDPtr->HSyncOffset;
> > + DisplayTimingPtr->VSyncOffset = (DTDPtr->HVOffsetWidth & 0x0C);
> > + DisplayTimingPtr->VSyncOffset = (DisplayTimingPtr->VSyncOffset << 2) |
> > +                                  ((DTDPtr->VSyncOffsetWidth & 0xF0)
> > + >> 4);  DisplayTimingPtr->HSync = (DTDPtr->HVOffsetWidth & 0x30);
> > + DisplayTimingPtr->HSync = (DisplayTimingPtr->HSync << 4) |
> > + DTDPtr->HSyncWidth;  DisplayTimingPtr->VSync =
> > + (DTDPtr->HVOffsetWidth & 0x03);  DisplayTimingPtr->VSync =
> (DisplayTimingPtr->VSync << 4) |
> > +                            (DTDPtr->VSyncOffsetWidth & 0x0F);
> > + DisplayTimingPtr->HImageSize = ((DTDPtr->HVImageSize & 0xF0) << 4) |
> > +                                 DTDPtr->HImageSize;
> > + DisplayTimingPtr->VImageSize = ((DTDPtr->HVImageSize & 0x0F) << 8) |
> > +                                 DTDPtr->VImageSize;
> 
> A lot of these above transforms are a fairly unreadable, but maybe they need
> to be?
> 
> > +  DisplayTimingPtr->HBorder = DTDPtr->HBorder;
> > + DisplayTimingPtr->VBorder = DTDPtr->VBorder;
> > + DisplayTimingPtr->EdidFlags = DTDPtr->EdidFlags;
> > + DisplayTimingPtr->Flags = 0;
> 
> A #define for that 0?
> 
> > +
> > +  DEBUG ((DEBUG_INFO, "--ConvertDTDToDisplayTiming()=ok\r\n"));
> 
> __FUNCTION__
> 
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Debug dump of Display Timing structure
> > +
> > +  @param[in]    DisplayTimingNamePtr  Name of display timing structure.
> > +  @param[in]    DisplayTimingPtr      Pointer to display timing structure.
> > +**/
> > +VOID
> > +PrintDisplayTiming (
> > +  IN CHAR8            *DisplayTimingNamePtr,
> > +  IN DISPLAY_TIMING   *DisplayTimingPtr
> > +  )
> > +{
> > +  DEBUG ((DEBUG_INFO, "**********************\n"));
> > +  DEBUG ((DEBUG_INFO, "%a\n", DisplayTimingNamePtr));
> > +  DEBUG ((DEBUG_INFO, "**********************\n"));
> > +  DEBUG ((DEBUG_INFO, "PixelClock %d\n",
> > +DisplayTimingPtr->PixelClock));
> > +  DEBUG ((DEBUG_INFO, "HActive %d\n", DisplayTimingPtr->HActive));
> > +  DEBUG ((DEBUG_INFO, "HBlank %d\n", DisplayTimingPtr->HBlank));
> > +  DEBUG ((DEBUG_INFO, "VActive %d\n", DisplayTimingPtr->VActive));
> > +  DEBUG ((DEBUG_INFO, "VBlank %d\n", DisplayTimingPtr->VBlank));
> > +  DEBUG ((DEBUG_INFO, "HSync %d\n", DisplayTimingPtr->HSync));
> > +  DEBUG ((DEBUG_INFO, "VSync %d\n", DisplayTimingPtr->VSync));
> > +  DEBUG ((DEBUG_INFO, "HSyncOffset %d\n",
> > +DisplayTimingPtr->HSyncOffset));
> > +  DEBUG ((DEBUG_INFO, "VSyncOffset %d\n",
> > +DisplayTimingPtr->VSyncOffset));
> > +  DEBUG ((DEBUG_INFO, "HBorder %d\n", DisplayTimingPtr->HBorder));
> > +  DEBUG ((DEBUG_INFO, "VBorder %d\n", DisplayTimingPtr->VBorder));
> > +  DEBUG ((DEBUG_INFO, "EdidFlags %d\n",
> > +DisplayTimingPtr->EdidFlags));
> > +  DEBUG ((DEBUG_INFO, "Flags %d\n", DisplayTimingPtr->Flags));
> > +  DEBUG ((DEBUG_INFO, "PixelRepetition %d\n",
> > +DisplayTimingPtr->PixelRepetition));
> > +  DEBUG ((DEBUG_INFO, "BPP %d\n", DisplayTimingPtr->Bpp));
> > +  DEBUG ((DEBUG_INFO, "PixelFormat %d\n",
> > +DisplayTimingPtr->PixelFormat));
> > +  DEBUG ((DEBUG_INFO, "**********************\n")); }
> > +
> > +/**
> > +  Check if EDID is valid
> > +
> > +  @param[in]    EdidDataPtr  Pointer to EDID data.
> > +
> > +  @retval   EFI_SUCCESS             EDID data is a valid EDID.
> > +  @retval   EFI_INVALID_PARAMETER   EDID data is invalid.
> > +
> > +**/
> > +EFI_STATUS
> > +ValidateEdidData (
> > +  IN UINT8 *EdidDataPtr
> > +  )
> > +{
> > +  UINT8   Checksum;
> > +  UINT8   Index;
> > +
> > +  DEBUG ((DEBUG_INFO, "++ValidateEdidData()\r\n"));
> 
> __FUNCTION__
> 
> > +
> > +  if (EdidDataPtr[0] != 0x00 ||
> > +      EdidDataPtr[1] != 0xFF ||
> > +      EdidDataPtr[2] != 0xFF ||
> > +      EdidDataPtr[3] != 0xFF ||
> > +      EdidDataPtr[4] != 0xFF ||
> > +      EdidDataPtr[5] != 0xFF ||
> > +      EdidDataPtr[6] != 0xFF ||
> > +      EdidDataPtr[7] != 0x00) {
> > +    DEBUG ((DEBUG_ERROR, "Invalid EDID header\n"));
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  // Validate EDID checksum
> > +  Checksum = 0;
> > +  for (Index = 0; Index < EDID_MIN_SIZE; Index++) {
> > +    Checksum += EdidDataPtr[Index];
> > +  }
> > +
> > +  if (Checksum != 0) {
> > +    DEBUG ((DEBUG_ERROR, "Invalid EDID checksum\n"));
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  DEBUG ((DEBUG_INFO, "--ValidateEdidData()=ok\r\n"));
> 
> __FUNCTION__
> 
> /
>     Leif
> 
> > +  return EFI_SUCCESS;
> > +}
> > diff --git
> > a/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
> > b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
> > new file mode 100644
> > index 000000000000..bd77d4159639
> > --- /dev/null
> > +++ b/Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.i
> > +++ nf
> > @@ -0,0 +1,31 @@
> > +## @file
> > +#
> > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +#
> > +#  This program and the accompanying materials #  are licensed and
> > +made available under the terms and conditions of the BSD License #
> > +which accompanies this distribution.  The full text of the license
> > +may be found at #
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C06e5c1f1adef43f79f9008d6402494f7%7C72f988bf86
> f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636766923203581009&amp;sdata=s3Y
> tp2LL8
> > +T9AkKX6X%2FK2QCn3%2FXgj5wqjS%2BIE9EBYwzk%3D&amp;reserved=0
> > +#
> > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> EITHER EXPRESS OR IMPLIED.
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x0001001A
> > +  BASE_NAME                      = iMXDisplayLib
> > +  FILE_GUID                      = C0408490-F09B-4CFA-9A2F-5159F2705323
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = iMXDisplayLib
> > +
> > +[Packages]
> > +  EmbeddedPkg/EmbeddedPkg.dec
> > +  MdePkg/MdePkg.dec
> > +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> > +
> > +[LibraryClasses]
> > +
> > +[Sources.common]
> > +  iMXDisplayLib.c
> > --
> > 2.16.2.gvfs.1.33.gf5370f1
> >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-11-01 18:20   ` Leif Lindholm
@ 2018-12-01  0:22     ` Chris Co
  2018-12-03  9:42       ` Leif Lindholm
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-12-01  0:22 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Leif,

> -----Original Message-----
> From: Leif Lindholm <leif.lindholm@linaro.org>
> Sent: Thursday, November 1, 2018 11:20 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-
> specific i.MX packages to use
> 
> On Fri, Sep 21, 2018 at 08:26:00AM +0000, Chris Co wrote:
> > This adds common headers for other NXP i.MX SoC packages.
> > More specifically, this adds i.MX-generic GPIO, IoMux, and Platform
> > definitions.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > ---
> >  Silicon/NXP/iMXPlatformPkg/Include/Platform.h | 67 ++++++++++++++
> > Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h  | 92
> > ++++++++++++++++++++  Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h |
> > 24 +++++
> >  3 files changed, 183 insertions(+)
> >
> > diff --git a/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
> > b/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
> > new file mode 100644
> > index 000000000000..8a1e828f68ea
> > --- /dev/null
> > +++ b/Silicon/NXP/iMXPlatformPkg/Include/Platform.h
> > @@ -0,0 +1,67 @@
> > +/** @file
> > +*
> > +*  i.MX Platform specific defines for constructing ACPI tables
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C53adf4afe364416fab0c08d64026b170%7C72f988bf8
> 6f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636766932265064004&amp;sdata=lEf
> %2Bq2l
> > +nuxJ3cw%2BL91rhCTJ2e3jzWZfvgZZY8cyHswY%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#ifndef _PLATFORM_IMX_H_
> > +#define _PLATFORM_IMX_H_
> > +
> > +#include <IndustryStandard/Acpi50.h>
> > +
> > +#define EFI_ACPI_OEM_ID               {'M','C','R','S','F','T'} // OEMID 6 bytes
> > +#define EFI_ACPI_VENDOR_ID            SIGNATURE_32('N','X','P','I')
> > +#define EFI_ACPI_CSRT_REVISION        0x00000005
> > +#define EFI_ACPI_5_0_CSRT_REVISION    0x00000000
> > +
> > +// Resource Descriptor Types
> > +#define EFI_ACPI_CSRT_RD_TYPE_INTERRUPT 1 #define
> > +EFI_ACPI_CSRT_RD_TYPE_TIMER 2 #define EFI_ACPI_CSRT_RD_TYPE_DMA 3
> > +#define EFI_ACPI_CSRT_RD_TYPE_CACHE 4
> > +
> > +// Resource Descriptor Subtypes
> > +#define EFI_ACPI_CSRT_RD_SUBTYPE_INTERRUPT_LINES 0 #define
> > +EFI_ACPI_CSRT_RD_SUBTYPE_INTERRUPT_CONTROLLER 1 #define
> > +EFI_ACPI_CSRT_RD_SUBTYPE_TIMER 0 #define
> > +EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CHANNEL 0 #define
> > +EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CONTROLLER 1 #define
> > +EFI_ACPI_CSRT_RD_SUBTYPE_CACHE 0
> 
> If using EFI_ACPI prefix, these #defines really should be in edk2 MdePkg. And
> CSRT itself is, so that might not be a bad idea.
> 
> > +
> > +#pragma pack(push, 1)
> 
> I don't see this #pragma making any difference to the structs below, can it be
> dropped?
> 

The pragma pack is defensive. Without it, we rely on the compiler packing structures by default and this may not happen on 64 bit compiles.

I have addressed the remaining feedback and will resubmit with v2.

Thanks,
Chris

> > +//-------------------------------------------------------------------
> > +----- // CSRT Resource Group header 24 bytes long
> > +//-------------------------------------------------------------------
> > +-----
> > +typedef struct {
> > +  UINT32 Length;
> > +  UINT32 VendorID;
> > +  UINT32 SubVendorId;
> > +  UINT16 DeviceId;
> > +  UINT16 SubdeviceId;
> > +  UINT16 Revision;
> > +  UINT16 Reserved;
> > +  UINT32 SharedInfoLength;
> > +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER;
> > +
> > +//-------------------------------------------------------------------
> > +----- // CSRT Resource Descriptor 12 bytes total
> > +//-------------------------------------------------------------------
> > +-----
> > +typedef struct {
> > +  UINT32 Length;
> > +  UINT16 ResourceType;
> > +  UINT16 ResourceSubType;
> > +  UINT32 UID;
> > +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER;
> > +#pragma pack (pop)
> > +
> > +#endif // !_PLATFORM_IMX_H_
> > diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
> > b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
> > new file mode 100644
> > index 000000000000..dce01f789058
> > --- /dev/null
> > +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
> > @@ -0,0 +1,92 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C53adf4afe364416fab0c08d64026b170%7C72f988bf8
> 6f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636766932265064004&amp;sdata=lEf
> %2Bq2l
> > +nuxJ3cw%2BL91rhCTJ2e3jzWZfvgZZY8cyHswY%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#ifndef _IMX_GPIO_H_
> > +#define _IMX_GPIO_H_
> > +
> > +#include <Library/PcdLib.h>
> > +
> > +typedef enum {
> > +  IMX_GPIO_LOW = 0,
> > +  IMX_GPIO_HIGH = 1
> > +} IMX_GPIO_VALUE;
> > +
> > +typedef enum {
> > +  IMX_GPIO_DIR_INPUT,
> > +  IMX_GPIO_DIR_OUTPUT
> > +} IMX_GPIO_DIR;
> > +
> > +typedef enum {
> > +  IMX_GPIO_BANK1 = 1,
> > +  IMX_GPIO_BANK2,
> > +  IMX_GPIO_BANK3,
> > +  IMX_GPIO_BANK4,
> > +  IMX_GPIO_BANK5,
> > +  IMX_GPIO_BANK6,
> > +  IMX_GPIO_BANK7,
> > +} IMX_GPIO_BANK;
> > +
> > +#pragma pack(push, 1)
> 
> I don't see what effect this is supposed to have, can it be dropped?
> 
> > +
> > +#define GPIO_RESERVED_SIZE \
> > +    ((FixedPcdGet32(PcdGpioBankMemoryRange) / 4) - 8)
> > +
> > +typedef struct {
> > +  UINT32 DR;                            // 0x00 GPIO data register (GPIO1_DR)
> > +  UINT32 GDIR;                          // 0x04 GPIO direction register (GPIO1_GDIR)
> > +  UINT32 PSR;                           // 0x08 GPIO pad status register (GPIO1_PSR)
> > +  UINT32 ICR1;                          // 0x0C GPIO interrupt configuration register1
> (GPIO1_ICR1)
> > +  UINT32 ICR2;                          // 0x10 GPIO interrupt configuration register2
> (GPIO1_ICR2)
> > +  UINT32 IMR;                           // 0x14 GPIO interrupt mask register
> (GPIO1_IMR)
> > +  UINT32 ISR;                           // 0x18 GPIO interrupt status register
> (GPIO1_ISR)
> > +  UINT32 EDGE_SEL;                      // 0x1C GPIO edge select register
> (GPIO1_EDGE_SEL)
> > +  UINT32 reserved[GPIO_RESERVED_SIZE]; } IMX_GPIO_BANK_REGISTERS;
> > +
> > +#pragma pack(pop)
> > +
> > +typedef struct {
> > +  IMX_GPIO_BANK_REGISTERS Banks[7];
> > +} IMX_GPIO_REGISTERS;
> > +
> > +/**
> > +    Set the specified GPIO to the specified direction.
> > +**/
> > +VOID
> > +ImxGpioDirection (
> > +  IMX_GPIO_BANK Bank,
> > +  UINT32 IoNumber,
> > +  IMX_GPIO_DIR Direction
> > +  );
> > +
> > +/**
> > +    Write a value to a GPIO pin.
> > +**/
> > +VOID
> > +ImxGpioWrite (
> > +  IMX_GPIO_BANK Bank,
> > +  UINT32 IoNumber,
> > +  IMX_GPIO_VALUE Value
> > +  );
> > +
> > +/**
> > +    Read a GPIO pin input value.
> > +**/
> > +IMX_GPIO_VALUE
> > +ImxGpioRead (
> > +  IMX_GPIO_BANK Bank,
> > +  UINT32 IoNumber
> > +  );
> > +
> > +#endif
> > diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
> > b/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
> > new file mode 100644
> > index 000000000000..7696af57d7ea
> > --- /dev/null
> > +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
> > @@ -0,0 +1,24 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C53adf4afe364416fab0c08d64026b170%7C72f988bf8
> 6f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636766932265064004&amp;sdata=lEf
> %2Bq2l
> > +nuxJ3cw%2BL91rhCTJ2e3jzWZfvgZZY8cyHswY%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#ifndef _IMX_IO_MUX_H_
> > +#define _IMX_IO_MUX_H_
> > +
> > +#define _IMX_PAD(CtlRegOffset, MuxRegOffset) \
> 
> No _ for macros. Why does one pad an iMX? Can the name be more
> descriptive? (applies to next few macros too).
> 
> /
>     Leif
> 
> > +  ((((CtlRegOffset) & 0xffff) << 16) | ((MuxRegOffset) & 0xffff))
> > +
> > +#define _IMX_PAD_CTL_OFFSET(ImxPadVal) ((ImxPadVal) >> 16) #define
> > +_IMX_PAD_MUX_OFFSET(ImxPadVal) ((ImxPadVal) & 0xffff)
> > +
> > +#endif // _IMX_IO_MUX_H_
> > --
> > 2.16.2.gvfs.1.33.gf5370f1
> >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-12-01  0:22     ` Chris Co
@ 2018-12-03  9:42       ` Leif Lindholm
  2018-12-04  1:44         ` Chris Co
  0 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-12-03  9:42 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Sat, Dec 01, 2018 at 12:22:17AM +0000, Chris Co wrote:
> > If using EFI_ACPI prefix, these #defines really should be in edk2 MdePkg. And
> > CSRT itself is, so that might not be a bad idea.
> > 
> > > +
> > > +#pragma pack(push, 1)
> > 
> > I don't see this #pragma making any difference to the structs below, can it be
> > dropped?
> 
> The pragma pack is defensive. Without it, we rely on the compiler
> packing structures by default and this may not happen on 64 bit
> compiles.

I understand that is what the pragma does. My comment was because all
of the variables in the below structs are naturally aligned.
The reason I dislike its use when effectively a no-op, is that it
makes it look like it it isn't a no-op.

If it covers a larger set of structs, some of which require the packed
attribute I'm OK with that. But I'm not a fan of adding it "just in
case" without contemplating the statement's (lack of) effect.

Regards,

Leif

> I have addressed the remaining feedback and will resubmit with v2.
> 
> Thanks,
> Chris
> 
> > > +//-------------------------------------------------------------------
> > > +----- // CSRT Resource Group header 24 bytes long
> > > +//-------------------------------------------------------------------
> > > +-----
> > > +typedef struct {
> > > +  UINT32 Length;
> > > +  UINT32 VendorID;
> > > +  UINT32 SubVendorId;
> > > +  UINT16 DeviceId;
> > > +  UINT16 SubdeviceId;
> > > +  UINT16 Revision;
> > > +  UINT16 Reserved;
> > > +  UINT32 SharedInfoLength;
> > > +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER;
> > > +
> > > +//-------------------------------------------------------------------
> > > +----- // CSRT Resource Descriptor 12 bytes total
> > > +//-------------------------------------------------------------------
> > > +-----
> > > +typedef struct {
> > > +  UINT32 Length;
> > > +  UINT16 ResourceType;
> > > +  UINT16 ResourceSubType;
> > > +  UINT32 UID;
> > > +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER;
> > > +#pragma pack (pop)


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library
  2018-11-08 18:00   ` Leif Lindholm
@ 2018-12-04  1:41     ` Chris Co
  0 siblings, 0 replies; 75+ messages in thread
From: Chris Co @ 2018-12-04  1:41 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Leif,

> -----Original Message-----
> From: Leif Lindholm <leif.lindholm@linaro.org>
> Sent: Thursday, November 8, 2018 10:00 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX
> library
> 
> On Fri, Sep 21, 2018 at 08:26:03AM +0000, Chris Co wrote:
> > This adds support for initializing and manipulating the I/O Pads on
> > NXP i.MX6 SoCs.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > ---
> >  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c      | 151
> ++++++++++++++++++++
> >  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf |  41
> > ++++++
> >  2 files changed, 192 insertions(+)
> >
> > diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
> > b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
> > new file mode 100644
> > index 000000000000..7c0c7b54a2fe
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
> > @@ -0,0 +1,151 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C416f86ef76c04f1cac6408d645a40e53%7C72f988b
> f86f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636772968261577670&amp;sdata=
> vkaVmLhCg
> > +d0X80xpryCJ4kHPUTUtcv6W6MFg3a082nk%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#include <PiDxe.h>
> > +
> > +#include <Library/DebugLib.h>
> > +#include <Library/IoLib.h>
> > +
> > +#include <iMX6.h>
> > +#include <iMX6IoMux.h>
> > +
> > +// Muxing functions
> > +VOID
> > +ImxPadConfig (
> > +  IN  IMX_PAD     Pad,
> > +  IN  IMX_PADCFG  PadConfig
> 
> I'll get back to reviewing patch 11 at some point, but that one is hard going. So
> I'll point out here what I'll mention then:
> Please just use UINT64. Typedefs are useful to reduce pointless repetition for
> structs, but here it just obscures what is programatically going on.
> 

I'm thinking to rework the PADCFG to actually use structs properly instead of custom-packing with macros. It seems the previous dev was very macro happy and I am the opposite...
The remaining feedback makes sense. Will address for v2.

Thanks,
Chris

> > +  )
> > +{
> > +  // Configure Mux Control
> > +  MmioWrite32 (
> > +    IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad),
> > +    _IMX_PADCFG_MUX_CTL (PadConfig));
> 
> It would be worth adding macros or simple accessor functions for these - there's
> a lot of text in this file that has no semantic value and needs to be manually
> filtered when reading.
> 
> I.e. IomuxWrite32 (Pad, ...), IomuxRead32 (Pad), ...
> 
> Other comment really belonging to 11:
> Please drop leading _ from macros. Such macros are intended for internal use
> by toolchains.
> 
> > +
> > +  // Configure Select Input Control
> > +  if (_IMX_PADCFG_SEL_INP (PadConfig) != 0) {
> > +    DEBUG ((DEBUG_INFO, "Setting INPUT_SELECT %x value %x\n",
> > +            _IMX_SEL_INP_REGISTER (_IMX_PADCFG_SEL_INP (PadConfig)),
> > +            _IMX_SEL_INP_VALUE (_IMX_PADCFG_SEL_INP (PadConfig))));
> > +
> > +    MmioWrite32 (
> > +      _IMX_SEL_INP_REGISTER (_IMX_PADCFG_SEL_INP (PadConfig)),
> > +      _IMX_SEL_INP_VALUE (_IMX_PADCFG_SEL_INP (PadConfig)));  }
> > +
> > +  // Configure Pad Control
> > +  MmioWrite32 (
> > +    IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad),
> > +    _IMX_PADCFG_PAD_CTL (PadConfig)); }
> > +
> > +VOID
> > +ImxPadDumpConfig (
> > +  IN  CHAR8 *SignalFriendlyName,
> > +  IN  IMX_PAD Pad
> > +  )
> > +{
> > +  IMX_IOMUXC_MUX_CTL  MuxCtl;
> > +  IMX_IOMUXC_PAD_CTL  PadCtl;
> > +
> > +  MuxCtl.AsUint32 = MmioRead32 (
> > +                      IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad));
> > +
> > +  DEBUG ((
> > +           DEBUG_INIT,
> > +           "- %a MUX_CTL(0x%p)=0x%08x: MUX_MODE:%d SION:%d | ",
> > +           SignalFriendlyName,
> > +           IMX_IOMUXC_BASE + _IMX_PAD_MUX_OFFSET (Pad),
> > +           MuxCtl.AsUint32,
> > +           MuxCtl.Fields.MUX_MODE,
> > +           MuxCtl.Fields.SION));
> > +
> > +  PadCtl.AsUint32 = MmioRead32 (
> > +                      IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad));
> > +
> > +  DEBUG ((
> > +           DEBUG_INIT,
> > +           "PAD_CTL(0x%p)=0x%08x: SRE:%d DSE:%d SPEED:%d ODE:%d PKE:%d
> PUE:%d PUS:%d HYS:%d\n",
> > +           IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (Pad),
> > +           PadCtl.AsUint32,
> > +           PadCtl.Fields.SRE,
> > +           PadCtl.Fields.DSE,
> > +           PadCtl.Fields.SPEED,
> > +           PadCtl.Fields.ODE,
> > +           PadCtl.Fields.PKE,
> > +           PadCtl.Fields.PUE,
> > +           PadCtl.Fields.PUS,
> > +           PadCtl.Fields.HYS));
> > +}
> > +
> > +// GPIO functions
> > +VOID
> > +ImxGpioDirection (
> > +  IN  IMX_GPIO_BANK   Bank,
> > +  IN  UINT32          IoNumber,
> > +  IN  IMX_GPIO_DIR    Direction
> > +  )
> > +{
> > +  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
> 
> What makes this pointer volatile?
> (Hint: drop it, it does nothing useful here.)
> 
> That initial 'g', following EDK2 naming rules, says that this is a variable in the
> global namespace, exported from this module. It should be GpioRegisters.
> 
> > +
> > +  ASSERT (IoNumber < 32);
> 
> That 32 needs a #define.
> 
> > +
> > +  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;  if
> > + (Direction == IMX_GPIO_DIR_INPUT) {
> > +    MmioAnd32 ((UINTN) &gpioRegisters->Banks[Bank - 1].GDIR, ~ (1 <<
> > + IoNumber));
> 
> This 'Bank - 1' stuff looks a bit scary. Why aren't we passing the inde to use? A
> comment block before the function could explain what the inputs are meant to
> be.
> 
> > +  } else {
> > +    MmioOr32 ((UINTN) &gpioRegisters->Banks[Bank - 1].GDIR, 1 <<
> > + IoNumber);
> 
> Since we're doing 1 << IoNumber on all possible routes through this function,
> could we assign it to a temporary variable? And we're doing it to the same bank.
> 
> If I wrote this function, I'd probably do something more like
> 
>   UINTN DirectionRegister;
>   UINT32 Pin;
>   DirectionRegister = (UINTN)&((IMX_GPIO_REGISTERS *)IMX_GPIO_BASE)-
> >Banks[Bank - 1].GDIR;
>   Pin = 1 << IoNumber;
> 
>   if (Direction == IMX_GPIO_DIR_INPUT) {
>     MmioAnd32 (DirectionRegister, ~Pin);
>   } else {
>     MmioOr32 (DirectionRegister, Pin);
>   }
> 
> > +  }
> > +}
> > +
> > +VOID
> > +ImxGpioWrite (
> > +  IN  IMX_GPIO_BANK   Bank,
> > +  IN  UINT32          IoNumber,
> > +  IN  IMX_GPIO_VALUE  Value
> > +  )
> > +{
> > +  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
> > +
> > +  ASSERT (IoNumber < 32);
> > +
> > +  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;  if (Value ==
> > + IMX_GPIO_LOW) {
> > +    MmioAnd32 ((UINTN) &gpioRegisters->Banks[Bank - 1].DR, ~ (1 <<
> > + IoNumber));  } else {
> > +    MmioOr32 ((UINTN) &gpioRegisters->Banks[Bank - 1].DR, 1 <<
> > + IoNumber);  }
> 
> All the same comments as above.
> 
> > +}
> > +
> > +IMX_GPIO_VALUE
> > +ImxGpioRead (
> > +  IN  IMX_GPIO_BANK   Bank,
> > +  IN  UINT32          IoNumber
> > +  )
> > +{
> > +  volatile IMX_GPIO_REGISTERS   *gpioRegisters;
> > +  UINT32                        Mask;
> > +  UINT32                        Psr;
> > +
> > +  ASSERT (IoNumber < 32);
> > +
> > +  gpioRegisters = (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE;  Mask = (1 <<
> > + IoNumber);  Psr = MmioRead32 ((UINTN) &gpioRegisters->Banks[Bank -
> > + 1].PSR);
> > +
> > +  if (Psr & Mask) {
> > +    return IMX_GPIO_HIGH;
> > +  } else {
> > +    return IMX_GPIO_LOW;
> > +  }
> 
> Some of the same comments as above :)
> (I.e., those that apply.)
> 
> /
>     Leif
> 
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
> > b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
> > new file mode 100644
> > index 000000000000..84bbbee5c1db
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
> > @@ -0,0 +1,41 @@
> > +## @file
> > +#
> > +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +#
> > +#  This program and the accompanying materials #  are licensed and
> > +made available under the terms and conditions of the BSD License #
> > +which accompanies this distribution.  The full text of the license
> > +may be found at #
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C416f86ef76c04f1cac6408d645a40e53%7C72f988b
> f86f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636772968261577670&amp;sdata=
> vkaVmLhCg
> > +d0X80xpryCJ4kHPUTUtcv6W6MFg3a082nk%3D&amp;reserved=0
> > +#
> > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> EITHER EXPRESS OR IMPLIED.
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x0001001A
> > +  BASE_NAME                      = iMX6IoMuxLib
> > +  FILE_GUID                      = FA41BEF0-0666-4C07-9EC3-47F61C36EDBE
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = iMX6IoMuxLib
> > +
> > +[Packages]
> > +  ArmPkg/ArmPkg.dec
> > +  EmbeddedPkg/EmbeddedPkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +  MdePkg/MdePkg.dec
> > +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> > +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseMemoryLib
> > +  DebugLib
> > +  IoLib
> > +  TimerLib
> > +
> > +[Sources.common]
> > +  iMX6IoMux.c
> > +
> > + [FixedPcd]
> > +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> > --
> > 2.16.2.gvfs.1.33.gf5370f1
> >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-12-03  9:42       ` Leif Lindholm
@ 2018-12-04  1:44         ` Chris Co
  2018-12-04  9:33           ` Ard Biesheuvel
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-12-04  1:44 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney



> -----Original Message-----
> From: Leif Lindholm <leif.lindholm@linaro.org>
> Sent: Monday, December 3, 2018 1:43 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-
> specific i.MX packages to use
> 
> On Sat, Dec 01, 2018 at 12:22:17AM +0000, Chris Co wrote:
> > > If using EFI_ACPI prefix, these #defines really should be in edk2
> > > MdePkg. And CSRT itself is, so that might not be a bad idea.
> > >
> > > > +
> > > > +#pragma pack(push, 1)
> > >
> > > I don't see this #pragma making any difference to the structs below,
> > > can it be dropped?
> >
> > The pragma pack is defensive. Without it, we rely on the compiler
> > packing structures by default and this may not happen on 64 bit
> > compiles.
> 
> I understand that is what the pragma does. My comment was because all of the
> variables in the below structs are naturally aligned.
> The reason I dislike its use when effectively a no-op, is that it makes it look like it
> it isn't a no-op.
> 
> If it covers a larger set of structs, some of which require the packed attribute I'm
> OK with that. But I'm not a fan of adding it "just in case" without contemplating
> the statement's (lack of) effect.
> 
> Regards,
> 
> Leif
> 

Makes sense. I am checking to make sure this pragma wasn't included due to some observed compiler behavior on our end, since this header is also used on our ARM64 work.
Will remove it once confirmed it is safe.

Thanks,
Chris

> > I have addressed the remaining feedback and will resubmit with v2.
> >
> > Thanks,
> > Chris
> >
> > > > +//---------------------------------------------------------------
> > > > +----
> > > > +----- // CSRT Resource Group header 24 bytes long
> > > > +//---------------------------------------------------------------
> > > > +----
> > > > +-----
> > > > +typedef struct {
> > > > +  UINT32 Length;
> > > > +  UINT32 VendorID;
> > > > +  UINT32 SubVendorId;
> > > > +  UINT16 DeviceId;
> > > > +  UINT16 SubdeviceId;
> > > > +  UINT16 Revision;
> > > > +  UINT16 Reserved;
> > > > +  UINT32 SharedInfoLength;
> > > > +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER;
> > > > +
> > > > +//---------------------------------------------------------------
> > > > +----
> > > > +----- // CSRT Resource Descriptor 12 bytes total
> > > > +//---------------------------------------------------------------
> > > > +----
> > > > +-----
> > > > +typedef struct {
> > > > +  UINT32 Length;
> > > > +  UINT16 ResourceType;
> > > > +  UINT16 ResourceSubType;
> > > > +  UINT32 UID;
> > > > +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER;
> > > > +#pragma pack (pop)


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
  2018-11-08 18:14   ` Leif Lindholm
@ 2018-12-04  2:06     ` Chris Co
  2018-12-04 12:58       ` Leif Lindholm
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2018-12-04  2:06 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Leif,

> -----Original Message-----
> From: Leif Lindholm <leif.lindholm@linaro.org>
> Sent: Thursday, November 8, 2018 10:14 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and
> EPIT timer headers
> 
> On Fri, Sep 21, 2018 at 08:26:05AM +0000, Chris Co wrote:
> > This adds the definitions for the NXP i.MX6 General Purpose Timer and
> > the Enhanced Periodic Interrupt Timer modules.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > ---
> >  Silicon/NXP/iMX6Pkg/Include/common_epit.h | 118 +++++++++
> > Silicon/NXP/iMX6Pkg/Include/common_gpt.h  | 271
> ++++++++++++++++++++
> >  2 files changed, 389 insertions(+)
> >
> > diff --git a/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> > b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> > new file mode 100644
> > index 000000000000..485d6ccbc51e
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> 
> Rename to CamelCase?
> 

Can do. Would you prefer the iMX prefix to be in CamelCase too? (i.e. Imx6Epit.h)

> > @@ -0,0 +1,118 @@
> > +/** @file
> > +*
> > +*  Provides definitions for the EPIT (Enhanced Periodic Interrupt
> > +Timer)
> > +*  module that are common to Freescale SoCs.
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*  Copyright (c) 2004-2010, Freescale Semiconductor, Inc. All Rights
> Reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C5da90dbbf4b5452a4c8e08d645a605cc%7C72f988
> bf86f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636772976703090578&amp;sdata=
> g3OOywqu7
> > +VDuq39F3PVs8SaXZVbA7h77F7riMUXb0lE%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#ifndef __COMMON_EPIT_H
> > +#define __COMMON_EPIT_H
> 
> COMMON is a bit too common. Can we at least stick an IMX on the front?
> 
> This is really also a problem for all of the structs and #defines below as well.
> 
> > +
> > +typedef struct {
> > +  UINT32 CR;
> > +  UINT32 SR;
> > +  UINT32 LR;
> > +  UINT32 CMPR;
> > +  UINT32 CNT;
> > +} CSP_EPIT_REG, *PCSP_EPIT_REG;
> 
> I'm really not a fan of typedef pointers. Please drop the *PSCP one.
> 
> > +
> > +#define EPIT_CR_OFFSET          0x0000
> > +#define EPIT_SR_OFFSET          0x0004
> > +#define EPIT_LR_OFFSET          0x0008
> > +#define EPIT_CMPR_OFFSET        0x000C
> > +#define EPIT_CNR_OFFSET         0x0010
> > +
> > +#define EPIT_CR_EN_LSH          0
> 
> What is LSH?
> 
> > +#define EPIT_CR_ENMOD_LSH       1
> > +#define EPIT_CR_OCIEN_LSH       2
> > +#define EPIT_CR_RLD_LSH         3
> > +#define EPIT_CR_PRESCALAR_LSH   4
> > +#define EPIT_CR_SWR_LSH         16
> > +#define EPIT_CR_IOVW_LSH        17
> > +#define EPIT_CR_DBGEN_LSH       18
> > +#define EPIT_CR_WAITEN_LSH      19
> > +#define EPIT_CR_DOZEN_LSH       20
> > +#define EPIT_CR_STOPEN_LSH      21
> > +#define EPIT_CR_OM_LSH          22
> > +#define EPIT_CR_CLKSRC_LSH      24
> > +
> > +#define EPIT_SR_OCIF_LSH        0
> > +#define EPIT_LR_LOAD_LSH        0
> > +#define EPIT_CMPR_COMPARE_LSH   0
> > +#define EPIT_CNT_COUNT_LSH      0
> > +
> > +#define EPIT_CR_EN_WID          1
> 
> What is WID?
> 

LSH is the number of bits to left shift to get to the specified bitfield in the register. WID is the length of the specified bitfield.
I don't like this register access pattern at all. Will define structs of the registers instead...

Thanks,
Chris

> > +#define EPIT_CR_ENMOD_WID       1
> > +#define EPIT_CR_OCIEN_WID       2
> > +#define EPIT_CR_RLD_WID         1
> > +#define EPIT_CR_PRESCALAR_WID   12
> > +#define EPIT_CR_SWR_WID         1
> > +#define EPIT_CR_IOVW_WID        1
> > +#define EPIT_CR_DBGEN_WID       1
> > +#define EPIT_CR_WAITEN_WID      1
> > +#define EPIT_CR_DOZEN_WID       1
> > +#define EPIT_CR_STOPEN_WID      1
> > +#define EPIT_CR_OM_WID          2
> > +#define EPIT_CR_CLKSRC_WID      2
> > +
> > +#define EPIT_SR_OCIF_WID        1
> > +#define EPIT_LR_LOAD_WID        32
> > +#define EPIT_CMPR_COMPARE_WID   32
> > +#define EPIT_CNT_COUNT_WID      32
> > +
> > +// CR
> > +#define EPIT_CR_EN_DISABLE          0
> > +#define EPIT_CR_EN_ENABLE           1
> > +
> > +#define EPIT_CR_ENMOD_RESUME        0
> > +#define EPIT_CR_ENMOD_LOAD          1
> > +
> > +#define EPIT_CR_OCIEN_DISABLE       0
> > +#define EPIT_CR_OCIEN_ENABLE        1
> > +
> > +#define EPIT_CR_RLD_ROLLOVER        0
> > +#define EPIT_CR_RLD_RELOAD          1
> > +
> > +#define EPIT_CR_SWR_NORESET         0
> > +#define EPIT_CR_SWR_RESET           1
> > +
> > +#define EPIT_CR_IOVW_NOOVR          0
> > +#define EPIT_CR_IOVW_OVR            1
> > +
> > +#define EPIT_CR_DBGEN_INACTIVE      0
> > +#define EPIT_CR_DBGEN_ACTIVE        1
> > +
> > +#define EPIT_CR_WAITEN_DISABLE      0
> > +#define EPIT_CR_WAITEN_ENABLE       1
> > +
> > +#define EPIT_CR_DOZEN_DISABLE       0
> > +#define EPIT_CR_DOZEN_ENABLE        1
> > +
> > +#define EPIT_CR_STOPEN_DISABLE      0
> > +#define EPIT_CR_STOPEN_ENABLE       1
> > +
> > +#define EPIT_CR_OM_DICONNECT        0
> > +#define EPIT_CR_OM_TOGGLE           1
> > +#define EPIT_CR_OM_CLEAR            2
> > +#define EPIT_CR_OM_SET              3
> > +
> > +#define EPIT_CR_CLKSRC_OFF          0
> > +#define EPIT_CR_CLKSRC_IPGCLK       1
> > +#define EPIT_CR_CLKSRC_HIGHFREQ     2   // High freq is sourcing from
> PERCLK
> > +#define EPIT_CR_CLKSRC_CKIL         3
> > +
> > +// CNT
> > +#define EPIT_CNT_COUNT_MAX          0xFFFFFFFF
> 
> MAX_UINT32?
> 
> > +
> > +#endif // __COMMON_EPIT_H
> > diff --git a/Silicon/NXP/iMX6Pkg/Include/common_gpt.h
> > b/Silicon/NXP/iMX6Pkg/Include/common_gpt.h
> > new file mode 100644
> > index 000000000000..7fdfc25d819f
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/Include/common_gpt.h
> 
> Rename to CamelCase.
> 
> > @@ -0,0 +1,271 @@
> > +/** @file
> > +*
> > +*  Provides definitions for the GPT (General Purpose Timer) module
> > +*  that are common to Freescale SoCs.
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*  Copyright (c) 2004-2010, Freescale Semiconductor, Inc. All Rights
> Reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of
> > +the BSD License
> > +*  which accompanies this distribution.  The full text of the license
> > +may be found at
> > +*
> > +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopens
> > +ource.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher
> >
> +.Co%40microsoft.com%7C5da90dbbf4b5452a4c8e08d645a605cc%7C72f988
> bf86f1
> >
> +41af91ab2d7cd011db47%7C1%7C0%7C636772976703090578&amp;sdata=
> g3OOywqu7
> > +VDuq39F3PVs8SaXZVbA7h77F7riMUXb0lE%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#ifndef __COMMON_GPT_H
> > +#define __COMMON_GPT_H
> 
> +IMX.
> 
> > +
> > +typedef struct {
> > +  UINT32 CR;
> > +  UINT32 PR;
> > +  UINT32 SR;
> > +  UINT32 IR;
> > +  UINT32 OCR1;
> > +  UINT32 OCR2;
> > +  UINT32 OCR3;
> > +  UINT32 ICR1;
> > +  UINT32 ICR2;
> > +  UINT32 CNT;
> > +} CSP_GPT_REGS, *PCSP_GPT_REGS;
> 
> Drop *PCSP.
> 
> > +
> > +#define GPT_CR_OFFSET          0x0000
> > +#define GPT_PR_OFFSET          0x0004
> > +#define GPT_SR_OFFSET          0x0008
> > +#define GPT_IR_OFFSET          0x000C
> > +#define GPT_OCR1_OFFSET        0x0010
> > +#define GPT_OCR2_OFFSET        0x0014
> > +#define GPT_OCR3_OFFSET        0x0018
> > +#define GPT_ICR1_OFFSET        0x001C
> > +#define GPT_ICR2_OFFSET        0x0020
> > +#define GPT_CNT_OFFSET         0x0024
> > +
> > +
> > +#define GPT_CR_EN_LSH          0
> 
> What is LSH?
> 
> > +#define GPT_CR_ENMOD_LSH       1
> > +#define GPT_CR_DBGEN_LSH       2
> > +#define GPT_CR_WAITEN_LSH      3
> > +#define GPT_CR_STOPEN_LSH      5
> > +#define GPT_CR_CLKSRC_LSH      6
> > +#define GPT_CR_FRR_LSH         9
> > +#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
> > +#define GPT_CR_EN_24M_LSH      10
> > +#endif
> > +#define GPT_CR_SWR_LSH         15
> > +#define GPT_CR_IM1_LSH         16
> > +#define GPT_CR_IM2_LSH         18
> > +#define GPT_CR_OM1_LSH         20
> > +#define GPT_CR_OM2_LSH         23
> > +#define GPT_CR_OM3_LSH         26
> > +#define GPT_CR_FO1_LSH         29
> > +#define GPT_CR_FO2_LSH         30
> > +#define GPT_CR_FO3_LSH         31
> > +
> > +#define GPT_PR_PRESCALER_LSH   0
> > +
> > +#define GPT_SR_OF1_LSH         0
> > +#define GPT_SR_OF2_LSH         1
> > +#define GPT_SR_OF3_LSH         2
> > +#define GPT_SR_IF1_LSH         3
> > +#define GPT_SR_IF2_LSH         4
> > +#define GPT_SR_ROV_LSH         5
> > +
> > +#define GPT_IR_OF1IE_LSH       0
> > +#define GPT_IR_OF2IE_LSH       1
> > +#define GPT_IR_OF3IE_LSH       2
> > +#define GPT_IR_IF1IE_LSH       3
> > +#define GPT_IR_IF2IE_LSH       4
> > +#define GPT_IR_ROVIE_LSH       5
> > +
> > +#define GPT_OCR1_COMP_LSH      0
> > +#define GPT_OCR2_COMP_LSH      0
> > +#define GPT_OCR3_COMP_LSH      0
> > +#define GPT_ICR1_CAPT_LSH      0
> > +#define GPT_ICR2_CAPT_LSH      0
> > +#define GPT_CNT_COUNT_LSH      0
> > +
> > +#define GPT_CR_EN_WID          1
> 
> What is WID?
> 
> /
>     Leif
> 
> > +#define GPT_CR_ENMOD_WID       1
> > +#define GPT_CR_DBGEN_WID       1
> > +#define GPT_CR_WAITEN_WID      1
> > +#define GPT_CR_STOPEN_WID      1
> > +#define GPT_CR_CLKSRC_WID      3
> > +#define GPT_CR_FRR_WID         1
> > +#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
> > +#define GPT_CR_EN_24M_WID      1
> > +#endif
> > +#define GPT_CR_SWR_WID         1
> > +#define GPT_CR_IM1_WID         2
> > +#define GPT_CR_IM2_WID         2
> > +#define GPT_CR_OM1_WID         3
> > +#define GPT_CR_OM2_WID         3
> > +#define GPT_CR_OM3_WID         3
> > +#define GPT_CR_FO1_WID         1
> > +#define GPT_CR_FO2_WID         1
> > +#define GPT_CR_FO3_WID         1
> > +
> > +#define GPT_PR_PRESCALER_WID   12
> > +
> > +#define GPT_SR_OF1_WID         1
> > +#define GPT_SR_OF2_WID         1
> > +#define GPT_SR_OF3_WID         1
> > +#define GPT_SR_IF1_WID         1
> > +#define GPT_SR_IF2_WID         1
> > +#define GPT_SR_ROV_WID         1
> > +
> > +#define GPT_IR_OF1IE_WID       1
> > +#define GPT_IR_OF2IE_WID       1
> > +#define GPT_IR_OF3IE_WID       1
> > +#define GPT_IR_IF1IE_WID       1
> > +#define GPT_IR_IF2IE_WID       1
> > +#define GPT_IR_ROVIE_WID       1
> > +
> > +#define GPT_OCR1_COMP_WID      32
> > +#define GPT_OCR2_COMP_WID      32
> > +#define GPT_OCR3_COMP_WID      32
> > +#define GPT_ICR1_CAPT_WID      32
> > +#define GPT_ICR2_CAPT_WID      32
> > +#define GPT_CNT_COUNT_WID      32
> > +
> > +
> > +//-------------------------------------------------------------------
> > +-----------
> > +// REGISTER BIT WRITE VALUES
> > +//-------------------------------------------------------------------
> > +-----------
> > +
> > +// GPTCR
> > +#define GPT_CR_EN_ENABLE                1 // GPT enabled
> > +#define GPT_CR_EN_DISABLE               0 // GPT disabled
> > +
> > +#define GPT_CR_ENMOD_RESET              1 // GPT counter reset to
> > +                                          //   0 when disabled
> > +#define GPT_CR_ENMOD_RETAIN             0 // GPT counter retains
> > +                                          //   value when disabled
> > +
> > +#define GPT_CR_DBGEN_ENABLE             1 // GPT enabled in debug mode
> > +#define GPT_CR_DBGEN_DISABLE            0 // GPT disabled in debug mode
> > +
> > +#define GPT_CR_WAITEN_ENABLE            1 // GPT enabled in wait mode
> > +#define GPT_CR_WAITEN_DISABLE           0 // GPT disabled in wait mode
> > +
> > +#define GPT_CR_STOPEN_ENABLE            1 // GPT enabled in stopdoze mode
> > +#define GPT_CR_STOPEN_DISABLE           0 // GPT disabled in stopoze mode
> > +
> > +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> > +#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
> > +#define GPT_CR_CLKSRC_IPGCLK            1 // ipg_clk is the clock source
> > +#define GPT_CR_CLKSRC_HIGHFREQ          2 // ipg_clk_highfreq
> > +#define GPT_CR_CLKSRC_EXTCLK            3 // ipp_gpt_clkin (external clock
> > +// from pad) is the clock source
> > +#define GPT_CR_CLKSRC_CLK32K            4 // ipg_clk_32k is clock source
> > +#define GPT_CR_CLKSRC_CLK8M             5 // crystal oscillator divided by 8 is
> clock source
> > +#define GPT_CR_CLKSRC_CLK24M            7 // crystal oscillator (24 Mhz) is
> clock source
> > +#elif defined(CPU_IMX6SDL)
> > +#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
> > +#define GPT_CR_CLKSRC_IPGCLK            1 // Peripheral Clock
> > +#define GPT_CR_CLKSRC_HIGHFREQ          2 // High Frequency Reference
> Clock
> > +#define GPT_CR_CLKSRC_EXTCLK            3 // External Clock (CLKIN)
> > +#define GPT_CR_CLKSRC_LOWFREQ           4 // Low Frequency Reference
> Clock
> > +#define GPT_CR_CLKSRC_CLK24M            5 // Crystal oscillator as Reference
> Clock
> > +#elif defined(CPU_IMX6SX)
> > +#define GPT_CR_CLKSRC_NOCLK             0 // No clock to GPT
> > +#define GPT_CR_CLKSRC_PERIPHCLK         1 // Peripheral Clock
> > +#define GPT_CR_CLKSRC_HIGHFREQ          2 // High Frequency Reference
> Clock
> > +#define GPT_CR_CLKSRC_EXTCLK            3 // External Clock (CLKIN)
> > +#define GPT_CR_CLKSRC_LOWFREQ           4 // Low Frequency Reference
> Clock
> > +#define GPT_CR_CLKSRC_CLK24M            5 // Crystal oscillator as Reference
> Clock
> > +#else
> > +#error CPU Preprocessor Flag Not Defined #endif
> > +
> > +#define GPT_CR_FRR_FREERUN              1 // Freerun mode (counter
> > +                                          //   continues after compare)
> > +#define GPT_CR_FRR_RESTART              0 // Restart mode (counter set
> > +                                          //   to zero after compare)
> > +#if defined(CPU_IMX6SX) || defined(CPU_IMX6SDL)
> > +#define GPT_CR_EN_24M_DISABLE           0  // 24M clock disabled
> > +#define GPT_CR_EN_24M_ENABLE            1  // 24M clock enabled
> > +#endif
> > +
> > +#define GPT_CR_SWR_RESET                1 // Self-clearing software reset
> > +#define GPT_CR_SWR_NORESET              0 // Do not activate software reset
> > +
> > +#define GPT_CR_IM1_DISABLE              0 // Capture Disabled
> > +#define GPT_CR_IM1_EDGE_RISE            1 // Capture on rising edge
> > +#define GPT_CR_IM1_EDGE_FALL            2 // Capture on falling edge
> > +#define GPT_CR_IM1_EDGE_BOTH            3 // Capture on both edges
> > +
> > +#define GPT_CR_IM2_DISABLE              0 // Capture Disabled
> > +#define GPT_CR_IM2_EDGE_RISE            1 // Capture on rising edge
> > +#define GPT_CR_IM2_EDGE_FALL            2 // Capture on falling edge
> > +#define GPT_CR_IM2_EDGE_BOTH            3 // Capture on both edges
> > +
> > +#define GPT_CR_OM1_DISABLE              0 // Compare generates no response
> > +#define GPT_CR_OM1_TOGGLE               1 // Compare toggles output pin
> > +#define GPT_CR_OM1_CLEAR                2 // Compare clears output pin
> > +#define GPT_CR_OM1_SET                  3 // Compare sets output pin
> > +#define GPT_CR_OM1_PULSE                4 // Compare event generates a
> > +                                          //   single count duration pulse
> > +                                          //   on output pin
> > +
> > +#define GPT_CR_OM2_DISABLE              0 // Compare generates no response
> > +#define GPT_CR_OM2_TOGGLE               1 // Compare toggles output pin
> > +#define GPT_CR_OM2_CLEAR                2 // Compare clears output pin
> > +#define GPT_CR_OM2_SET                  3 // Compare sets output pin
> > +#define GPT_CR_OM2_PULSE                4 // Compare event generates a
> > +                                          //   single count duration pulse
> > +                                          //   on output pin
> > +
> > +#define GPT_CR_OM3_DISABLE              0 // Compare generates no response
> > +#define GPT_CR_OM3_TOGGLE               1 // Compare toggles output pin
> > +#define GPT_CR_OM3_CLEAR                2 // Compare clears output pin
> > +#define GPT_CR_OM3_SET                  3 // Compare sets output pin
> > +#define GPT_CR_OM3_PULSE                4 // Compare event generates a
> > +                                          //   single count duration pulse
> > +                                          //   on output pin
> > +
> > +#define GPT_CR_FO1_FORCE                1 // Force pin action programmed
> > +                                          //   for output compare 1 pin.
> > +                                          //   Pin is self-negating.
> > +#define GPT_CR_FO1_NOFORCE              0 // Do not force pin
> > +
> > +#define GPT_CR_FO2_FORCE                1 // Force pin action programmed
> > +                                          //   for output compare 1 pin
> > +                                          //   Pin is self-negating.
> > +#define GPT_CR_FO2_NOFORCE              0 // Do not force pin
> > +
> > +#define GPT_CR_FO3_FORCE                1 // Force pin action programmed
> > +                                          //   for output compare 1 pin
> > +                                          //   Pin is self-negating.
> > +#define GPT_CR_FO3_NOFORCE              0 // Do not force pin
> > +
> > +// GPTSR
> > +#define GPT_SR_OF1_STATUS_CLEAR         1 // Output compare 1 status
> clear
> > +#define GPT_SR_OF2_STATUS_CLEAR         1 // Output compare 2 status
> clear
> > +#define GPT_SR_OF3_STATUS_CLEAR         1 // Output compare 3 status
> clear
> > +#define GPT_SR_IF1_STATUS_CLEAR         1 // Input capture 1 status clear
> > +#define GPT_SR_IF2_STATUS_CLEAR         1 // Input capture 2 status clear
> > +#define GPT_SR_ROV_STATUS_CLEAR         1 // Rollover status clear
> > +
> > +// GPTIR
> > +#define GPT_IR_OF1IE_INT_ENABLE         1 // Output compare 1 int enabled
> > +#define GPT_IR_OF1IE_INT_DISABLE        0 // Output compare 1 int disabled
> > +
> > +#define GPT_IR_OF2IE_INT_ENABLE         1 // Output compare 2 int enabled
> > +#define GPT_IR_OF2IE_INT_DISABLE        0 // Output compare 2 int disabled
> > +
> > +#define GPT_IR_OF3IE_INT_ENABLE         1 // Output compare 3 int enabled
> > +#define GPT_IR_OF3IE_INT_DISABLE        0 // Output compare 3 int disabled
> > +
> > +#define GPT_IR_IF1IE_INT_ENABLE         1 // Input capture 1 int enabled
> > +#define GPT_IR_IF1IE_INT_DISABLE        0 // Input capture 1 int disabled
> > +
> > +#define GPT_IR_IF2IE_INT_ENABLE         1 // Input capture 2 int enabled
> > +#define GPT_IR_IF2IE_INT_DISABLE        0 // Input capture 2 int disabled
> > +
> > +#define GPT_IR_ROVIE_INT_ENABLE         1 // Rollover int enabled
> > +#define GPT_IR_ROVIE_INT_DISABLE        0 // Rollover int disabled
> > +
> > +#endif // __COMMON_GPT_H
> > --
> > 2.16.2.gvfs.1.33.gf5370f1
> >


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-12-04  1:44         ` Chris Co
@ 2018-12-04  9:33           ` Ard Biesheuvel
  2018-12-04 12:22             ` Leif Lindholm
  0 siblings, 1 reply; 75+ messages in thread
From: Ard Biesheuvel @ 2018-12-04  9:33 UTC (permalink / raw)
  To: Chris Co; +Cc: Leif Lindholm, edk2-devel@lists.01.org, Michael D Kinney



> On 4 Dec 2018, at 02:44, Chris Co <Christopher.Co@microsoft.com> wrote:
> 
> 
> 
>> -----Original Message-----
>> From: Leif Lindholm <leif.lindholm@linaro.org>
>> Sent: Monday, December 3, 2018 1:43 AM
>> To: Chris Co <Christopher.Co@microsoft.com>
>> Cc: edk2-devel@lists.01.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
>> Michael D Kinney <michael.d.kinney@intel.com>
>> Subject: Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-
>> specific i.MX packages to use
>> 
>> On Sat, Dec 01, 2018 at 12:22:17AM +0000, Chris Co wrote:
>>>> If using EFI_ACPI prefix, these #defines really should be in edk2
>>>> MdePkg. And CSRT itself is, so that might not be a bad idea.
>>>> 
>>>>> +
>>>>> +#pragma pack(push, 1)
>>>> 
>>>> I don't see this #pragma making any difference to the structs below,
>>>> can it be dropped?
>>> 
>>> The pragma pack is defensive. Without it, we rely on the compiler
>>> packing structures by default and this may not happen on 64 bit
>>> compiles.
>> 
>> I understand that is what the pragma does. My comment was because all of the
>> variables in the below structs are naturally aligned.
>> The reason I dislike its use when effectively a no-op, is that it makes it look like it
>> it isn't a no-op.
>> 
>> If it covers a larger set of structs, some of which require the packed attribute I'm
>> OK with that. But I'm not a fan of adding it "just in case" without contemplating
>> the statement's (lack of) effect.
>> 
>> Regards,
>> 
>> Leif
>> 
> 
> Makes sense. I am checking to make sure this pragma wasn't included due to some observed compiler behavior on our end, since this header is also used on our ARM64 work.
> Will remove it once confirmed it is safe.


I’d prefer to keep the pragma. It doesn’t only remove padding, it also informs the compiler that the whole struct may appear at any unaligned offset. On 32 bit ARM, this means the compiler will refrain from using load/store double or load/store multiple to access the contents when dereferencing a pointer to such a struct, which would result in a crash otherwise.

> 
>>> I have addressed the remaining feedback and will resubmit with v2.
>>> 
>>> Thanks,
>>> Chris
>>> 
>>>>> +//---------------------------------------------------------------
>>>>> +----
>>>>> +----- // CSRT Resource Group header 24 bytes long
>>>>> +//---------------------------------------------------------------
>>>>> +----
>>>>> +-----
>>>>> +typedef struct {
>>>>> +  UINT32 Length;
>>>>> +  UINT32 VendorID;
>>>>> +  UINT32 SubVendorId;
>>>>> +  UINT16 DeviceId;
>>>>> +  UINT16 SubdeviceId;
>>>>> +  UINT16 Revision;
>>>>> +  UINT16 Reserved;
>>>>> +  UINT32 SharedInfoLength;
>>>>> +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER;
>>>>> +
>>>>> +//---------------------------------------------------------------
>>>>> +----
>>>>> +----- // CSRT Resource Descriptor 12 bytes total
>>>>> +//---------------------------------------------------------------
>>>>> +----
>>>>> +-----
>>>>> +typedef struct {
>>>>> +  UINT32 Length;
>>>>> +  UINT16 ResourceType;
>>>>> +  UINT16 ResourceSubType;
>>>>> +  UINT32 UID;
>>>>> +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER;
>>>>> +#pragma pack (pop)


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use
  2018-12-04  9:33           ` Ard Biesheuvel
@ 2018-12-04 12:22             ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-04 12:22 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: Chris Co, edk2-devel@lists.01.org, Michael D Kinney

On Tue, Dec 04, 2018 at 10:33:23AM +0100, Ard Biesheuvel wrote:
> >>>>> +#pragma pack(push, 1)
> >>>> 
> >>>> I don't see this #pragma making any difference to the structs below,
> >>>> can it be dropped?
> >>> 
> >>> The pragma pack is defensive. Without it, we rely on the compiler
> >>> packing structures by default and this may not happen on 64 bit
> >>> compiles.
> >> 
> >> I understand that is what the pragma does. My comment was because all of the
> >> variables in the below structs are naturally aligned.
> >> The reason I dislike its use when effectively a no-op, is that it makes it look like it
> >> it isn't a no-op.
> >> 
> >> If it covers a larger set of structs, some of which require the packed attribute I'm
> >> OK with that. But I'm not a fan of adding it "just in case" without contemplating
> >> the statement's (lack of) effect.
> >> 
> >> Regards,
> >> 
> >> Leif
> >> 
> > 
> > Makes sense. I am checking to make sure this pragma wasn't
> > included due to some observed compiler behavior on our end, since
> > this header is also used on our ARM64 work.
> > Will remove it once confirmed it is safe.
> 
> I’d prefer to keep the pragma. It doesn’t only remove padding, it
> also informs the compiler that the whole struct may appear at any
> unaligned offset.
> On 32 bit ARM, this means the compiler will
> refrain from using load/store double or load/store multiple to
> access the contents when dereferencing a pointer to such a struct,
> which would result in a crash otherwise.

OK, if it is a real concern that the structs themselves may appear
unaligned in memory, please ignore this feedback.

/
    Leif




^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
  2018-12-04  2:06     ` Chris Co
@ 2018-12-04 12:58       ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-04 12:58 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Tue, Dec 04, 2018 at 02:06:04AM +0000, Chris Co wrote:
> > > diff --git a/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> > > b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> > > new file mode 100644
> > > index 000000000000..485d6ccbc51e
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/Include/common_epit.h
> > 
> > Rename to CamelCase?
> 
> Can do. Would you prefer the iMX prefix to be in CamelCase too? (i.e. Imx6Epit.h)

I'm honestly not too fussed.

My preference (which contradicts the coding style, mind you) is to
keep names looking like they do in normal reading. So I would
aesthetically prefer the former, whereas the coding style says the
latter. You choose :)

/
    Leif


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 13/27] Silicon/NXP: Add support for iMX SDHC
  2018-09-21  8:26 ` [PATCH edk2-platforms 13/27] Silicon/NXP: Add support for iMX SDHC Chris Co
@ 2018-12-05 10:31   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-05 10:31 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:04AM +0000, Chris Co wrote:
> This adds support for using the SD host controller on
> NXP i.MX platforms.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c   | 1246 ++++++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h   |   81 ++
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf |   70 ++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h          |  277 +++++
>  4 files changed, 1674 insertions(+)
> 
> diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
> new file mode 100644
> index 000000000000..9fe0bc3792a9
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
> @@ -0,0 +1,1246 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/DmaLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/EmbeddedExternalDevice.h>
> +#include <Protocol/Sdhc.h>
> +
> +#include <iMXuSdhc.h>
> +#include <iMXGpio.h>
> +#include "SdhcDxe.h"
> +
> +VOID
> +DumpState (
> +  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
> +  )
> +{
> +  DEBUG_CODE_BEGIN ();
> +
> +  USDHC_REGISTERS         *Reg;

Reg->Registers. Alternatively, could just call it Controller.
The fact that they're registers is less interesting than whose
registers they are.

> +  USDHC_BLK_ATT_REG       BlkAtt;
> +  UINT32                  CmdArg;
> +  USDHC_CMD_XFR_TYP_REG   CmdXfrTyp;
> +  UINT32                  IntSignalEn;
> +  USDHC_INT_STATUS_REG    IntStatus;
> +  UINT32                  IntStatusEn;
> +  USDHC_MIX_CTRL_REG      MixCtrl;
> +  UINT32                  MmcBoot;
> +  USDHC_PRES_STATE_REG    PresState;
> +  USDHC_PROT_CTRL_REG     ProtCtrl;
> +  USDHC_WTMK_LVL_REG      WtmkLvl;
> +  UINT32                  VendSpec;
> +  UINT32                  VendSpec2;
> +
> +  Reg = SdhcCtx->RegistersBase;
> +  BlkAtt.AsUint32 = MmioRead32 ((UINTN)&Reg->BLK_ATT);
> +  CmdArg = MmioRead32 ((UINTN)&Reg->CMD_ARG);
> +  CmdXfrTyp.AsUint32 = MmioRead32 ((UINTN)&Reg->CMD_XFR_TYP);
> +  ProtCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->PROT_CTRL);
> +  WtmkLvl.AsUint32 = MmioRead32 ((UINTN)&Reg->WTMK_LVL);
> +  MixCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->MIX_CTRL);
> +  IntStatusEn = MmioRead32 ((UINTN)&Reg->INT_STATUS_EN);
> +  IntSignalEn = MmioRead32 ((UINTN)&Reg->INT_SIGNAL_EN);
> +  VendSpec = MmioRead32 ((UINTN)&Reg->VEND_SPEC);
> +  MmcBoot = MmioRead32 ((UINTN)&Reg->MMC_BOOT);
> +  VendSpec2 = MmioRead32 ((UINTN)&Reg->VEND_SPEC2);
> +  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +  PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +
> +  LOG_INFO (
> +    " - BLK_ATT\t:0x%08x BLKSIZE:0x%x BLKCNT:0x%08x",
> +    BlkAtt.AsUint32,
> +    BlkAtt.Fields.BLKSIZE,
> +    BlkAtt.Fields.BLKCNT);
> +
> +  LOG_INFO (" - CMD_ARG\t:0x%08x", CmdArg);
> +
> +  LOG_INFO (
> +    " - CMD_XFR_TYP\t:0x%08x RSPTYP:%d CCCEN:%d CICEN:%d DPSEL:%d CMDTYP:%d CMDINX:%d",
> +    CmdXfrTyp.AsUint32,
> +    CmdXfrTyp.Fields.RSPTYP,
> +    CmdXfrTyp.Fields.CCCEN,
> +    CmdXfrTyp.Fields.CICEN,
> +    CmdXfrTyp.Fields.DPSEL,
> +    CmdXfrTyp.Fields.CMDTYP,
> +    CmdXfrTyp.Fields.CMDINX);
> +
> +  LOG_INFO (
> +    " - PROT_CTRL\t:0x%08x DTW:%d D3CD:%d CDSS:%d EMODE:%d DMASEL:%d SABGREQ:%d BURST_LEN_EN:%d",
> +    ProtCtrl.AsUint32,
> +    ProtCtrl.Fields.DTW,
> +    ProtCtrl.Fields.D3CD,
> +    ProtCtrl.Fields.CDSS,
> +    ProtCtrl.Fields.EMODE,
> +    ProtCtrl.Fields.DMASEL,
> +    ProtCtrl.Fields.SABGREQ,
> +    ProtCtrl.Fields.BURST_LEN_EN);
> +
> +  LOG_INFO (
> +    " - WTMK_LVL\t:0x%08x RD_WML:%d RD_BRST_LEN:%d WR_WML:%d WR_BRST_LEN:%d",
> +    WtmkLvl.AsUint32,
> +    WtmkLvl.Fields.RD_WML,
> +    WtmkLvl.Fields.RD_BRST_LEN,
> +    WtmkLvl.Fields.WR_WML,
> +    WtmkLvl.Fields.WR_BRST_LEN);
> +
> +  LOG_INFO (
> +    " - MIX_CTRL\t:0x%08x DMAEN:%d BCEN:%d AC12EN:%d DTDSEL:%d MSBSEL:%d AC23EN:%d FBCLK_SEL:%d",
> +    MixCtrl.AsUint32,
> +    MixCtrl.Fields.DMAEN,
> +    MixCtrl.Fields.BCEN,
> +    MixCtrl.Fields.AC12EN,
> +    MixCtrl.Fields.DTDSEL,
> +    MixCtrl.Fields.MSBSEL,
> +    MixCtrl.Fields.AC23EN,
> +    MixCtrl.Fields.FBCLK_SEL);
> +
> +  LOG_INFO (" - INT_STATUS_EN\t:0x%08x", IntStatusEn);
> +  LOG_INFO (" - INT_SIGNAL_EN\t:0x%08x", IntSignalEn);
> +  LOG_INFO (" - VEND_SPEC\t:0x%08x", VendSpec);
> +  LOG_INFO (" - MMC_BOOT\t:0x%08x", MmcBoot);
> +  LOG_INFO (" - VEND_SPEC2\t:0x%08x", VendSpec2);
> +
> +  LOG_INFO (
> +    " - INT_STATUS\t:0x%08x CC:%d TC:%d BWR:%d BRR:%d CTOE:%d CCE:%d CEBE:%d CIE:%d DTOE:%d DCE:%d DEBE:%d",
> +    IntStatus.AsUint32,
> +    IntStatus.Fields.CC,
> +    IntStatus.Fields.TC,
> +    IntStatus.Fields.BWR,
> +    IntStatus.Fields.BRR,
> +    IntStatus.Fields.CTOE,
> +    IntStatus.Fields.CCE,
> +    IntStatus.Fields.CEBE,
> +    IntStatus.Fields.CIE,
> +    IntStatus.Fields.DTOE,
> +    IntStatus.Fields.DCE,
> +    IntStatus.Fields.DEBE);
> +
> +  LOG_INFO (
> +    " - PRES_STATE\t:0x%08x CIHB:%d CDIHB:%d DLA:%d WTA:%d RTA:%d BWEN:%d BREN:%d CINST:%d DLSL:0x%x",
> +    PresState.AsUint32,
> +    PresState.Fields.CIHB,
> +    PresState.Fields.CDIHB,
> +    PresState.Fields.DLA,
> +    PresState.Fields.WTA,
> +    PresState.Fields.RTA,
> +    PresState.Fields.BWEN,
> +    PresState.Fields.BREN,
> +    PresState.Fields.CINST,
> +    PresState.Fields.DLSL);
> +
> +  DEBUG_CODE_END ();
> +}
> +
> +EFI_STATUS
> +WaitForReadFifo (
> +  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
> +  )
> +{
> +  USDHC_REGISTERS       *Reg;
> +  USDHC_INT_STATUS_REG  IntStatus;
> +  UINT32                Retry;
> +
> +  Reg = SdhcCtx->RegistersBase;
> +  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +  Retry = USDHC_POLL_RETRY_COUNT;
> +
> +  while (!IntStatus.Fields.BRR &&
> +         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
> +         Retry) {
> +    --Retry;
> +    gBS->Stall (USDHC_POLL_WAIT_US);
> +    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +  }
> +
> +  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
> +    LOG_ERROR ("Error detected");
> +    DumpState (SdhcCtx);
> +    return EFI_DEVICE_ERROR;
> +  } else if (IntStatus.Fields.BRR) {
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32);
> +    return EFI_SUCCESS;
> +  } else {
> +    ASSERT (!Retry);
> +    LOG_ERROR ("Time-out waiting on read FIFO");
> +    DumpState (SdhcCtx);
> +    return EFI_TIMEOUT;
> +  }
> +}
> +
> +EFI_STATUS
> +WaitForWriteFifo (
> +  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
> +  )
> +{
> +  USDHC_REGISTERS       *Reg;
> +  USDHC_INT_STATUS_REG  IntStatus;
> +  UINT32                Retry;
> +
> +  Reg = SdhcCtx->RegistersBase;
> +  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS) ;
> +  Retry = USDHC_POLL_RETRY_COUNT;
> +
> +  while (!IntStatus.Fields.BWR &&
> +         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
> +         Retry) {
> +    --Retry;
> +    gBS->Stall (USDHC_POLL_WAIT_US);
> +    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +  }
> +
> +  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
> +    LOG_ERROR ("Error detected");
> +    DumpState (SdhcCtx);
> +    return EFI_DEVICE_ERROR;
> +  } else if (IntStatus.Fields.BWR) {
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32);
> +    return EFI_SUCCESS;
> +  } else {
> +    ASSERT (!Retry);
> +    LOG_ERROR ("Time-out waiting on write FIFO");
> +    DumpState (SdhcCtx);
> +    return EFI_TIMEOUT;
> +  }
> +}
> +
> +EFI_STATUS
> +WaitForCmdAndOrDataLine (
> +  IN USDHC_PRIVATE_CONTEXT *SdhcCtx,
> +  IN CONST SD_COMMAND *Cmd
> +  )
> +{
> +  USDHC_REGISTERS       *Reg;
> +  USDHC_INT_STATUS_REG  IntStatus;
> +  USDHC_PRES_STATE_REG  PresState;
> +  UINT32                Retry;
> +  BOOLEAN               WaitForDataLine;
> +
> +  // Waiting on the DATA lines is the default behavior if no CMD is specified
> +  if (Cmd == NULL) {
> +    WaitForDataLine = TRUE;
> +  } else {
> +    // Per datasheet, the SDHC can isssue CMD0, CMD12, CMD13 and CMD52
> +    // when the DATA lines are busy during a data transfer. Other commands
> +    // should wait on the DATA lines before issuing
> +    switch (Cmd->Index) {
> +    case 0:
> +    case 12:
> +    case 13:
> +    case 52:

Guessing these could be substituted for CMD0, CMD12, CMD13, CMD52?

> +      WaitForDataLine = FALSE;
> +      break;
> +    default:
> +      WaitForDataLine = TRUE;
> +    }
> +  }
> +
> +  Reg = SdhcCtx->RegistersBase;
> +  PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS) ;
> +  Retry = USDHC_POLL_RETRY_COUNT;
> +
> +  while (PresState.Fields.CIHB &&
> +         (!WaitForDataLine || PresState.Fields.CDIHB) &&
> +         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
> +         Retry) {
> +    gBS->Stall (USDHC_POLL_WAIT_US);
> +    --Retry;
> +    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +  }
> +
> +  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
> +    LOG_ERROR ("Error detected");
> +    DumpState (SdhcCtx);
> +    return EFI_DEVICE_ERROR;
> +  } else if (!(PresState.Fields.CIHB &&
> +             (!WaitForDataLine || PresState.Fields.CDIHB))) {
> +    return EFI_SUCCESS;
> +  } else {
> +    ASSERT (!Retry);
> +    LOG_ERROR ("Time-out waiting on CMD and/or DATA lines");
> +    DumpState (SdhcCtx);
> +    return EFI_TIMEOUT;
> +  }
> +}
> +
> +EFI_STATUS
> +WaitForCmdResponse (
> +  IN USDHC_PRIVATE_CONTEXT *SdhcCtx
> +  )
> +{
> +  USDHC_REGISTERS       *Reg;
> +  USDHC_INT_STATUS_REG  IntStatus;
> +  UINT32                Retry;
> +
> +  Reg = SdhcCtx->RegistersBase;
> +  IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS) ;
> +  Retry = USDHC_POLL_RETRY_COUNT;
> +
> +  // Wait for command to finish execution either with success or failure
> +  while (!IntStatus.Fields.CC &&
> +         !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) &&
> +         Retry) {
> +    gBS->Stall (USDHC_POLL_WAIT_US);
> +    --Retry;
> +    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +  }
> +
> +  if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) {
> +    LOG_ERROR ("Error detected");
> +    DumpState (SdhcCtx);
> +    return EFI_DEVICE_ERROR;
> +  } else if (IntStatus.Fields.CC) {
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32);
> +    return EFI_SUCCESS;
> +  } else {
> +    ASSERT (!Retry);
> +    LOG_ERROR ("Time-out waiting on command completion");
> +    DumpState (SdhcCtx);
> +    return EFI_TIMEOUT;
> +  }
> +}
> +
> +EFI_STATUS
> +SdhcSetBusWidth (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN SD_BUS_WIDTH BusWidth
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  USDHC_PROT_CTRL_REG     ProtCtrl;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +  Reg = SdhcCtx->RegistersBase;
> +  ProtCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->PROT_CTRL);
> +
> +  LOG_TRACE ("SdhcSetBusWidth(%d)", BusWidth);
> +
> +  switch (BusWidth) {
> +  case SdBusWidth1Bit:
> +    ProtCtrl.Fields.DTW = USDHC_PROT_CTRL_DTW_1BIT;
> +    break;
> +  case SdBusWidth4Bit:
> +    ProtCtrl.Fields.DTW = USDHC_PROT_CTRL_DTW_4BIT;
> +    break;
> +  case SdBusWidth8Bit:
> +    ProtCtrl.Fields.DTW = USDHC_PROT_CTRL_DTW_8BIT;
> +    break;
> +  default:
> +    LOG_ASSERT ("Invalid bus width");
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  MmioWrite32 ((UINTN)&Reg->PROT_CTRL, ProtCtrl.AsUint32);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SdhcSetClock (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN UINT32 TargetFreqHz
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  UINT32                  BestDivisor;
> +  UINT32                  BestPrescaler;
> +  UINT32                  Divisor;
> +  UINT32                  FreqDistance;
> +  UINT32                  MinFreqDistance;
> +  USDHC_MIX_CTRL_REG      MixCtrl;
> +  UINT32                  Prescaler;
> +  USDHC_PRES_STATE_REG    PresState;
> +  UINT32                  Retry;
> +  UINT32                  SdClk;
> +  USDHC_SYS_CTRL_REG      SysCtrl;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +  LOG_TRACE ("SdhcSetClock(%dHz)", TargetFreqHz);
> +
> +  Reg = SdhcCtx->RegistersBase;
> +  SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +
> +  // SdClk = (Base Clock) / (prescaler x divisor)
> +  MixCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->MIX_CTRL);
> +
> +  // Bruteforce to find the best prescaler and divisor that result
> +  // in SdClk less than or equal to the requested frequency
> +  //
> +  // Allowed |Base clock divided By
> +  // SDCLKFS |DDR_EN=0   |DDR_EN=1
> +  // 80h      256         512
> +  // 40h      128         256
> +  // 20h      64          128
> +  // 10h      32          64
> +  // 08h      16          32
> +  // 04h      8           16
> +  // 02h      4           8
> +  // 01h      2           4
> +  // 00h      1           2
> +  CONST UINT32 PRESCALER_MIN = (MixCtrl.Fields.DDR_EN ? 2 : 1);
> +  CONST UINT32 PRESCALER_MAX = (MixCtrl.Fields.DDR_EN ? 512 : 256);;
> +  CONST UINT32 DIVISOR_MIN = 1;
> +  CONST UINT32 DIVISOR_MAX = 16;
> +  MinFreqDistance = MAX_UINT32;
> +  BestPrescaler = 0;
> +  BestDivisor = 0;
> +
> +  //
> +  // Bruteforce to find the best prescaler and divisor that result
> +  // in SdClk less than or equal to the requested frequency
> +  //
> +  for (Prescaler = PRESCALER_MAX; Prescaler >= PRESCALER_MIN; Prescaler /= 2) {
> +    for (Divisor = DIVISOR_MIN; Divisor <= DIVISOR_MAX; ++Divisor) {
> +      SdClk = USDHC_BASE_CLOCK_FREQ_HZ / (Prescaler * Divisor);
> +
> +      //
> +      // We are not willing to choose clocks higher than the target one
> +      // to avoid exceeding device limits
> +      //
> +      if (SdClk > TargetFreqHz) {
> +        continue;
> +      } else if (SdClk == TargetFreqHz) {
> +        BestPrescaler = Prescaler;
> +        BestDivisor = Divisor;
> +        break;
> +      } else {
> +        FreqDistance = TargetFreqHz - SdClk;
> +        if (FreqDistance < MinFreqDistance) {
> +          MinFreqDistance = FreqDistance;
> +          BestPrescaler = Prescaler;
> +          BestDivisor = Divisor;
> +        }
> +      }
> +    }
> +  }
> +
> +  // Wait for clock to become stable before any modifications
> +  PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +  Retry = USDHC_POLL_RETRY_COUNT;
> +
> +  while (!PresState.Fields.SDSTB &&
> +         Retry) {
> +    gBS->Stall (USDHC_POLL_WAIT_US);
> +    --Retry;
> +    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +  }
> +
> +  if (!PresState.Fields.SDSTB) {
> +    ASSERT (!Retry);
> +    LOG_ERROR ("Time-out waiting on SD clock to stabilize");
> +    DumpState (SdhcCtx);
> +    return EFI_TIMEOUT;
> +  }
> +
> +  SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +  SysCtrl.Fields.SDCLKFS = BestPrescaler / (MixCtrl.Fields.DDR_EN ? 4 : 2);
> +  SysCtrl.Fields.DVS = BestDivisor - 1;
> +
> +  MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
> +
> +  SdClk = USDHC_BASE_CLOCK_FREQ_HZ / (BestPrescaler * BestDivisor);
> +
> +  LOG_TRACE (
> +    "Current SdClk:%dHz SDCLKFS:0x%x DVS:0x%x",
> +    SdClk,
> +    (UINT32)SysCtrl.Fields.SDCLKFS,
> +    (UINT32)SysCtrl.Fields.DVS);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +BOOLEAN
> +SdhcIsCardPresent (
> +  IN EFI_SDHC_PROTOCOL *This
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  IMX_GPIO_VALUE          CardDetectLevel;
> +  BOOLEAN                 IsCardPresent;
> +  USDHC_PRES_STATE_REG    PresState;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +  if (SdhcCtx->CardDetectSignal == USDHC_SIGNAL_INTERNAL_PIN) {
> +    Reg = SdhcCtx->RegistersBase;
> +    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +    IsCardPresent = (PresState.Fields.CINST == 1);
> +  } else {
> +    if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal)) {
> +      //Read the state of  CD_B pin for the card socket
> +      CardDetectLevel = ImxGpioRead (
> +                         SdhcCtx->CardDetectGpioPin.Bank,
> +                         SdhcCtx->CardDetectGpioPin.IoNumber
> +                         );
> +    } else if (SdhcCtx->CardDetectSignal == USDHC_SIGNAL_OVERRIDE_PIN_LOW) {
> +      CardDetectLevel = IMX_GPIO_LOW;
> +    } else if (SdhcCtx->CardDetectSignal == USDHC_SIGNAL_OVERRIDE_PIN_HIGH) {
> +      CardDetectLevel = IMX_GPIO_HIGH;
> +    } else {
> +      ASSERT (!"Invalid CardDetect signal source");
> +      CardDetectLevel = IMX_GPIO_LOW;
> +    }
> +
> +    // When no card is present,  CD_B is pulled-high, and the SDCard when
> +    // inserted will pull CD_B low
> +    // CD_B=0 means card present, while CD_B=1 means card not present
> +    IsCardPresent = (CardDetectLevel == IMX_GPIO_LOW);
> +  }
> +
> +  LOG_TRACE ("SdhcIsCardPresent(): %d", IsCardPresent);
> +
> +  return IsCardPresent;
> +}
> +
> +BOOLEAN
> +SdhcIsReadOnly (
> +  IN EFI_SDHC_PROTOCOL *This
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  BOOLEAN                 IsReadOnly;
> +  USDHC_PRES_STATE_REG    PresState;
> +  IMX_GPIO_VALUE          WriteProtectLevel;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +
> +  if (SdhcCtx->WriteProtectSignal == USDHC_SIGNAL_INTERNAL_PIN) {
> +    Reg = SdhcCtx->RegistersBase;
> +    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +    IsReadOnly = (PresState.Fields.WPSPL == 0);
> +  } else {
> +    if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal)) {
> +      //Read the state of  WP pin for the card socket
> +      WriteProtectLevel = ImxGpioRead (
> +                           SdhcCtx->WriteProtectGpioPin.Bank,
> +                           SdhcCtx->WriteProtectGpioPin.IoNumber
> +                           );
> +    } else if (SdhcCtx->WriteProtectSignal == USDHC_SIGNAL_OVERRIDE_PIN_LOW) {
> +      WriteProtectLevel = IMX_GPIO_LOW;
> +    } else if (SdhcCtx->WriteProtectSignal == USDHC_SIGNAL_OVERRIDE_PIN_HIGH) {
> +      WriteProtectLevel = IMX_GPIO_HIGH;
> +    } else {
> +      ASSERT (!"Invalid WriteProtect signal source");
> +      WriteProtectLevel = IMX_GPIO_LOW;
> +    }
> +
> +    // When no card is present,  WP is pulled-high, and the SDCard when
> +    // inserted will pull WP low if WP switch is configured to write enable
> +    // the SDCard, otherwise it WP will stay pulled-high
> +    // WP=0 means write enabled, while WP=1 means write protected
> +    IsReadOnly = (WriteProtectLevel != IMX_GPIO_LOW);
> +  }
> +
> +  LOG_TRACE ("SdhcIsReadOnly(): %d", IsReadOnly);
> +  return IsReadOnly;
> +}
> +
> +EFI_STATUS
> +SdhcSendCommand (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN CONST SD_COMMAND *Cmd,
> +  IN UINT32 Argument,
> +  IN OPTIONAL CONST SD_COMMAND_XFR_INFO *XfrInfo
> +  )
> +{
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_BLK_ATT_REG       BlkAtt;
> +  USDHC_CMD_XFR_TYP_REG   CmdXfrTyp;
> +  USDHC_MIX_CTRL_REG      MixCtrl;
> +  EFI_STATUS              Status;
> +  USDHC_WTMK_LVL_REG      WtmkLvl;
> +  UINT32                  WtmkThreshold;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +  Reg = SdhcCtx->RegistersBase;
> +
> +  LOG_TRACE (
> +    "SdhcSendCommand(%cCMD%d, %08x)",
> +    ((Cmd->Class == SdCommandClassApp) ? 'A' : ' '),
> +    (UINT32)Cmd->Index,
> +    Argument);
> +
> +  Status = WaitForCmdAndOrDataLine (SdhcCtx, Cmd);
> +  if (Status != EFI_SUCCESS) {
> +    LOG_ERROR ("SdhcWaitForCmdAndDataLine failed");
> +    return Status;
> +  }
> +
> +  // Clear Interrupt status
> +  MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
> +
> +  // Setup data transfer command
> +  if (XfrInfo) {
> +    if (XfrInfo->BlockCount > USDHC_MAX_BLOCK_COUNT) {
> +      LOG_ERROR (
> +        "Provided %d block count while SDHC max block count is %d",
> +        XfrInfo->BlockCount,
> +        USDHC_MAX_BLOCK_COUNT);
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    // Set block size and count
> +    BlkAtt.AsUint32 = 0;
> +    BlkAtt.Fields.BLKSIZE = XfrInfo->BlockSize;
> +    ASSERT (XfrInfo->BlockCount > 0);
> +    BlkAtt.Fields.BLKCNT = XfrInfo->BlockCount;
> +    MmioWrite32 ((UINTN)&Reg->BLK_ATT, BlkAtt.AsUint32);
> +
> +    // Set transfer parameters
> +    MixCtrl.AsUint32 = 0;
> +    if (Cmd->TransferDirection == SdTransferDirectionRead) {
> +      MixCtrl.Fields.DTDSEL = 1;
> +    }
> +
> +    if (XfrInfo->BlockCount > 1) {
> +      ASSERT ((Cmd->TransferType == SdTransferTypeMultiBlock) ||
> +              (Cmd->TransferType == SdTransferTypeMultiBlockNoStop));
> +      MixCtrl.Fields.MSBSEL = 1;
> +      MixCtrl.Fields.BCEN = 1;
> +    }
> +
> +    MmioWrite32 ((UINTN)&Reg->MIX_CTRL, MixCtrl.AsUint32);
> +
> +    WtmkLvl.AsUint32 = 0;
> +
> +    WtmkThreshold = USDHC_BLOCK_LENGTH_BYTES / 4;
> +    if (Cmd->TransferDirection == SdTransferDirectionRead) {
> +      if (WtmkThreshold > USDHC_WTMK_RD_WML_MAX_VAL) {
> +        WtmkThreshold = USDHC_WTMK_RD_WML_MAX_VAL;
> +      }
> +      WtmkLvl.Fields.RD_WML = WtmkThreshold;
> +    } else {
> +      if (WtmkThreshold > USDHC_WTMK_WR_WML_MAX_VAL) {
> +        WtmkThreshold = USDHC_WTMK_WR_WML_MAX_VAL;
> +      }
> +      WtmkLvl.Fields.WR_WML = WtmkThreshold;
> +    }
> +
> +    MmioWrite32 ((UINTN)&Reg->WTMK_LVL, WtmkLvl.AsUint32);
> +  }
> +
> +  // Set CMD parameters
> +  CmdXfrTyp.AsUint32 = 0;
> +  CmdXfrTyp.Fields.CMDINX = Cmd->Index;
> +
> +  switch (Cmd->ResponseType) {
> +  case SdResponseTypeNone:
> +    break;
> +
> +  case SdResponseTypeR1:
> +  case SdResponseTypeR5:
> +  case SdResponseTypeR6:
> +    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_48;
> +    CmdXfrTyp.Fields.CICEN = 1;
> +    CmdXfrTyp.Fields.CCCEN = 1;
> +    break;
> +
> +  case SdResponseTypeR1B:
> +  case SdResponseTypeR5B:
> +    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_48_CHK_BSY;
> +    CmdXfrTyp.Fields.CICEN = 1;
> +    CmdXfrTyp.Fields.CCCEN = 1;
> +    break;
> +
> +  case SdResponseTypeR2:
> +    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_136;
> +    CmdXfrTyp.Fields.CCCEN = 1;
> +    break;
> +
> +  case SdResponseTypeR3:
> +  case SdResponseTypeR4:
> +    CmdXfrTyp.Fields.RSPTYP = USDHC_CMD_XFR_TYP_RSPTYP_RSP_48;
> +    break;
> +
> +  default:
> +    LOG_ASSERT ("SdhcSendCommand(): Invalid response type");
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Cmd->Type == SdCommandTypeAbort) {
> +    CmdXfrTyp.Fields.CMDTYP = USDHC_CMD_XFR_TYP_CMDTYP_ABORT;
> +  }
> +
> +  if (XfrInfo) {
> +    CmdXfrTyp.Fields.DPSEL = 1;
> +  }
> +
> +  // Send command and wait for response
> +  MmioWrite32 ((UINTN)&Reg->CMD_ARG, Argument);
> +  MmioWrite32 ((UINTN)&Reg->CMD_XFR_TYP, CmdXfrTyp.AsUint32);
> +
> +  Status = WaitForCmdResponse (SdhcCtx);
> +  if (EFI_ERROR (Status)) {
> +    LOG_ERROR ("WaitForCmdResponse() failed. %r", Status);
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SdhcReceiveResponse (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN CONST SD_COMMAND *Cmd,
> +  OUT UINT32 *Buffer
> +  )
> +{
> +
> +  USDHC_REGISTERS *Reg;
> +  USDHC_PRIVATE_CONTEXT *SdhcCtx;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +
> +  if (Buffer == NULL) {
> +    LOG_ERROR ("Input Buffer is NULL");
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Reg = SdhcCtx->RegistersBase;
> +
> +  switch (Cmd->ResponseType) {
> +  case SdResponseTypeNone:
> +    break;
> +  case SdResponseTypeR1:
> +  case SdResponseTypeR1B:
> +  case SdResponseTypeR3:
> +  case SdResponseTypeR4:
> +  case SdResponseTypeR5:
> +  case SdResponseTypeR5B:
> +  case SdResponseTypeR6:
> +    Buffer[0] = MmioRead32 ((UINTN)&Reg->CMD_RSP0);
> +    LOG_TRACE (
> +      "SdhcReceiveResponse(Type: %x), Buffer[0]: %08x",
> +      Cmd->ResponseType,
> +      Buffer[0]);
> +    break;
> +  case SdResponseTypeR2:
> +    Buffer[0] = MmioRead32 ((UINTN)&Reg->CMD_RSP0);
> +    Buffer[1] = MmioRead32 ((UINTN)&Reg->CMD_RSP1);
> +    Buffer[2] = MmioRead32 ((UINTN)&Reg->CMD_RSP2);
> +    Buffer[3] = MmioRead32 ((UINTN)&Reg->CMD_RSP3);
> +
> +    LOG_TRACE (
> +      "SdhcReceiveResponse(Type: %x), Buffer[0-3]: %08x, %08x, %08x, %08x",
> +      Cmd->ResponseType,
> +      Buffer[0],
> +      Buffer[1],
> +      Buffer[2],
> +      Buffer[3]);
> +    break;
> +  default:
> +    LOG_ASSERT ("SdhcReceiveResponse(): Invalid response type");
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SdhcReadBlockData (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN UINTN LengthInBytes,
> +  OUT UINT32 *Buffer
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  UINT32                  FifoWords;
> +  UINTN                   NumWords;
> +  EFI_STATUS              Status;
> +  UINTN                   WordIdx;
> +  USDHC_WTMK_LVL_REG      WtmkLvl;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +
> +  LOG_TRACE (
> +    "SdhcReadBlockData(LengthInBytes: 0x%x, Buffer: 0x%x)",
> +    LengthInBytes,
> +    Buffer);
> +
> +  ASSERT (Buffer != NULL);
> +  ASSERT (LengthInBytes % sizeof (UINT32) == 0);
> +
> +  WordIdx = 0;
> +  NumWords = LengthInBytes / sizeof (UINT32);
> +  Reg = SdhcCtx->RegistersBase;
> +  WtmkLvl.AsUint32 = MmioRead32 ((UINTN)&Reg->WTMK_LVL);
> +
> +  ASSERT (WtmkLvl.Fields.RD_WML > 0);
> +
> +  while (WordIdx < NumWords) {
> +    Status = WaitForReadFifo (SdhcCtx);
> +    if (EFI_ERROR (Status)) {
> +      LOG_ERROR (
> +        "WaitForReadFifo() failed at Word%d. %r",
> +        (UINT32)WordIdx,
> +        Status);
> +      return Status;
> +    }
> +
> +    FifoWords = WtmkLvl.Fields.RD_WML;
> +    while (WordIdx < NumWords && FifoWords--) {
> +      Buffer[WordIdx] = MmioRead32 ((UINTN)&Reg->DATA_BUFF_ACC_PORT);
> +      ++WordIdx;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SdhcWriteBlockData (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN UINTN LengthInBytes,
> +  IN CONST UINT32 *Buffer
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  USDHC_INT_STATUS_REG    IntStatus;
> +  UINTN                   NumBlocks;
> +  USDHC_PRES_STATE_REG    PresState;
> +  UINTN                   RemainingWords;
> +  INT32                   Retry;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +
> +  LOG_TRACE (
> +    "SdhcWriteBlockData(LengthInBytes: 0x%x, Buffer: 0x%x)",
> +    LengthInBytes,
> +    Buffer);
> +
> +  ASSERT (Buffer != NULL);
> +  ASSERT (LengthInBytes % USDHC_BLOCK_LENGTH_BYTES == 0);
> +
> +  CONST UINTN BlockWordCount = USDHC_BLOCK_LENGTH_BYTES / sizeof (UINT32);
> +  NumBlocks = LengthInBytes / USDHC_BLOCK_LENGTH_BYTES;
> +  Reg = SdhcCtx->RegistersBase;
> +  Retry = 100000;
> +
> +  while (NumBlocks > 0) {
> +    RemainingWords = BlockWordCount;
> +    IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +    PresState.AsUint32 = MmioRead32 ((UINTN)&Reg->PRES_STATE);
> +    while (!PresState.Fields.BWEN && --Retry);
> +    if (Retry <= 0) {
> +      LOG_ERROR ("Timeout waiting for FIFO PRES_STATE.BWEN flag");
> +      return EFI_TIMEOUT;
> +    }
> +
> +    while (RemainingWords > 0 && !IntStatus.Fields.TC) {
> +      MicroSecondDelay (100);
> +      IntStatus.AsUint32 = MmioRead32 ((UINTN)&Reg->INT_STATUS);
> +      MmioWrite32 ((UINTN)&Reg->DATA_BUFF_ACC_PORT, *Buffer);
> +      Buffer++;
> +      RemainingWords--;
> +    }
> +    NumBlocks--;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SdhcSoftwareReset (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  IN SDHC_RESET_TYPE ResetType
> +  )
> +{
> +  USDHC_REGISTERS         *Reg;
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  USDHC_PROT_CTRL_REG     ProtCtrl;
> +  UINT32                  Retry;
> +  EFI_STATUS              Status;
> +  USDHC_SYS_CTRL_REG      SysCtrl;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +  Reg = SdhcCtx->RegistersBase;
> +
> +  if (ResetType == SdhcResetTypeAll) {
> +    LOG_TRACE ("SdhcSoftwareReset(ALL)");
> +    // Software reset for ALL
> +    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    SysCtrl.Fields.RSTA = 1;
> +    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
> +    Retry = USDHC_POLL_RETRY_COUNT;
> +
> +    // Wait for reset to complete
> +    while (SysCtrl.Fields.RSTA && Retry) {
> +      --Retry;

Why use the prefix -- when the evaluation order doesn't matter?
This is inconsistent with other uses in this file, other than
... exactly this pattern seen across several functions.
Can this (and any other repeating patterns I haven't spotted) be
broken out into STATIC helper functions instead of duplicated?

> +      gBS->Stall (USDHC_POLL_WAIT_US);
> +      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    }
> +
> +    if (SysCtrl.Fields.RSTA) {
> +      ASSERT (!Retry);
> +      LOG_ERROR ("Time-out waiting on RSTA for self-clear");
> +      return EFI_TIMEOUT;
> +    }
> +
> +    // Disconnect interrupt signals between SDHC and GIC
> +    MmioWrite32 ((UINTN)&Reg->INT_SIGNAL_EN, 0);
> +
> +    // Clear and Enable all interrupts
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS_EN, (UINT32)~0);
> +
> +    LOG_TRACE ("Waiting for CMD and DATA lines");
> +
> +    // Wait for CMD and DATA lines to become available
> +    Status = WaitForCmdAndOrDataLine (SdhcCtx, NULL);
> +    if (Status != EFI_SUCCESS) {
> +      LOG_ERROR ("SdhcWaitForCmdAndDataLine() failed. %r", Status);
> +      return Status;
> +    }
> +
> +    // Send 80 clock ticks to power-up the card
> +    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    SysCtrl.Fields.INITA = 1;

What does this 1 mean? Can a descriptive #define clarify?

> +    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
> +    Retry = USDHC_POLL_RETRY_COUNT;
> +
> +    // Wait for the 80 clock ticks to complete
> +    while (SysCtrl.Fields.INITA && Retry) {
> +      --Retry;
> +      gBS->Stall (USDHC_POLL_WAIT_US);
> +      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    }
> +
> +    if (SysCtrl.Fields.INITA) {
> +      ASSERT (!Retry);
> +      LOG_ERROR ("Time-out waiting on INITA for self-clear");
> +      return EFI_TIMEOUT;
> +    }
> +
> +    LOG_TRACE ("Card power-up complete");
> +
> +    // Set max data-timout counter value
> +    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    SysCtrl.Fields.DTOCV = 0xF;
> +    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
> +
> +    // Reset Mixer Control
> +    MmioWrite32 ((UINTN)&Reg->MIX_CTRL, 0);
> +
> +    ProtCtrl.AsUint32 = 0;
> +    ProtCtrl.Fields.EMODE = USDHC_PROT_CTRL_EMODE_LITTLE_ENDIAN;
> +    ProtCtrl.Fields.LCTL = 1;

What does this 1 mean? Can a descriptive #define clarify?

> +    MmioWrite32 ((UINTN)&Reg->PROT_CTRL, ProtCtrl.AsUint32);
> +
> +    LOG_TRACE ("Reset ALL complete");
> +
> +  } else if (ResetType == SdhcResetTypeCmd) {
> +    LOG_TRACE ("SdhcSoftwareReset(CMD)");
> +    //
> +    // Software reset for CMD
> +    //
> +    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    SysCtrl.Fields.RSTC = 1;

What does this 1 mean? Can a descriptive #define clarify?
(I'll stop repeating here, but you get the point. Please try to get
rid of live-coded numbers.)

> +    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
> +    Retry = USDHC_POLL_RETRY_COUNT;
> +
> +    //
> +    // Wait for reset to complete
> +    //
> +    while (SysCtrl.Fields.RSTC && Retry) {
> +      --Retry;
> +      gBS->Stall (USDHC_POLL_WAIT_US);
> +      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    }
> +
> +    if (SysCtrl.Fields.RSTC) {
> +      ASSERT (!Retry);
> +      LOG_ERROR ("Time-out waiting on RSTC for self-clear");
> +      return EFI_TIMEOUT;
> +    }
> +
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
> +
> +    LOG_TRACE ("Reset CMD complete");
> +
> +  } else if (ResetType == SdhcResetTypeData) {
> +    LOG_TRACE ("SdhcSoftwareReset(DAT)");
> +    // Software reset for DAT
> +    SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    SysCtrl.Fields.RSTD = 1;
> +    MmioWrite32 ((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32);
> +    Retry = USDHC_POLL_RETRY_COUNT;
> +
> +    // Wait for reset to complete
> +    while (SysCtrl.Fields.RSTD && Retry) {
> +      --Retry;
> +      gBS->Stall (USDHC_POLL_WAIT_US);
> +      SysCtrl.AsUint32 = MmioRead32 ((UINTN)&Reg->SYS_CTRL);
> +    }
> +
> +    if (SysCtrl.Fields.RSTD) {
> +      ASSERT (!Retry);
> +      LOG_ERROR ("Time-out waiting on RSTD for self-clear");
> +      return EFI_TIMEOUT;
> +    }
> +
> +    MmioWrite32 ((UINTN)&Reg->INT_STATUS, (UINT32)~0);
> +
> +    LOG_TRACE ("Reset DAT complete");
> +
> +  } else {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +SdhcCleanup (
> +  IN EFI_SDHC_PROTOCOL *This
> +  )
> +{
> +  if (This->PrivateContext != NULL) {
> +    FreePool (This->PrivateContext);
> +    This->PrivateContext = NULL;

Why set this to NULL immediately before freeing the struct containing
it?

> +  }
> +
> +  FreePool (This);
> +}
> +
> +VOID
> +SdhcGetCapabilities (
> +  IN EFI_SDHC_PROTOCOL *This,
> +  OUT SDHC_CAPABILITIES *Capabilities
> +  )
> +{
> +  USDHC_REGISTERS           *Reg;
> +  USDHC_PRIVATE_CONTEXT     *SdhcCtx;
> +  USDHC_HOST_CTRL_CAP_REG   Caps;
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)This->PrivateContext;
> +  Reg = SdhcCtx->RegistersBase;
> +  Caps.AsUint32 = MmioRead32 ((UINTN)&Reg->HOST_CTRL_CAP);
> +  Capabilities->MaximumBlockSize = (UINT32) (512 << Caps.Fields.MBL);
> +  Capabilities->MaximumBlockCount = 0xFFFF;
> +}
> +
> +static EFI_SDHC_PROTOCOL mSdhcProtocolTemplate = {

STATIC

> +  SDHC_PROTOCOL_INTERFACE_REVISION,   // Revision
> +  0,                                  // DeviceId
> +  NULL,                               // PrivateContext
> +  SdhcGetCapabilities,
> +  SdhcSoftwareReset,
> +  SdhcSetClock,
> +  SdhcSetBusWidth,
> +  SdhcIsCardPresent,
> +  SdhcIsReadOnly,
> +  SdhcSendCommand,
> +  SdhcReceiveResponse,
> +  SdhcReadBlockData,
> +  SdhcWriteBlockData,
> +  SdhcCleanup
> +};
> +
> +EFI_STATUS
> +SdhcDeviceRegister (
> +  IN EFI_HANDLE ImageHandle,
> +  IN UINT32 SdhcId,
> +  IN VOID *RegistersBase,
> +  IN USDHC_SIGNAL_SOURCE CardDetectSignal,
> +  IN USDHC_SIGNAL_SOURCE WriteProtectSignal
> +  )
> +{
> +  USDHC_PRIVATE_CONTEXT   *SdhcCtx;
> +  EFI_SDHC_PROTOCOL       *SdhcProtocol;
> +  EFI_STATUS              Status;
> +
> +  SdhcProtocol = NULL;
> +  SdhcCtx = NULL;
> +
> +  if (ImageHandle == NULL ||
> +      RegistersBase == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +  // Allocate per-device SDHC protocol and private context storage
> +  SdhcProtocol = AllocateCopyPool (sizeof (EFI_SDHC_PROTOCOL),
> +                                   &mSdhcProtocolTemplate);
> +  if (SdhcProtocol == NULL) {
> +    Status =  EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +  SdhcProtocol->SdhcId = SdhcId;
> +  SdhcProtocol->PrivateContext = AllocateZeroPool (sizeof (
> +                                   USDHC_PRIVATE_CONTEXT));
> +  if (SdhcProtocol->PrivateContext == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +
> +  SdhcCtx = (USDHC_PRIVATE_CONTEXT *)SdhcProtocol->PrivateContext;
> +  SdhcCtx->SdhcId = SdhcId;
> +  SdhcCtx->RegistersBase = (USDHC_REGISTERS *)RegistersBase;
> +  SdhcCtx->CardDetectSignal = CardDetectSignal;
> +  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal)) {
> +    SdhcCtx->CardDetectGpioPin.IoNumber = PCD_GPIO_PIN_IO_NUMBER ((
> +                                            UINT16)CardDetectSignal);
> +    SdhcCtx->CardDetectGpioPin.Bank = PCD_GPIO_PIN_BANK (CardDetectSignal);
> +  }
> +
> +  SdhcCtx->WriteProtectSignal = WriteProtectSignal;
> +  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal)) {
> +    SdhcCtx->WriteProtectGpioPin.IoNumber = PCD_GPIO_PIN_IO_NUMBER ((
> +        UINT16)WriteProtectSignal);
> +    SdhcCtx->WriteProtectGpioPin.Bank = PCD_GPIO_PIN_BANK (WriteProtectSignal);
> +  }
> +

Pleas break from here

> +  LOG_INFO (
> +    "Initializing uSDHC%d @%p GPIO CD?:%d WP?:%d",
> +    SdhcId,
> +    RegistersBase,
> +    (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal) ? 1 : 0),
> +    (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal) ? 1 : 0));
> +
> +  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->CardDetectSignal)) {
> +    LOG_INFO (
> +      "Using GPIO%d_IO%d for CardDetect",
> +      SdhcCtx->CardDetectGpioPin.Bank,
> +      SdhcCtx->CardDetectGpioPin.IoNumber);
> +  }
> +
> +  if (USDHC_IS_GPIO_SIGNAL_SOURCE (SdhcCtx->WriteProtectSignal)) {
> +    LOG_INFO (
> +      "Using GPIO%d_IO%d for WriteProtect",
> +      SdhcCtx->WriteProtectGpioPin.Bank,
> +      SdhcCtx->WriteProtectGpioPin.IoNumber);
> +  }

to here into a static helper function.

> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +             &SdhcCtx->SdhcProtocolHandle,
> +             &gEfiSdhcProtocolGuid,
> +             SdhcProtocol,
> +             NULL);
> +  if (EFI_ERROR (Status)) {
> +    LOG_ERROR ("InstallMultipleProtocolInterfaces failed. %r", Status);
> +    goto Exit;

That goto seems excessive.

> +  }
> +
> +Exit:
> +  if (EFI_ERROR (Status)) {
> +    LOG_ERROR ("Failed to register and initialize uSDHC%d", SdhcId);
> +
> +    if (SdhcProtocol != NULL && SdhcProtocol->PrivateContext != NULL) {
> +      FreePool (SdhcProtocol->PrivateContext);
> +      SdhcProtocol->PrivateContext = NULL;
> +    }
> +
> +    if (SdhcProtocol != NULL) {
> +      FreePool (SdhcProtocol);
> +      SdhcProtocol = NULL;
> +    }

Why not call SdhcCleanup?

> +  }
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +SdhcInitialize (
> +  IN EFI_HANDLE ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  UINT32      SdhcRegisteredCount;
> +  EFI_STATUS  Status;
> +
> +  Status = EFI_SUCCESS;
> +  SdhcRegisteredCount = 0;
> +
> +  // Register uSDHC1 through uSDHC4 if their base address is non-zero
> +
> +  // uSDHC1
> +  if (FixedPcdGet32 (PcdSdhc1Enable)) {
> +    Status = SdhcDeviceRegister (
> +               ImageHandle,
> +               1,
> +               (VOID *)FixedPcdGet32 (PcdSdhc1Base),
> +               FixedPcdGet32 (PcdSdhc1CardDetectSignal),
> +               FixedPcdGet32 (PcdSdhc1WriteProtectSignal));
> +    if (!EFI_ERROR (Status)) {
> +      ++SdhcRegisteredCount;
> +    }
> +  }
> +
> +  // uSDHC2
> +  if (FixedPcdGet32 (PcdSdhc2Enable)) {
> +    Status = SdhcDeviceRegister (
> +               ImageHandle,
> +               2,
> +               (VOID *)FixedPcdGet32 (PcdSdhc2Base),
> +               FixedPcdGet32 (PcdSdhc2CardDetectSignal),
> +               FixedPcdGet32 (PcdSdhc2WriteProtectSignal));
> +    if (!EFI_ERROR (Status)) {
> +      ++SdhcRegisteredCount;
> +    }
> +  }
> +
> +  // uSDHC3
> +  if (FixedPcdGet32 (PcdSdhc3Enable)) {
> +    Status = SdhcDeviceRegister (
> +               ImageHandle,
> +               3,
> +               (VOID *)FixedPcdGet32 (PcdSdhc3Base),
> +               FixedPcdGet32 (PcdSdhc3CardDetectSignal),
> +               FixedPcdGet32 (PcdSdhc3WriteProtectSignal));
> +    if (!EFI_ERROR (Status)) {
> +      ++SdhcRegisteredCount;
> +    }
> +  }
> +
> +  // uSDHC4
> +  if (FixedPcdGet32 (PcdSdhc4Enable)) {
> +    Status = SdhcDeviceRegister (
> +               ImageHandle,
> +               4,
> +               (VOID *)FixedPcdGet32 (PcdSdhc4Base),
> +               FixedPcdGet32 (PcdSdhc4CardDetectSignal),
> +               FixedPcdGet32 (PcdSdhc4WriteProtectSignal));
> +    if (!EFI_ERROR (Status)) {
> +      ++SdhcRegisteredCount;
> +    }
> +  }
> +

The above needs to be converted into non-discoverable devices and UEFI
driver model.

> +  // Succeed driver loading if at least one enabled uSDHC got registered successfully
> +  if ((Status != EFI_SUCCESS) && (SdhcRegisteredCount > 0)) {
> +    Status = EFI_SUCCESS;
> +  }
> +
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h
> new file mode 100644
> index 000000000000..e3f7fe62b0b6
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h

Ah yeah, this would have helped to see before. Hence the sortOrder
file.

The whole driver should probablt be renamed iMXSdhcDxe, and files
follow form.

> @@ -0,0 +1,81 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _SDHC_DXE_H_
> +#define _SDHC_DXE_H_

And include guard IMX_.

> +
> +typedef struct {
> +  UINT32 IoNumber;
> +  IMX_GPIO_BANK Bank;
> +} IMX_GPIO_PIN;
> +
> +#define PCD_GPIO_PIN_IO_NUMBER(X)   ((X) & 0xFF)
> +#define PCD_GPIO_PIN_BANK(X)        (((X) >> 8) & 0xFF)
> +
> +// A special value to indicate that GPIO is not the signal source for either
> +// CardDetect or WriteProtect
> +typedef enum {
> +  USDHC_SIGNAL_GPIO_START = 0x000,
> +  USDHC_SIGNAL_GPIO_END = 0xFF00,
> +  USDHC_SIGNAL_OVERRIDE_PIN_LOW = 0xFF00,
> +  USDHC_SIGNAL_OVERRIDE_PIN_HIGH = 0xFF01,
> +  USDHC_SIGNAL_INTERNAL_PIN = 0xFFFF
> +} USDHC_SIGNAL_SOURCE;
> +
> +#define USDHC_IS_GPIO_SIGNAL_SOURCE(X)  \
> +    (((X) >= USDHC_SIGNAL_GPIO_START) && ((X) < USDHC_SIGNAL_GPIO_END))
> +
> +typedef struct {
> +  UINT32 SdhcId;
> +  EFI_HANDLE SdhcProtocolHandle;
> +  USDHC_REGISTERS *RegistersBase;
> +  USDHC_SIGNAL_SOURCE CardDetectSignal;
> +  USDHC_SIGNAL_SOURCE WriteProtectSignal;
> +  IMX_GPIO_PIN CardDetectGpioPin;
> +  IMX_GPIO_PIN WriteProtectGpioPin;
> +} USDHC_PRIVATE_CONTEXT;
> +
> +#define LOG_FMT_HELPER(FMT, ...) \
> +    "SDHC%d:" FMT "%a\n", ((SdhcCtx != NULL) ? SdhcCtx->SdhcId : -1), __VA_ARGS__
> +
> +#define LOG_INFO(...) \
> +    DEBUG((DEBUG_INFO | DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
> +
> +#define LOG_TRACE(...) \
> +    DEBUG((DEBUG_VERBOSE | DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
> +
> +#define LOG_ERROR(...) \
> +    DEBUG((DEBUG_ERROR | DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
> +
> +#define LOG_ASSERT(TXT) \
> +    ASSERT(!"Sdhc: " TXT "\n")
> +
> +// uSDHC read/write FIFO is 128x32-bit
> +#define USDHC_FIFO_MAX_WORD_COUNT       128
> +
> +// Max block count allowed in a single transfer
> +#define USDHC_MAX_BLOCK_COUNT           0xFFFF
> +
> +// Number of register maximum polls
> +#define USDHC_POLL_RETRY_COUNT          100000
> +
> +// Waits between each registry poll
> +#define USDHC_POLL_WAIT_US              20
> +
> +// uSDHC input clock. Ideally, should query it from clock manager
> +#define USDHC_BASE_CLOCK_FREQ_HZ        198000000
> +
> +#define USDHC_BLOCK_LENGTH_BYTES               512
> +
> +#endif // _SDHC_DXE_H_
> diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
> new file mode 100644
> index 000000000000..5f29b7a7b7c8
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
> @@ -0,0 +1,70 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = SdhcDxe
> +  FILE_GUID                      = A9945BAB-78C9-43C9-9175-F576CA189870
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = SdhcInitialize
> +
> +[Sources.common]
> +  SdhcDxe.c
> +
> +[Packages]
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +  Platform/Microsoft/MsPkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +  iMXIoMuxLib
> +  IoLib
> +  MemoryAllocationLib
> +  PcdLib
> +  UefiLib
> +  UefiDriverEntryPoint
> +
> +[Guids]
> +
> +[Protocols]
> +  gEfiSdhcProtocolGuid
> +
> +[Pcd]
> +  giMXPlatformTokenSpaceGuid.PcdSdhc1Base
> +  giMXPlatformTokenSpaceGuid.PcdSdhc1CardDetectSignal
> +  giMXPlatformTokenSpaceGuid.PcdSdhc1Enable
> +  giMXPlatformTokenSpaceGuid.PcdSdhc1WriteProtectSignal
> +
> +  giMXPlatformTokenSpaceGuid.PcdSdhc2Base
> +  giMXPlatformTokenSpaceGuid.PcdSdhc2CardDetectSignal
> +  giMXPlatformTokenSpaceGuid.PcdSdhc2Enable
> +  giMXPlatformTokenSpaceGuid.PcdSdhc2WriteProtectSignal
> +
> +  giMXPlatformTokenSpaceGuid.PcdSdhc3Base
> +  giMXPlatformTokenSpaceGuid.PcdSdhc3CardDetectSignal
> +  giMXPlatformTokenSpaceGuid.PcdSdhc3Enable
> +  giMXPlatformTokenSpaceGuid.PcdSdhc3WriteProtectSignal
> +
> +  giMXPlatformTokenSpaceGuid.PcdSdhc4Base
> +  giMXPlatformTokenSpaceGuid.PcdSdhc4CardDetectSignal
> +  giMXPlatformTokenSpaceGuid.PcdSdhc4Enable
> +  giMXPlatformTokenSpaceGuid.PcdSdhc4WriteProtectSignal
> +
> +[FixedPcd]
> +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> +
> +[depex]
> +  TRUE
> diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h b/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
> new file mode 100644
> index 000000000000..df57159d9d41
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
> @@ -0,0 +1,277 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef __IMX_USDHC_H__
> +#define __IMX_USDHC_H__
> +
> +//
> +// uSDHCx Registers Layout
> +//
> +typedef struct {
> +  UINT32 DS_ADDR;
> +  UINT32 BLK_ATT;
> +  UINT32 CMD_ARG;
> +  UINT32 CMD_XFR_TYP;
> +  UINT32 CMD_RSP0;
> +  UINT32 CMD_RSP1;
> +  UINT32 CMD_RSP2;
> +  UINT32 CMD_RSP3;
> +  UINT32 DATA_BUFF_ACC_PORT;
> +  UINT32 PRES_STATE;
> +  UINT32 PROT_CTRL;
> +  UINT32 SYS_CTRL;
> +  UINT32 INT_STATUS;
> +  UINT32 INT_STATUS_EN;
> +  UINT32 INT_SIGNAL_EN;
> +  UINT32 AUTOCMD12_ERR_STATUS;
> +  UINT32 HOST_CTRL_CAP;
> +  UINT32 WTMK_LVL;
> +  UINT32 MIX_CTRL;
> +  UINT32 _pad0;
> +  UINT32 FORCE_EVENT;
> +  UINT32 ADMA_ERR_STATUS;
> +  UINT32 ADMA_SYS_ADDR;
> +  UINT32 _pad1;
> +  UINT32 DLL_CTRL;
> +  UINT32 DLL_STATUS;
> +  UINT32 CLK_TUNE_CTRL_STATUS;
> +  UINT32 _pad2[21];
> +  UINT32 VEND_SPEC;
> +  UINT32 MMC_BOOT;
> +  UINT32 VEND_SPEC2;

Struct members should be renamed to CamelCase, throughout.

> +} USDHC_REGISTERS;
> +
> +//
> +// Block Attributes uSDHCx_BLK_ATT fields
> +//
> +typedef union {
> +  UINT32 AsUint32;

Raw, or Data, throughout.

/
    Leif

> +  struct {
> +    UINT32 BLKSIZE    : 13; // 0:12
> +    UINT32 _reserved0 : 3;  // 13:15
> +    UINT32 BLKCNT     : 16; // 16:31
> +  } Fields;
> +} USDHC_BLK_ATT_REG;
> +
> +//
> +// Command Transfer Type uSDHCx_CMD_XFR_TYP fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 _reserved0   : 16; // 0:15
> +    UINT32 RSPTYP       : 2; // 16:17
> +    UINT32 _reserved1   : 1; // 18
> +    UINT32 CCCEN        : 1; // 19
> +    UINT32 CICEN        : 1; // 20
> +    UINT32 DPSEL        : 1; // 21
> +    UINT32 CMDTYP       : 2; // 22:23
> +    UINT32 CMDINX       : 6; // 24:29
> +    UINT32 _reserved2   : 2; // 30:31
> +  } Fields;
> +} USDHC_CMD_XFR_TYP_REG;
> +
> +#define USDHC_CMD_XFR_TYP_RSPTYP_NO_RSP          0
> +#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_136         1
> +#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_48          2
> +#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_48_CHK_BSY  3
> +#define USDHC_CMD_XFR_TYP_CMDTYP_ABORT           3
> +
> +//
> +// System Control uSDHCx_SYS_CTRL fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 _reserved0   : 4; // 0:3
> +    UINT32 DVS          : 4; // 4:7
> +    UINT32 SDCLKFS      : 8; // 8:15
> +    UINT32 DTOCV        : 4; // 16:19
> +    UINT32 _reserved1   : 3; // 20:22
> +    UINT32 IPP_RST_N    : 1; // 23
> +    UINT32 RSTA         : 1; // 24
> +    UINT32 RSTC         : 1; // 25
> +    UINT32 RSTD         : 1; // 26
> +    UINT32 INITA        : 1; // 27
> +    UINT32 _reserved2   : 4; // 28-31
> +  } Fields;
> +} USDHC_SYS_CTRL_REG;
> +
> +//
> +// Host Controller Capabilities Register uSDHCx_HOST_CTRL_CAP fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 _reserved0       : 16; // 0:15
> +    UINT32 MBL              : 3; // 16:18
> +    UINT32 _reserved1       : 1; // 19
> +    UINT32 ADMAS            : 1; // 20
> +    UINT32 HSS              : 1; // 21
> +    UINT32 DMAS             : 1; // 22
> +    UINT32 SRS              : 1; // 23
> +    UINT32 VS33             : 1; // 24
> +    UINT32 VS30             : 1; // 25
> +    UINT32 VS18             : 1; // 26
> +    UINT32 _reserved2       : 5; // 27:31
> +  } Fields;
> +} USDHC_HOST_CTRL_CAP_REG;
> +
> +//
> +// Watermark Level uSDHCx_WTMK_LVL
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 RD_WML           : 8; // 0:7
> +    UINT32 RD_BRST_LEN      : 5; // 8:12
> +    UINT32 _reserved0       : 3; // 13:15
> +    UINT32 WR_WML           : 8; // 16:23
> +    UINT32 WR_BRST_LEN      : 5; // 24:28
> +    UINT32 _reserved1       : 3; // 29:31
> +  } Fields;
> +} USDHC_WTMK_LVL_REG;
> +
> +#define USDHC_WTMK_RD_WML_MAX_VAL   0x10
> +#define USDHC_WTMK_WR_WML_MAX_VAL   0x80
> +
> +//
> +// Mixer Control uSDHCx_MIX_CTRL fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 DMAEN          : 1; // 0
> +    UINT32 BCEN           : 1; // 1
> +    UINT32 AC12EN         : 1; // 2
> +    UINT32 DDR_EN         : 1; // 3
> +    UINT32 DTDSEL         : 1; // 4
> +    UINT32 MSBSEL         : 1; // 5
> +    UINT32 NIBBLE_POS     : 1; // 6
> +    UINT32 AC23EN         : 1; // 7
> +    UINT32 _reserved0     : 14; // 8:21
> +    UINT32 EXE_TUNE       : 1; // 22
> +    UINT32 SMP_CLK_SEL    : 1; // 23
> +    UINT32 AUTO_TUNE_EN   : 1; //24
> +    UINT32 FBCLK_SEL      : 1; // 25
> +    UINT32 _reserved1     : 6; // 26-31
> +  } Fields;
> +} USDHC_MIX_CTRL_REG;
> +
> +//
> +// Present State uSDHCx_PRES_STATE fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 CIHB         : 1; // 0
> +    UINT32 CDIHB        : 1; // 1
> +    UINT32 DLA          : 1; // 2
> +    UINT32 SDSTB        : 1; // 3
> +    UINT32 IPGOFF       : 1; // 4
> +    UINT32 HCKOFF       : 1; // 5
> +    UINT32 PEROFF       : 1; // 6
> +    UINT32 SDOFF        : 1; // 7
> +    UINT32 WTA          : 1; // 8
> +    UINT32 RTA          : 1; // 9
> +    UINT32 BWEN         : 1; // 10
> +    UINT32 BREN         : 1; // 11
> +    UINT32 PTR          : 1; // 12
> +    UINT32 _reserved0   : 3; // 13:15
> +    UINT32 CINST        : 1; // 16
> +    UINT32 _reserved1   : 1; // 17
> +    UINT32 CDPL         : 1; // 18
> +    UINT32 WPSPL        : 1; // 19
> +    UINT32 _reserved2   : 3; // 20:22
> +    UINT32 CLSL         : 1; // 23
> +    UINT32 DLSL         : 8; // 24:31
> +  } Fields;
> +} USDHC_PRES_STATE_REG;
> +
> +//
> +// Present State uSDHCx_PROT_CTRL fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 LCTL             : 1; // 0
> +    UINT32 DTW              : 2; // 1:2
> +    UINT32 D3CD             : 1; // 3
> +    UINT32 EMODE            : 2; // 4:5
> +    UINT32 CDTL             : 1; // 6
> +    UINT32 CDSS             : 1; // 7
> +    UINT32 DMASEL           : 2; // 8:9
> +    UINT32 _reserved0       : 6; // 10:15
> +    UINT32 SABGREQ          : 1; // 16
> +    UINT32 CREQ             : 1; // 17
> +    UINT32 RWCTL            : 1; // 18
> +    UINT32 IABG             : 1; // 19
> +    UINT32 RD_DONE_NO_8CLK  : 1; // 20
> +    UINT32 _reserved1       : 3; // 21:23
> +    UINT32 WECINT           : 1; // 24
> +    UINT32 WECINS           : 1; // 25
> +    UINT32 WECRM            : 1; // 26
> +    UINT32 BURST_LEN_EN     : 3; // 27:29
> +    UINT32 NON_EXACT_BLK_RD : 1; // 30
> +    UINT32 _reserved2       : 1; // 31
> +  } Fields;
> +} USDHC_PROT_CTRL_REG;
> +
> +#define USDHC_PROT_CTRL_DTW_1BIT             0x0
> +#define USDHC_PROT_CTRL_DTW_4BIT             0x1
> +#define USDHC_PROT_CTRL_DTW_8BIT             0x2
> +#define USDHC_PROT_CTRL_EMODE_LITTLE_ENDIAN  0x2
> +
> +//
> +// Interrupt Status uSDHCx_INT_STATUS fields
> +//
> +typedef union {
> +  UINT32 AsUint32;
> +  struct {
> +    UINT32 CC           : 1; // 0
> +    UINT32 TC           : 1; // 1
> +    UINT32 BGE          : 1; // 2
> +    UINT32 DINT         : 1; // 3
> +    UINT32 BWR          : 1; // 4
> +    UINT32 BRR          : 1; // 5
> +    UINT32 CINS         : 1; // 6
> +    UINT32 CRM          : 1; // 7
> +    UINT32 CINT         : 1; // 8
> +    UINT32 _reserved0   : 3; // 9:11
> +    UINT32 RTE          : 1; // 12
> +    UINT32 _reserved1   : 1; // 13
> +    UINT32 TP           : 1; // 14
> +    UINT32 _reserved2   : 1; // 15
> +    UINT32 CTOE         : 1; // 16
> +    UINT32 CCE          : 1; // 17
> +    UINT32 CEBE         : 1; // 18
> +    UINT32 CIE          : 1; // 19
> +    UINT32 DTOE         : 1; // 20
> +    UINT32 DCE          : 1; // 21
> +    UINT32 DEBE         : 1; // 22
> +    UINT32 _reserved3   : 1; // 23
> +    UINT32 AC12E        : 1; // 24
> +    UINT32 _reserved4   : 1; // 25
> +    UINT32 TNE          : 1; // 26
> +    UINT32 _reserved5   : 1; // 27
> +    UINT32 DMAE         : 1; // 28
> +    UINT32 _reserved6   : 3; // 29:31
> +  } Fields;
> +} USDHC_INT_STATUS_REG;
> +
> +#define USDHC_INT_STATUS_CMD_ERROR   (BIT16 | BIT17 | BIT18 | BIT19)
> +#define USDHC_INT_STATUS_DATA_ERROR  (BIT20 | BIT21 | BIT22)
> +#define USDHC_INT_STATUS_ERROR       (USDHC_INT_STATUS_CMD_ERROR | USDHC_INT_STATUS_DATA_ERROR)
> +
> +#endif // __IMX_USDHC_H__
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 



^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 11/27] Silicon/NXP: Add i.MX6 SoC header files
  2018-09-21  8:26 ` [PATCH edk2-platforms 11/27] Silicon/NXP: Add i.MX6 SoC header files Chris Co
@ 2018-12-13 17:11   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-13 17:11 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:02AM +0000, Chris Co wrote:
> This adds includes for NXP i.MX6 SoC family, specifically Dual/Quad,
> Solo/DualLite, SoloX, DualPlus/QuadPlus families.
> These are the header files for managing clocks, IoMux, and general
> SoC register layout information.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Include/iMX6.h           |   39 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h   |   55 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h     |  105 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h  |  181 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h |  176 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h  |  190 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h      |  202 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h  | 2466 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h  | 1875 +++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h   | 2270 ++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h        |  332 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h       |  335 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h       |  301 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h        | 1730 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_common.h    | 1350 +++++++++++
>  15 files changed, 11607 insertions(+)
> 

> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6.h b/Silicon/NXP/iMX6Pkg/Include/iMX6.h
> new file mode 100644
> index 000000000000..ded03eced048
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6.h
> @@ -0,0 +1,39 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef __IMX6_H__
> +#define __IMX6_H__
> +
> +// Platform specific definition
> +#define EFI_ACPI_OEM_TABLE_ID      SIGNATURE_64('I','M','X','6','E','D','K','2')
> +#define EFI_ACPI_OEM_REVISION      0x01000101
> +#define EFI_ACPI_CREATOR_ID        SIGNATURE_32('I','M','X','6')
> +#define EFI_ACPI_CREATOR_REVISION  0x00000001
> +
> +#if defined(CPU_IMX6DQ)
> +#include "iMX6_DQ.h"
> +#elif defined(CPU_IMX6DQP)
> +#include "iMX6_DQP.h"
> +#elif defined(CPU_IMX6SDL)
> +#include "iMX6_SDL.h"
> +#elif defined(CPU_IMX6SX)
> +#include "iMX6_SX.h"
> +#else
> +#error iMX6 CPU Type Not Defined! (Preprocessor Flag)
> +#endif
> +
> +#define SERIAL_DEBUG_PORT_INIT_MSG "\r\nDebug Serial Port Init\r\n"
> +#define SERIAL_PORT_INIT_MSG "UART"
> +
> +#endif // __IMX6_H__
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h b/Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
> new file mode 100644
> index 000000000000..7997ebc72897
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
> @@ -0,0 +1,55 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_BOARD_LIB_H_
> +#define _IMX6_BOARD_LIB_H_
> +
> +/*
> +  Mandatory functions to implement by the board library.
> +*/
> +
> +VOID
> +ImxClkPwrInit (
> +  );
> +
> +/*
> +  Optional functions to implement by the board library.
> +  The default implementation of these functions if not overridden is NOOP.
> +*/
> +
> +VOID
> +SdhcInit (
> +  );
> +
> +VOID
> +EhciInit (
> +  );
> +
> +VOID
> +I2cInit (
> +  );
> +
> +VOID
> +SpiInit (
> +  );
> +
> +VOID
> +PcieInit (
> +  );
> +
> +VOID
> +SetupAudio (
> +  );
> +
> +#endif // _IMX6_BOARD_LIB_H_
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
> new file mode 100644
> index 000000000000..18262751c443
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
> @@ -0,0 +1,105 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_CLK_PWR_H_
> +#define _IMX6_CLK_PWR_H_
> +
> +// The valid value for PLL loop divider is 27-54 so define the range of valid
> +// frequency for PLL5 below before divider is applied.
> +#define PLL5_MIN_FREQ 648000000
> +#define PLL5_MAX_FREQ 1296000000
> +
> +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> +#include "iMX6ClkPwr_DQ.h"
> +#elif defined(CPU_IMX6SDL)
> +#include "iMX6ClkPwr_SDL.h"
> +#elif defined(CPU_IMX6SX)
> +#include "iMX6ClkPwr_SX.h"
> +#else
> +#error iMX6 CPU Type Not Defined!
> +#endif
> +
> +typedef enum {
> +  IMX_CLOCK_GATE_STATE_OFF = 0x0,
> +  IMX_CLOCK_GATE_STATE_ON_RUN = 0x1,
> +  IMX_CLOCK_GATE_STATE_ON = 0x3,
> +} IMX_CLOCK_GATE_STATE;
> +
> +typedef struct {
> +  UINT32 Frequency;
> +  IMX_CLK Parent;
> +} IMX_CLOCK_INFO;
> +
> +VOID
> +ImxClkPwrSetClockGate (
> +  IN IMX_CLK_GATE ClockGate,
> +  IN IMX_CLOCK_GATE_STATE State
> +  );
> +
> +// Set multiple clock gates to a given state
> +VOID
> +ImxClkPwrSetClockGates (
> +  IN CONST IMX_CLK_GATE *ClockGateList,
> +  IN UINTN ClockGateCount,
> +  IN IMX_CLOCK_GATE_STATE State
> +  );
> +
> +IMX_CLOCK_GATE_STATE
> +ImxClkPwrGetClockGate (
> +  IN IMX_CLK_GATE ClockGate
> +  );
> +
> +EFI_STATUS
> +ImxClkPwrGetClockInfo (
> +  IN IMX_CLK ClockId,
> +  OUT IMX_CLOCK_INFO *ClockInfo
> +);
> +
> +EFI_STATUS
> +ImxClkPwrGpuEnable (
> +  );
> +
> +EFI_STATUS
> +ImxClkPwrIpuDIxEnable (
> +  );
> +
> +EFI_STATUS ImxClkPwrIpuLDBxEnable (
> +  );
> +
> +EFI_STATUS
> +ImxSetPll5ReferenceRate (
> +  UINT32 ClockRate
> +  );
> +
> +EFI_STATUS
> +ImxClkPwrClkOut1Enable (
> +  IMX_CLK Clock,
> +  UINT32 Divider
> +  );
> +
> +VOID
> +ImxClkPwrClkOut1Disable (
> +  );
> +
> +EFI_STATUS
> +ImxClkPwrValidateClocks (
> +  );
> +
> +CONST CHAR16
> +*StringFromImxClk (
> +  IN IMX_CLK Value
> +  );
> +
> +#endif // _IMX6_CLK_PWR_H_
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
> new file mode 100644
> index 000000000000..253e7c028bcb
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
> @@ -0,0 +1,181 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_CLK_PWR_DQ_H_
> +#define _IMX6_CLK_PWR_DQ_H_
> +
> +// Clock signal definitions
> +typedef enum {
> +  IMX_CLK_NONE,
> +  IMX_OSC_CLK,
> +  IMX_PLL1_MAIN_CLK,
> +  IMX_PLL2_MAIN_CLK,
> +  IMX_PLL2_PFD0,
> +  IMX_PLL2_PFD1,
> +  IMX_PLL2_PFD2,
> +  IMX_PLL3_MAIN_CLK,
> +  IMX_PLL3_PFD0,
> +  IMX_PLL3_PFD1,
> +  IMX_PLL3_PFD2,
> +  IMX_PLL3_PFD3,
> +  IMX_PLL4_MAIN_CLK,
> +  IMX_PLL5_MAIN_CLK,
> +  IMX_CLK1,
> +  IMX_CLK2,
> +  IMX_PLL1_SW_CLK,
> +  IMX_STEP_CLK,
> +  IMX_PLL3_SW_CLK,
> +  IMX_AXI_ALT,
> +  IMX_AXI_CLK_ROOT,
> +  IMX_PERIPH_CLK2,
> +  IMX_PERIPH_CLK,
> +  IMX_PRE_PERIPH_CLK,
> +  IMX_PRE_PERIPH2_CLK,
> +  IMX_PERIPH2_CLK,
> +  IMX_ARM_CLK_ROOT,
> +  IMX_MMDC_CH0_CLK_ROOT,
> +  IMX_MMDC_CH1_CLK_ROOT,
> +  IMX_AHB_CLK_ROOT,
> +  IMX_IPG_CLK_ROOT,
> +  IMX_PERCLK_CLK_ROOT,
> +  IMX_USDHC1_CLK_ROOT,
> +  IMX_USDHC2_CLK_ROOT,
> +  IMX_USDHC3_CLK_ROOT,
> +  IMX_USDHC4_CLK_ROOT,
> +  IMX_SSI1_CLK_ROOT,
> +  IMX_SSI2_CLK_ROOT,
> +  IMX_SSI3_CLK_ROOT,
> +  IMX_GPU2D_AXI_CLK_ROOT,
> +  IMX_GPU3D_AXI_CLK_ROOT,
> +  IMX_PCIE_AXI_CLK_ROOT,
> +  IMX_VDO_AXI_CLK_ROOT,
> +  IMX_IPU1_HSP_CLK_ROOT,
> +  IMX_IPU2_HSP_CLK_ROOT,
> +  IMX_GPU2D_CORE_CLK_ROOT,
> +  IMX_ACLK_EIM_SLOW_CLK_ROOT,
> +  IMX_ACLK_CLK_ROOT,
> +  IMX_ENFC_CLK_ROOT,
> +  IMX_GPU3D_CORE_CLK_ROOT,
> +  IMX_GPU3D_SHADER_CLK_ROOT,
> +  IMX_VPU_AXI_CLK_ROOT,
> +  IMX_IPU1_DI0_CLK_ROOT,
> +  IMX_IPU1_DI1_CLK_ROOT,
> +  IMX_IPU2_DI0_CLK_ROOT,
> +  IMX_IPU2_DI1_CLK_ROOT,
> +  IMX_LDB_DI0_SERIAL_CLK_ROOT,
> +  IMX_LDB_DI0_IPU,
> +  IMX_LDB_DI1_SERIAL_CLK_ROOT,
> +  IMX_LDB_DI1_IPU,
> +  IMX_SPDIF0_CLK_ROOT,
> +  IMX_SPDIF1_CLK_ROOT,
> +  IMX_ESAI_CLK_ROOT,
> +  IMX_HSI_TX_CLK_ROOT,
> +  IMX_CAN_CLK_ROOT,
> +  IMX_ECSPI_CLK_ROOT,
> +  IMX_UART_CLK_ROOT,
> +  IMX_VIDEO_27M_CLK_ROOT,
> +  IMX_CLK_MAX,
> +} IMX_CLK;
> +
> +// Clock gate definitions
> +typedef enum {
> +  IMX_AIPS_TZ1_CLK_ENABLE,
> +  IMX_AIPS_TZ2_CLK_ENABLE,
> +  IMX_APBHDMA_HCLK_ENABLE,
> +  IMX_ASRC_CLK_ENABLE,
> +  IMX_CAAM_SECURE_MEM_CLK_ENABLE,
> +  IMX_CAAM_WRAPPER_ACLK_ENABLE,
> +  IMX_CAAM_WRAPPER_IPG_ENABLE,
> +  IMX_CAN1_CLK_ENABLE,
> +  IMX_CAN1_SERIAL_CLK_ENABLE,
> +  IMX_CAN2_CLK_ENABLE,
> +  IMX_CAN2_SERIAL_CLK_ENABLE,
> +  IMX_ARM_DBG_CLK_ENABLE,
> +  IMX_DCIC1_CLK_ENABLE,
> +  IMX_DCIC2_CLK_ENABLE,
> +  IMX_DTCP_CLK_ENABLE,
> +  IMX_ECSPI1_CLK_ENABLE,
> +  IMX_ECSPI2_CLK_ENABLE,
> +  IMX_ECSPI3_CLK_ENABLE,
> +  IMX_ECSPI4_CLK_ENABLE,
> +  IMX_ECSPI5_CLK_ENABLE,
> +  IMX_ENET_CLK_ENABLE,
> +  IMX_EPIT1_CLK_ENABLE,
> +  IMX_EPIT2_CLK_ENABLE,
> +  IMX_ESAI_CLK_ENABLE,
> +  IMX_GPT_CLK_ENABLE,
> +  IMX_GPT_SERIAL_CLK_ENABLE,
> +  IMX_GPU2D_CLK_ENABLE,
> +  IMX_GPU3D_CLK_ENABLE,
> +  IMX_HDMI_TX_ENABLE,
> +  IMX_HDMI_TX_ISFRCLK_ENABLE,
> +  IMX_I2C1_SERIAL_CLK_ENABLE,
> +  IMX_I2C2_SERIAL_CLK_ENABLE,
> +  IMX_I2C3_SERIAL_CLK_ENABLE,
> +  IMX_IIM_CLK_ENABLE,
> +  IMX_IOMUX_IPT_CLK_IO_ENABLE,
> +  IMX_IPMUX1_CLK_ENABLE,
> +  IMX_IPMUX2_CLK_ENABLE,
> +  IMX_IPMUX3_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPU1_CLK_ENABLE,
> +  IMX_IPU1_DI0_CLK_ENABLE,
> +  IMX_IPU1_DI1_CLK_ENABLE,
> +  IMX_IPU2_CLK_ENABLE,
> +  IMX_IPU2_DI0_CLK_ENABLE,
> +  IMX_IPU2_DI1_CLK_ENABLE,
> +  IMX_LDB_DI0_CLK_ENABLE,
> +  IMX_LDB_DI1_CLK_ENABLE,
> +  IMX_MIPI_CORE_CFG_CLK_ENABLE,
> +  IMX_MLB_CLK_ENABLE,
> +  IMX_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE,
> +  IMX_MMDC_CORE_IPG_CLK_P0_ENABLE,
> +  IMX_OCRAM_CLK_ENABLE,
> +  IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
> +  IMX_PCIE_ROOT_ENABLE,
> +  IMX_PL301_MX6QFAST1_S133CLK_ENABLE,
> +  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
> +  IMX_PL301_MX6QPER2_MAINCLK_ENABLE,
> +  IMX_PWM1_CLK_ENABLE,
> +  IMX_PWM2_CLK_ENABLE,
> +  IMX_PWM3_CLK_ENABLE,
> +  IMX_PWM4_CLK_ENABLE,
> +  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
> +  IMX_ROM_CLK_ENABLE,
> +  IMX_SATA_CLK_ENABLE,
> +  IMX_SDMA_CLK_ENABLE,
> +  IMX_SPBA_CLK_ENABLE,
> +  IMX_SPDIF_CLK_ENABLE,
> +  IMX_SSI1_CLK_ENABLE,
> +  IMX_SSI2_CLK_ENABLE,
> +  IMX_SSI3_CLK_ENABLE,
> +  IMX_UART_CLK_ENABLE,
> +  IMX_UART_SERIAL_CLK_ENABLE,
> +  IMX_USBOH3_CLK_ENABLE,
> +  IMX_USDHC1_CLK_ENABLE,
> +  IMX_USDHC2_CLK_ENABLE,
> +  IMX_USDHC3_CLK_ENABLE,
> +  IMX_USDHC4_CLK_ENABLE,
> +  IMX_EIM_SLOW_CLK_ENABLE,
> +  IMX_VDOAXICLK_CLK_ENABLE,
> +  IMX_VPU_CLK_ENABLE,
> +  IMX_CLK_GATE_MAX,
> +} IMX_CLK_GATE;
> +
> +#endif  /* _IMX6_CLK_PWR_DQ_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
> new file mode 100644
> index 000000000000..d9e0bb1e15a7
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
> @@ -0,0 +1,176 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_CLK_PWR_SDL_H_
> +#define _IMX6_CLK_PWR_SDL_H_
> +
> +// Clock signal definitions for iMX6 Solo and DualLite
> +typedef enum {
> +  IMX_CLK_NONE,
> +  IMX_OSC_CLK,
> +  IMX_PLL1_MAIN_CLK,
> +  IMX_PLL2_MAIN_CLK,
> +  IMX_PLL2_PFD0,
> +  IMX_PLL2_PFD1,
> +  IMX_PLL2_PFD2,
> +  IMX_PLL3_MAIN_CLK,
> +  IMX_PLL3_PFD0,
> +  IMX_PLL3_PFD1,
> +  IMX_PLL3_PFD2,
> +  IMX_PLL3_PFD3,
> +  IMX_PLL4_MAIN_CLK,
> +  IMX_PLL5_MAIN_CLK,
> +  IMX_CLK1,
> +  IMX_CLK2,
> +  IMX_PLL1_SW_CLK,
> +  IMX_STEP_CLK,
> +  IMX_PLL3_SW_CLK,
> +  IMX_AXI_ALT,
> +  IMX_AXI_CLK_ROOT,
> +  IMX_PERIPH_CLK2,
> +  IMX_PERIPH_CLK,
> +  IMX_PRE_PERIPH_CLK,
> +  IMX_PRE_PERIPH2_CLK,
> +  IMX_PERIPH2_CLK,
> +  IMX_ARM_CLK_ROOT,
> +  IMX_MMDC_CH0_CLK_ROOT,
> +  IMX_MMDC_CH1_CLK_ROOT,
> +  IMX_AHB_CLK_ROOT,
> +  IMX_IPG_CLK_ROOT,
> +  IMX_PERCLK_CLK_ROOT,
> +  IMX_USDHC1_CLK_ROOT,
> +  IMX_USDHC2_CLK_ROOT,
> +  IMX_USDHC3_CLK_ROOT,
> +  IMX_USDHC4_CLK_ROOT,
> +  IMX_SSI1_CLK_ROOT,
> +  IMX_SSI2_CLK_ROOT,
> +  IMX_SSI3_CLK_ROOT,
> +  IMX_GPU2D_AXI_CLK_ROOT,
> +  IMX_GPU3D_AXI_CLK_ROOT,
> +  IMX_PCIE_AXI_CLK_ROOT,
> +  IMX_VDO_AXI_CLK_ROOT,
> +  IMX_IPU1_HSP_CLK_ROOT,
> +  IMX_GPU2D_CORE_CLK_ROOT,
> +  IMX_ACLK_EIM_SLOW_CLK_ROOT,
> +  IMX_ACLK_CLK_ROOT,
> +  IMX_ENFC_CLK_ROOT,
> +  IMX_GPU3D_CORE_CLK_ROOT,
> +  IMX_GPU3D_SHADER_CLK_ROOT,
> +  IMX_VPU_AXI_CLK_ROOT,
> +  IMX_IPU1_DI0_CLK_ROOT,
> +  IMX_IPU1_DI1_CLK_ROOT,
> +  IMX_LDB_DI0_SERIAL_CLK_ROOT,
> +  IMX_LDB_DI0_IPU,
> +  IMX_LDB_DI1_SERIAL_CLK_ROOT,
> +  IMX_LDB_DI1_IPU,
> +  IMX_SPDIF0_CLK_ROOT,
> +  IMX_SPDIF1_CLK_ROOT,
> +  IMX_ESAI_CLK_ROOT,
> +  IMX_HSI_TX_CLK_ROOT,
> +  IMX_CAN_CLK_ROOT,
> +  IMX_ECSPI_CLK_ROOT,
> +  IMX_UART_CLK_ROOT,
> +  IMX_VIDEO_27M_CLK_ROOT,
> +  IMX_CLK_MAX,
> +} IMX_CLK;
> +
> +// Clock gate definitions
> +typedef enum {
> +  IMX_AIPS_TZ1_CLK_ENABLE,
> +  IMX_AIPS_TZ2_CLK_ENABLE,
> +  IMX_APBHDMA_HCLK_ENABLE,
> +  IMX_ASRC_CLK_ENABLE,
> +  IMX_CAAM_SECURE_MEM_CLK_ENABLE,
> +  IMX_CAAM_WRAPPER_ACLK_ENABLE,
> +  IMX_CAAM_WRAPPER_IPG_ENABLE,
> +  IMX_CAN1_CLK_ENABLE,
> +  IMX_CAN1_SERIAL_CLK_ENABLE,
> +  IMX_CAN2_CLK_ENABLE,
> +  IMX_CAN2_SERIAL_CLK_ENABLE,
> +  IMX_ARM_DBG_CLK_ENABLE,
> +  IMX_DCIC1_CLK_ENABLE,
> +  IMX_DCIC2_CLK_ENABLE,
> +  IMX_DTCP_CLK_ENABLE,
> +  IMX_ECSPI1_CLK_ENABLE,
> +  IMX_ECSPI2_CLK_ENABLE,
> +  IMX_ECSPI3_CLK_ENABLE,
> +  IMX_ECSPI4_CLK_ENABLE,
> +  IMX_ECSPI5_CLK_ENABLE,
> +  IMX_ENET_CLK_ENABLE,
> +  IMX_EPIT1_CLK_ENABLE,
> +  IMX_EPIT2_CLK_ENABLE,
> +  IMX_ESAI_CLK_ENABLE,
> +  IMX_GPT_CLK_ENABLE,
> +  IMX_GPT_SERIAL_CLK_ENABLE,
> +  IMX_GPU2D_CLK_ENABLE,
> +  IMX_GPU3D_CLK_ENABLE,
> +  IMX_HDMI_TX_ENABLE,
> +  IMX_HDMI_TX_ISFRCLK_ENABLE,
> +  IMX_I2C1_SERIAL_CLK_ENABLE,
> +  IMX_I2C2_SERIAL_CLK_ENABLE,
> +  IMX_I2C3_SERIAL_CLK_ENABLE,
> +  IMX_I2C4_SERIAL_CLK_ENABLE,
> +  IMX_IIM_CLK_ENABLE,
> +  IMX_IOMUX_IPT_CLK_IO_ENABLE,
> +  IMX_IPMUX1_CLK_ENABLE,
> +  IMX_IPMUX2_CLK_ENABLE,
> +  IMX_IPMUX3_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPU1_CLK_ENABLE,
> +  IMX_IPU1_DI0_CLK_ENABLE,
> +  IMX_IPU1_DI1_CLK_ENABLE,
> +  IMX_LDB_DI0_CLK_ENABLE,
> +  IMX_LDB_DI1_CLK_ENABLE,
> +  IMX_MIPI_CORE_CFG_CLK_ENABLE,
> +  IMX_MLB_CLK_ENABLE,
> +  IMX_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE,
> +  IMX_MMDC_CORE_IPG_CLK_P0_ENABLE,
> +  IMX_OCRAM_CLK_ENABLE,
> +  IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
> +  IMX_PCIE_ROOT_ENABLE,
> +  IMX_PL301_MX6QFAST1_S133CLK_ENABLE,
> +  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
> +  IMX_PL301_MX6QPER2_MAINCLK_ENABLE,
> +  IMX_PWM1_CLK_ENABLE,
> +  IMX_PWM2_CLK_ENABLE,
> +  IMX_PWM3_CLK_ENABLE,
> +  IMX_PWM4_CLK_ENABLE,
> +  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
> +  IMX_ROM_CLK_ENABLE,
> +  IMX_SATA_CLK_ENABLE,
> +  IMX_SDMA_CLK_ENABLE,
> +  IMX_SPBA_CLK_ENABLE,
> +  IMX_SPDIF_CLK_ENABLE,
> +  IMX_SSI1_CLK_ENABLE,
> +  IMX_SSI2_CLK_ENABLE,
> +  IMX_SSI3_CLK_ENABLE,
> +  IMX_UART_CLK_ENABLE,
> +  IMX_UART_SERIAL_CLK_ENABLE,
> +  IMX_USBOH3_CLK_ENABLE,
> +  IMX_USDHC1_CLK_ENABLE,
> +  IMX_USDHC2_CLK_ENABLE,
> +  IMX_USDHC3_CLK_ENABLE,
> +  IMX_USDHC4_CLK_ENABLE,
> +  IMX_EIM_SLOW_CLK_ENABLE,
> +  IMX_VDOAXICLK_CLK_ENABLE,
> +  IMX_VPU_CLK_ENABLE,
> +  IMX_CLK_GATE_MAX,
> +} IMX_CLK_GATE;
> +
> +#endif  /* _IMX6_CLK_PWR_SDL_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
> new file mode 100644
> index 000000000000..8b03f5e45b00
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
> @@ -0,0 +1,190 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_CLK_PWR_SX_H_
> +#define _IMX6_CLK_PWR_SX_H_
> +
> +// Clock signal definitions
> +// Figure 19-2 Clock Tree
> +typedef enum {
> +  IMX_CLK_NONE,
> +  IMX_OSC_CLK,
> +  IMX_PLL1_MAIN_CLK,
> +  IMX_PLL2_MAIN_CLK,
> +  IMX_PLL2_PFD0,
> +  IMX_PLL2_PFD1,
> +  IMX_PLL2_PFD2,
> +  IMX_PLL2_PFD3,
> +  IMX_PLL3_MAIN_CLK,
> +  IMX_PLL3_PFD0,
> +  IMX_PLL3_PFD1,
> +  IMX_PLL3_PFD2,
> +  IMX_PLL3_PFD3,
> +  IMX_PLL4_MAIN_CLK,
> +  IMX_PLL5_MAIN_CLK,
> +  IMX_CLK1,
> +  IMX_CLK2,
> +  IMX_PLL1_SW_CLK,
> +  IMX_STEP_CLK,
> +  IMX_PLL3_SW_CLK,
> +  IMX_PERIPH_CLK2,
> +  IMX_PERIPH_CLK,
> +  IMX_PRE_PERIPH_CLK,
> +  IMX_ARM_CLK_ROOT,
> +  IMX_MMDC_CLK_ROOT,
> +  IMX_FABRIC_CLK_ROOT,
> +  IMX_OCRAM_CLK_ROOT,
> +  IMX_PCIE_CLK_ROOT,
> +  IMX_AHB_CLK_ROOT,
> +  IMX_PERCLK_CLK_ROOT,
> +  IMX_IPG_CLK_ROOT,
> +  IMX_USDHC1_CLK_ROOT,
> +  IMX_USDHC2_CLK_ROOT,
> +  IMX_USDHC3_CLK_ROOT,
> +  IMX_USDHC4_CLK_ROOT,
> +  IMX_ACLK_EIM_SLOW_CLK_ROOT,
> +  IMX_GPU_AXI_CLK_ROOT,
> +  IMX_GPU_CORE_CLK_ROOT,
> +  IMX_VID_CLK_ROOT,
> +  IMX_ESAI_CLK_ROOT,
> +  IMX_AUDIO_CLK_ROOT,
> +  IMX_SPDIF0_CLK_ROOT,
> +  IMX_SSI1_CLK_ROOT,
> +  IMX_SSI2_CLK_ROOT,
> +  IMX_SSI3_CLK_ROOT,
> +  IMX_LCDIF2_PIX_CLK_ROOT,
> +  IMX_LCDIF1_PIX_CLK_ROOT,
> +  IMX_LVDS_CLK_ROOT,
> +  IMX_M4_CLK_ROOT,
> +  IMX_ENET_CLK_ROOT,
> +  IMX_QSPI1_CLK_ROOT,
> +  IMX_QSPI2_CLK_ROOT,
> +  IMX_DISPLAY_CLK_ROOT,
> +  IMX_CSI_CLK_ROOT,
> +  IMX_CAN_CLK_ROOT,
> +  IMX_ECSPI_CLK_ROOT,
> +  IMX_UART_CLK_ROOT,
> +  IMX_CLK_MAX,
> +} IMX_CLK;
> +
> +// Clock gate definitions
> +typedef enum {
> +  IMX_AIPS_TZ1_CLK_ENABLE,
> +  IMX_AIPS_TZ2_CLK_ENABLE,
> +  IMX_APBHDMA_HCLK_ENABLE,
> +  IMX_ASRC_CLK_ENABLE,
> +  IMX_CAAM_SECURE_MEM_CLK_ENABLE,
> +  IMX_CAAM_WRAPPER_ACLK_ENABLE,
> +  IMX_CAAM_WRAPPER_IPG_ENABLE,
> +  IMX_CAN1_CLK_ENABLE,
> +  IMX_CAN1_SERIAL_CLK_ENABLE,
> +  IMX_CAN2_CLK_ENABLE,
> +  IMX_CAN2_SERIAL_CLK_ENABLE,
> +  IMX_ARM_DBG_CLK_ENABLE,
> +  IMX_DCIC1_CLK_ENABLE,
> +  IMX_DCIC2_CLK_ENABLE,
> +  IMX_AIPS_TZ3_CLK_ENABLE,
> +  IMX_ECSPI1_CLK_ENABLE,
> +  IMX_ECSPI2_CLK_ENABLE,
> +  IMX_ECSPI3_CLK_ENABLE,
> +  IMX_ECSPI4_CLK_ENABLE,
> +  IMX_ECSPI5_CLK_ENABLE,
> +  IMX_EPIT1_CLK_ENABLE,
> +  IMX_EPIT2_CLK_ENABLE,
> +  IMX_ESAI_CLK_ENABLE,
> +  IMX_WAKEUP_CLK_ENABLE,
> +  IMX_GPT_CLK_ENABLE,
> +  IMX_GPT_SERIAL_CLK_ENABLE,
> +  IMX_GPU_CLK_ENABLE,
> +  IMX_OCRAM_S_CLK_ENABLE,
> +  IMX_CANFD_CLK_ENABLE,
> +  IMX_CSI_CLK_ENABLE,
> +  IMX_I2C1_SERIAL_CLK_ENABLE,
> +  IMX_I2C2_SERIAL_CLK_ENABLE,
> +  IMX_I2C3_SERIAL_CLK_ENABLE,
> +  IMX_IIM_CLK_ENABLE,
> +  IMX_IOMUX_IPT_CLK_IO_ENABLE,
> +  IMX_IPMUX1_CLK_ENABLE,
> +  IMX_IPMUX2_CLK_ENABLE,
> +  IMX_IPMUX3_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
> +  IMX_LCD_CLK_ENABLE,
> +  IMX_PXP_CLK_ENABLE,
> +  IMX_M4_CLK_ENABLE,
> +  IMX_ENET_CLK_ENABLE,
> +  IMX_DISP_AXI_CLK_ENABLE,
> +  IMX_LCDIF2_PIX_CLK_ENABLE,
> +  IMX_LCDIF1_PIX_CLK_ENABLE,
> +  IMX_LDB_DI0_CLK_ENABLE,
> +  IMX_QSPI1_CLK_ENABLE,
> +  IMX_MLB_CLK_ENABLE,
> +  IMX_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE,
> +  IMX_MMDC_CORE_IPG_CLK_P0_ENABLE,
> +  IMX_MMDC_CORE_IPG_CLK_P1_ENABLE,
> +  IMX_OCRAM_CLK_ENABLE,
> +  IMX_PCIE_ROOT_ENABLE,
> +  IMX_QSPI2_CLK_ENABLE,
> +  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
> +  IMX_PL301_MX6QPER2_MAINCLK_ENABLE,
> +  IMX_PWM1_CLK_ENABLE,
> +  IMX_PWM2_CLK_ENABLE,
> +  IMX_PWM3_CLK_ENABLE,
> +  IMX_PWM4_CLK_ENABLE,
> +  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
> +  IMX_ROM_CLK_ENABLE,
> +  IMX_SDMA_CLK_ENABLE,
> +  IMX_SPBA_CLK_ENABLE,
> +  IMX_SPDIF_AND_AUDIO_CLK_ENABLE,
> +  IMX_SSI1_CLK_ENABLE,
> +  IMX_SSI2_CLK_ENABLE,
> +  IMX_SSI3_CLK_ENABLE,
> +  IMX_UART_CLK_ENABLE,
> +  IMX_UART_SERIAL_CLK_ENABLE,
> +  IMX_SAI1_CLK_ENABLE,
> +  IMX_SAI2_CLK_ENABLE,
> +  IMX_USBOH3_CLK_ENABLE,
> +  IMX_USDHC1_CLK_ENABLE,
> +  IMX_USDHC2_CLK_ENABLE,
> +  IMX_USDHC3_CLK_ENABLE,
> +  IMX_USDHC4_CLK_ENABLE,
> +  IMX_EIM_SLOW_CLK_ENABLE,
> +  IMX_PWM8_CLK_ENABLE,
> +  IMX_VADC_CLK_ENABLE,
> +  IMX_GIS_CLK_ENABLE,
> +  IMX_I2C4_SERIAL_CLK_ENABLE,
> +  IMX_PWM5_CLK_ENABLE,
> +  IMX_PWM6_CLK_ENABLE,
> +  IMX_PWM7_CLK_ENABLE,
> +  IMX_CLK_GATE_MAX,
> +} IMX_CLK_GATE;
> +
> +VOID
> +ImxClkPwrLcdClockDisable (
> +  VOID
> +  );
> +
> +VOID
> +ImxClkPwrLcdClockEnable (
> +  VOID
> +  );
> +
> +EFI_STATUS
> +ImxSetLcdIfClockRate (
> +  IN  UINT32  ClockRate
> +  );
> +
> +#endif  /* _IMX6_CLK_PWR_SX_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
> new file mode 100644
> index 000000000000..30c859529a44
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
> @@ -0,0 +1,202 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_IOMUX_H_
> +#define _IMX6_IOMUX_H_
> +
> +//
> +// IOMux common definition
> +//
> +#include <iMXIoMux.h>
> +
> +//
> +// GPIO common definition
> +//
> +#include <iMXGpio.h>
> +
> +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> +#include "iMX6IoMux_DQP.h"
> +#elif defined(CPU_IMX6SX)
> +#include "iMX6IoMux_SX.h"
> +#elif defined(CPU_IMX6SDL)
> +#include "iMX6IoMux_SDL.h"
> +#else
> +#error CPU Preprocessor Flag Not Defined
> +#endif
> +
> +typedef UINT64 IMX_PADCFG;
> +
> +//
> +// Pad control settings
> +//
> +typedef enum {
> +  IMX_HYS_DISABLED,
> +  IMX_HYS_ENABLED,
> +} IMX_HYS;
> +
> +typedef enum {
> +  IMX_PUS_100K_OHM_PD,
> +  IMX_PUS_47K_OHM_PU,
> +  IMX_PUS_100K_OHM_PU,
> +  IMX_PUS_22K_OHM_PU,
> +} IMX_PUS;
> +
> +typedef enum {
> +  IMX_PUE_KEEP,
> +  IMX_PUE_PULL,
> +} IMX_PUE;
> +
> +typedef enum {
> +  IMX_PKE_DISABLE,
> +  IMX_PKE_ENABLE,
> +} IMX_PKE;
> +
> +typedef enum {
> +  IMX_ODE_DISABLE,
> +  IMX_ODE_ENABLE,
> +} IMX_ODE;
> +
> +typedef enum {
> +  IMX_SPEED_LOW,
> +  IMX_SPEED_MEDIUM = 2,
> +  IMX_SPEED_MAXIMUM,
> +} IMX_SPEED;
> +
> +typedef enum {
> +  IMX_DSE_HIZ,
> +  IMX_DSE_260_OHM,
> +  IMX_DSE_130_OHM,
> +  IMX_DSE_90_OHM,
> +  IMX_DSE_60_OHM,
> +  IMX_DSE_50_OHM,
> +  IMX_DSE_40_OHM,
> +  IMX_DSE_33_OHM,
> +} IMX_DSE;
> +
> +typedef enum {
> +  IMX_SRE_SLOW,
> +  IMX_SRE_FAST,
> +} IMX_SRE;
> +
> +typedef enum {
> +  IMX_SION_DISABLED,
> +  IMX_SION_ENABLED,
> +} IMX_IOMUXC_CTL_SION;
> +
> +typedef union {
> +  UINT32 AsUint32;

My brain cannot decide whether it's properly pointed this out in any
patch, or if I just put it in my draft for an earlier file that I then
discarded. Tardy reviewing helps no one :(

Anyway:
Please replace all these "As<type>" with "Raw" or "Data".

> +  struct {
> +    UINT32 SRE : 1;
> +    UINT32 reserved0 : 2;
> +    UINT32 DSE : 3;
> +    UINT32 SPEED : 2;
> +    UINT32 reserved1 : 3;
> +    UINT32 ODE : 1 ;
> +    UINT32 PKE : 1;
> +    UINT32 PUE : 1;
> +    UINT32 PUS : 2;
> +    UINT32 HYS : 1;
> +    UINT32 reserved2 : 15;
> +  } Fields;
> +} IMX_IOMUXC_PAD_CTL;

None of these struct members follow the coding style.
The reserved ones are easy, just -> Reserved*.

For the rest, The abbreviations would appear to violate the coding
style (if not accompanied by a glossary at the start of the file), and
the names should normally be in CamelCase.

Are these the names they are referred to in the documentation?

Every comment I would have on this file follows this pattern, so I'm
stopping here. If we could agree on the way forward for this struct,
the same would apply for the rest of the file.

Regards,

Leif


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 15/27] Silicon/NXP: Add i.MX6 GPT Timer library
  2018-09-21  8:26 ` [PATCH edk2-platforms 15/27] Silicon/NXP: Add i.MX6 GPT Timer library Chris Co
@ 2018-12-13 17:26   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-13 17:26 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:07AM +0000, Chris Co wrote:
> This adds support for GPT Timer on NXP i.MX6 SoCs.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h           |  24 ++
>  Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c   | 246 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf |  45 ++++
>  3 files changed, 315 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h b/Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
> new file mode 100644
> index 000000000000..fbac9d2a61c0
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
> @@ -0,0 +1,24 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_TIMER_H_
> +#define _IMX6_TIMER_H_
> +
> +RETURN_STATUS
> +EFIAPI
> +TimerConstructor (
> +  VOID
> +  );
> +
> +#endif  /* _IMX6_TIMER_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c b/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
> new file mode 100644
> index 000000000000..fa55cee242ef
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
> @@ -0,0 +1,246 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Base.h>
> +#include <Uefi.h>
> +
> +#include <Library/ArmLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include <common_gpt.h>
> +#include <iMX6.h>
> +#include <iMX6Timer.h>
> +
> +RETURN_STATUS
> +EFIAPI
> +TimerConstructor (
> +  VOID
> +  )
> +{
> +  PCSP_GPT_REGS pGpt;
> +  UINT32 FreqPreScale;
> +
> +  pGpt = (PCSP_GPT_REGS)CSP_BASE_REG_PA_GPT;
> +
> +  ASSERT (SOC_OSC_FREQUENCY_REF_HZ >= PcdGet32 (PcdArmArchTimerFreqInHz));

This line strikes me as slightly counterintuitive.
Are you reusing the Arch Timer Pcd for a custom timer?

If this is the case, we should still be able to share some of the code
from the ArmPkg ArmArchTimerLib by breaking it out and sharing it
(like we did with TimeBaseLib).

> +
> +  // Calculate the scale factor since we are using the 24Mhz oscillator
> +  // as reference.
> +  FreqPreScale = SOC_OSC_FREQUENCY_REF_HZ / PcdGet32 (PcdArmArchTimerFreqInHz);
> +  ASSERT (FreqPreScale <= (1 << GPT_PR_PRESCALER_WID));
> +
> +  // Set the frequency scale
> +  MmioWrite32 ((UINTN)&pGpt->PR, FreqPreScale - 1);
> +
> +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> +  // Set GPT configuration:
> +  // - GPT Enabled
> +  // - Use the 24Mhz oscillator source
> +  MmioWrite32 ((UINTN)&pGpt->CR,
> +            (GPT_CR_EN_ENABLE << GPT_CR_EN_LSH) |

Can you do a global search and replace _LSH/_SHIFT?

/
    Leif


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 16/27] Silicon/NXP: Add i.MX6 Timer DXE driver
  2018-09-21  8:26 ` [PATCH edk2-platforms 16/27] Silicon/NXP: Add i.MX6 Timer DXE driver Chris Co
@ 2018-12-13 17:33   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-13 17:33 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:08AM +0000, Chris Co wrote:
> This adds DXE support for EPIT timer on NXP i.MX6 SoCs.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c      | 278 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf |  55 ++++
>  2 files changed, 333 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
> new file mode 100644
> index 000000000000..6b4db6185b48
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
> @@ -0,0 +1,278 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include <Protocol/HardwareInterrupt.h>
> +#include <Protocol/Timer.h>
> +
> +#include <common_epit.h>
> +#include <iMX6.h>
> +
> +// The notification function to call on every timer interrupt.
> +volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY) NULL;
> +EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT) NULL;
> +
> +// Cached copy of the Hardware Interrupt protocol instance
> +EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
> +
> +// Cached interrupt vector
> +volatile UINTN  mVector;
> +UINT64 mCurrentTimerPeriod;
> +
> +EFI_STATUS
> +EFIAPI
> +TimerDriverRegisterHandler (
> +  IN EFI_TIMER_ARCH_PROTOCOL  *This,
> +  IN EFI_TIMER_NOTIFY         NotifyFunction
> +  )
> +{
> +  DEBUG ((DEBUG_VERBOSE, "++TimerDriverRegisterHandler()\n"));

Please use %a and __FUNCTION__ rather than manually typing the
function name. (Throughout the set.)

> +  if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  mTimerNotifyFunction = NotifyFunction;
> +  DEBUG ((DEBUG_VERBOSE, "--TimerDriverRegisterHandler()=ok\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +TimerDriverSetTimerPeriod (
> +  IN EFI_TIMER_ARCH_PROTOCOL  *This,
> +  IN UINT64                   TimerPeriod
> +  )
> +{
> +  PCSP_EPIT_REG   pEpit;
> +  UINT16          EpitPreScalar;
> +  EFI_STATUS      Status;
> +  UINT32          TimerCount;
> +  UINT32          Value;
> +
> +  DEBUG ((DEBUG_VERBOSE, "++TimerDriverSetTimerPeriod(%d)\n", TimerPeriod));
> +
> +  pEpit = (PCSP_EPIT_REG) CSP_BASE_REG_PA_EPIT1;
> +  DEBUG ((DEBUG_VERBOSE,
> +          "TimerDriverSetTimerPeriod() disable timer. EPIT_REG adr=%p\n", pEpit));
> +
> +  // First stop the timer.
> +  Value = MmioRead32 ((UINTN)&pEpit->CR);
> +  Value &= ~(((1 << EPIT_CR_EN_WID) - 1) << EPIT_CR_EN_LSH);

Just to clarify comment from last email: I did mean global
search/replace on _LSH to _SHIFT for the entire set.

> +  Value |= (EPIT_CR_EN_DISABLE << EPIT_CR_EN_LSH);
> +  MmioWrite32 ((UINTN)&pEpit->CR, Value);
> +
> +  if (TimerPeriod == 0) {
> +    Status = gInterrupt->DisableInterruptSource (gInterrupt, mVector);
> +    mCurrentTimerPeriod = 0;
> +    DEBUG ((DEBUG_VERBOSE, "--TimerDriverSetTimerPeriod() Timer Disabled\n"));
> +    return Status;
> +  }
> +
> +  // Configure EPIT to be sourced from iMX6 24 MHz crystal oscialltor
> +  // Aim to have UEFI tick counting at 1 MHz clock or another frequency as set in pcd
> +  EpitPreScalar = 68;

That 68 needs a #define.

> +  DEBUG ((DEBUG_VERBOSE,
> +          "TimerDriverSetTimerPeriod() using corrected EPIT prescalar=%d\n",
> +          EpitPreScalar));
> +
> +  MmioWrite32 ((UINTN)&pEpit->CR,
> +            (EPIT_CR_ENMOD_LOAD << EPIT_CR_ENMOD_LSH) |
> +            (EPIT_CR_OCIEN_ENABLE << EPIT_CR_OCIEN_LSH) |
> +            (EPIT_CR_RLD_RELOAD << EPIT_CR_RLD_LSH) |
> +            ((EpitPreScalar - 1) << EPIT_CR_PRESCALAR_LSH) |
> +            (EPIT_CR_SWR_NORESET << EPIT_CR_SWR_LSH) |
> +            (EPIT_CR_IOVW_OVR << EPIT_CR_IOVW_LSH) |
> +            (EPIT_CR_DBGEN_ACTIVE << EPIT_CR_DBGEN_LSH) |
> +            (EPIT_CR_WAITEN_ENABLE << EPIT_CR_WAITEN_LSH) |
> +            (EPIT_CR_DOZEN_ENABLE << EPIT_CR_DOZEN_LSH) |
> +            (EPIT_CR_STOPEN_ENABLE << EPIT_CR_STOPEN_LSH) |
> +            (EPIT_CR_OM_DICONNECT << EPIT_CR_OM_LSH) |
> +            (EPIT_CR_CLKSRC_IPGCLK << EPIT_CR_CLKSRC_LSH));
> +
> +  // Clear timer compare interrupt flag (write-1-clear)
> +  MmioWrite32 ((UINTN)&pEpit->SR, ((1 << EPIT_SR_OCIF_WID) - 1) << EPIT_SR_OCIF_LSH);
> +  TimerCount = (UINT32) (TimerPeriod / 10);
> +  if ((UINT64)TimerCount > (UINT64)0xffffffff) {
> +    TimerCount = 0xffffffff;

MAX_UINT32?

/
    Leif

> +  }
> +
> +  mCurrentTimerPeriod = TimerPeriod;
> +  MmioWrite32 ((UINTN)&pEpit->CMPR, TimerCount);
> +  MmioWrite32 ((UINTN)&pEpit->LR, TimerCount);
> +  Status = gInterrupt->EnableInterruptSource (gInterrupt, mVector);
> +
> +  // Turn the timer on
> +  Value = MmioRead32 ((UINTN)&pEpit->CR);
> +  Value &= ~(((1 << EPIT_CR_EN_WID) - 1) << EPIT_CR_EN_LSH);
> +  Value |= EPIT_CR_EN_ENABLE << EPIT_CR_EN_LSH;
> +  MmioWrite32 ((UINTN)&pEpit->CR, Value);
> +
> +  DEBUG ((DEBUG_VERBOSE, "--TimerDriverSetTimerPeriod(%d)=%Xh\n", TimerPeriod,
> +          Status));
> +  return Status;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +TimerDriverGetTimerPeriod (
> +  IN EFI_TIMER_ARCH_PROTOCOL   *This,
> +  OUT UINT64                   *TimerPeriod
> +  )
> +{
> +  *TimerPeriod = mCurrentTimerPeriod;
> +  DEBUG ((DEBUG_VERBOSE, "+-TimerDriverGetTimerPeriod(%d)=ok\n",
> +          mCurrentTimerPeriod));
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +EFIAPI
> +TimerInterruptHandler (
> +  IN  HARDWARE_INTERRUPT_SOURCE   Source,
> +  IN  EFI_SYSTEM_CONTEXT          SystemContext
> +  )
> +{
> +  EFI_TPL OriginalTPL;
> +  PCSP_EPIT_REG pEpit;
> +
> +  pEpit = (PCSP_EPIT_REG) CSP_BASE_REG_PA_EPIT1;
> +
> +  // DXE core uses this callback for the EFI timer tick. The DXE core uses locks
> +  // that raise to TPL_HIGH and then restore back to current level. Thus we need
> +  // to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
> +  OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +
> +  // Check if the timer interrupt is active
> +  if (MmioRead32 ((UINTN)&pEpit->SR) != 0) {
> +    // Acknowledge the EPIT interrupt
> +    MmioWrite32 ((UINTN)&pEpit->SR, 0x1);
> +
> +    // Signal EOI to avoid losing subsequent ticks from long duration handlers
> +    gInterrupt->EndOfInterrupt (gInterrupt, Source);
> +
> +    if (mTimerNotifyFunction) {
> +      mTimerNotifyFunction (mCurrentTimerPeriod);
> +    }
> +  }
> +
> +  gBS->RestoreTPL (OriginalTPL);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +TimerDriverGenerateSoftInterrupt (
> +  IN EFI_TIMER_ARCH_PROTOCOL  *This
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_TIMER_ARCH_PROTOCOL gTimer = {
> +  TimerDriverRegisterHandler,
> +  TimerDriverSetTimerPeriod,
> +  TimerDriverGetTimerPeriod,
> +  TimerDriverGenerateSoftInterrupt
> +};
> +
> +VOID
> +EFIAPI
> +ExitBootServicesEvent (
> +  IN EFI_EVENT  Event,
> +  IN VOID       *Context
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  DEBUG ((DEBUG_INFO, "Disabling EPIT timer on ExitBootServicesEvent"));
> +
> +  // Disable the timer
> +  Status = TimerDriverSetTimerPeriod (&gTimer, 0);
> +  ASSERT_EFI_ERROR (Status);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +TimerInitialize (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +)
> +{
> +  EFI_HANDLE  Handle;
> +  EFI_STATUS  Status;
> +  DEBUG ((DEBUG_VERBOSE, "++TimerInitialize()\n"));
> +
> +  Handle = NULL;
> +  mVector = IRQ_EPIT1;
> +
> +  // Find the interrupt controller protocol.
> +  Status = gBS->LocateProtocol (
> +             &gHardwareInterruptProtocolGuid,
> +             NULL,
> +             (VOID **) &gInterrupt);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  // Disable the timer
> +  Status = TimerDriverSetTimerPeriod (&gTimer, 0);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  // Install interrupt handler
> +  Status = gInterrupt->RegisterInterruptSource (gInterrupt, mVector,
> +           TimerInterruptHandler);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  // Set up default timer
> +  Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32 (PcdTimerPeriod));
> +  ASSERT_EFI_ERROR (Status);
> +
> +  DEBUG ((
> +           DEBUG_VERBOSE,
> +           "EPIT Timer initialized to default period %d x 100ns ~ %dms\n",
> +           FixedPcdGet32 (PcdTimerPeriod),
> +           FixedPcdGet32 (PcdTimerPeriod) / 10000));
> +
> +  // Install the Timer Architectural Protocol onto a new handle
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +             &Handle,
> +             &gEfiTimerArchProtocolGuid,
> +             &gTimer,
> +             NULL);
> +
> +  ASSERT_EFI_ERROR (Status);
> +
> +  // Register for ExitBootServicesEvent
> +  Status = gBS->CreateEvent (
> +             EVT_SIGNAL_EXIT_BOOT_SERVICES,
> +             TPL_NOTIFY,
> +             ExitBootServicesEvent,
> +             NULL,
> +             &EfiExitBootServicesEvent);
> +
> +  ASSERT_EFI_ERROR (Status);
> +
> +  DEBUG ((DEBUG_VERBOSE, "--TimerInitialize()\n"));
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
> new file mode 100644
> index 000000000000..adcc158e29ab
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
> @@ -0,0 +1,55 @@
> +#/** @file
> +#
> +#  Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  All rights reserved. This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = iMX6TimerDxe
> +  FILE_GUID                      = 7CAF576F-F1D9-4104-A922-CB64537FD7AE
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = TimerInitialize
> +
> +[Sources.common]
> +  Timer.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  IoLib
> +  PerformanceLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  UefiRuntimeServicesTableLib
> +
> +[Guids]
> +
> +[Protocols]
> +  gEfiTimerArchProtocolGuid
> +  gHardwareInterruptProtocolGuid
> +
> +[Pcd.common]
> +  gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds
> +  gEmbeddedTokenSpaceGuid.PcdTimerPeriod
> +
> +[Depex]
> +  gHardwareInterruptProtocolGuid
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 17/27] Silicon/NXP: Add i.MX6 USB Phy Library
  2018-09-21  8:26 ` [PATCH edk2-platforms 17/27] Silicon/NXP: Add i.MX6 USB Phy Library Chris Co
@ 2018-12-14 17:10   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 17:10 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:09AM +0000, Chris Co wrote:
> This adds support for configuring the USB EHCI PHY on NXP i.MX6 SoCs.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h                    |  20 ++
>  Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c      | 328 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf |  43 +++
>  3 files changed, 391 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h b/Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
> new file mode 100644
> index 000000000000..153c5461a6ad
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
> @@ -0,0 +1,20 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_USB_PHY_H_
> +#define _IMX6_USB_PHY_H_
> +
> +EFI_STATUS ImxUsbPhyInit (IMX_USBPHY_ID ImxUsbPhyId);
> +
> +#endif // _IMX6_USB_PHY_H_
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
> new file mode 100644
> index 000000000000..317d17d14844
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
> @@ -0,0 +1,328 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6IoMux.h>
> +#include <iMX6UsbPhy.h>
> +
> +#define USB_PHY_PLL_LOCK_TIMEOUT_USEC (UINT32)(1000*1000)
> +#define USB_EHCI_STOP_RESET_TIMEOUT_USEC (UINT32)(1000*1000)
> +
> +#define IMX_CCM_ANALOG_PLL_USB1_REG_LOCK 0x80000000
> +#define IMX_USB_CMD_REG_RUN 0x00000001
> +#define IMX_USB_CMD_REG_RESET 0x00000002
> +
> +/**
> +  Wait for a register bit to be on/off
> +**/
> +EFI_STATUS
> +RegisterWaitBit (
> +  IN  volatile VOID   *RegisterAddr,

Why volatile?

> +  IN  UINT32          Mask,
> +  IN  BOOLEAN         IsWaitOn,
> +  IN  UINT32          TimeOutUsec

Could just be called MicroSeconds (would match elsewhere in edk2).

> +  )
> +{
> +  UINT32 RegisterValue;
> +  UINT32 TimeUsec;

TimeWaited?

> +
> +  TimeUsec = 0;
> +  do {
> +    RegisterValue = MmioRead32 ((UINTN)RegisterAddr) & Mask;
> +    if (((RegisterValue == Mask) && IsWaitOn) || ((RegisterValue == 0)
> +        && !IsWaitOn)) {

Could you re-break this line to keep either side of || together and
aligned horizontally?

> +      return EFI_SUCCESS;
> +    }
> +
> +    MicroSecondDelay (10);
> +    TimeUsec += 10;
> +  } while (TimeUsec < TimeOutUsec);
> +
> +  return EFI_TIMEOUT;
> +}
> +
> +/**
> +  Turn on the 480Mhz PLL
> +**/
> +EFI_STATUS
> +ImxUsbPhyEnablePll (
> +  IN  IMX_USBPHY_ID   ImxUsbPhyId
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS     *CcmAnaRegsPtr;
> +  volatile IMX_CCM_ANALOG_PLL_USB1_REG  *PllUsbClrRegPtr;
> +  volatile IMX_CCM_ANALOG_PLL_USB1_REG  *PllUsbSetRegPtr;

I am very confused by these. Three volatile pointers are created and
never used to access anything directly.
You can drop the volatile on all three, and the latter two would make
more sense as UINTN.

> +  IMX_CCM_ANALOG_PLL_USB1_REG           PllUsbClrReg;
> +  IMX_CCM_ANALOG_PLL_USB1_REG           PllUsbSetReg;
> +  EFI_STATUS                            Status;
> +
> +  CcmAnaRegsPtr = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
> +
> +  switch (ImxUsbPhyId) {
> +  case IMX_USBPHY0:
> +    PllUsbClrRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB1_CLR;
> +    PllUsbSetRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB1_SET;
> +    break;
> +  case IMX_USBPHY1:
> +    PllUsbClrRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB2_CLR;
> +    PllUsbSetRegPtr = (IMX_CCM_ANALOG_PLL_USB1_REG *)&CcmAnaRegsPtr->PLL_USB2_SET;
> +    break;
> +  default:
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PllUsbClrReg.AsUint32 = 0;
> +  PllUsbClrReg.BYPASS = 1;
> +  MmioWrite32 ((UINTN)PllUsbClrRegPtr, PllUsbClrReg.AsUint32);
> +
> +  PllUsbSetReg.AsUint32 = 0;
> +  PllUsbSetReg.EN_USB_CLKS = 1;
> +  PllUsbSetReg.POWER = 1;
> +  PllUsbSetReg.ENABLE = 1;
> +  MmioWrite32 ((UINTN)PllUsbSetRegPtr, PllUsbSetReg.AsUint32);
> +
> +  // Wait for PLL to lock
> +  Status = RegisterWaitBit (
> +             PllUsbSetRegPtr,
> +             IMX_CCM_ANALOG_PLL_USB1_REG_LOCK,
> +             TRUE,
> +             USB_PHY_PLL_LOCK_TIMEOUT_USEC);
> +
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "PLL 480Mhz failed to lock for PHY %d\n",
> +            (UINT32)ImxUsbPhyId));
> +    // On failure disable the PHY
> +    PllUsbClrReg.AsUint32 = 0;
> +    PllUsbSetReg.EN_USB_CLKS = 1;
> +    PllUsbSetReg.POWER = 1;
> +    PllUsbSetReg.ENABLE = 1;
> +    MmioWrite32 ((UINTN)PllUsbClrRegPtr, PllUsbSetReg.AsUint32);
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Reset the EHCI controller associated with the given PHY.
> +**/
> +EFI_STATUS
> +ImxUsbEhciResetController (
> +  IN  IMX_USBPHY_ID   ImxUsbPhyId
> +  )
> +{
> +  volatile USB_USBCMD_REG   *UsbCmdRegPtr;
> +  volatile USB_USBMODE_REG  *UsbModeRegPtr;

Again, volatile with no function. Please address this antipattern
throughout: drop volatile, hold addresses as UINTN. (Oh, and
Ptr->Address.)

> +  EFI_STATUS                Status;
> +  USB_USBCMD_REG            UsbCmdReg;
> +  USB_USBMODE_REG           UsbModeReg;
> +
> +  switch (ImxUsbPhyId) {
> +  case IMX_USBPHY0:
> +    UsbCmdRegPtr = (USB_USBCMD_REG *) (IMX_USBCORE_BASE + IMX_USBCORE_LENGTH * 0 +
> +                                       IMX_USBCMD_OFFSET);
> +    break;
> +  case IMX_USBPHY1:
> +    UsbCmdRegPtr = (USB_USBCMD_REG *) (IMX_USBCORE_BASE + IMX_USBCORE_LENGTH * 1 +
> +                                       IMX_USBCMD_OFFSET);
> +    break;
> +  default:
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // The host controller can only be reset when it is stopped.
> +  UsbCmdReg.AsUint32 = MmioRead32 ((UINTN)UsbCmdRegPtr);
> +  UsbCmdReg.RS = 0;
> +  MmioWrite32 ((UINTN)UsbCmdRegPtr, UsbCmdReg.AsUint32);
> +
> +  // Wait for controller to stop
> +  Status = RegisterWaitBit (
> +             UsbCmdRegPtr,
> +             IMX_USB_CMD_REG_RUN,
> +             FALSE,
> +             USB_EHCI_STOP_RESET_TIMEOUT_USEC);
> +  if (Status != EFI_SUCCESS) {
> +    ASSERT_EFI_ERROR (Status);
> +    DEBUG ((DEBUG_ERROR, "Failed to stop EHCI controller (PHY %d)\n",
> +            (UINT32)ImxUsbPhyId));
> +    return Status;
> +  }
> +
> +  // Reset the controller
> +  UsbCmdReg.AsUint32 = MmioRead32 ((UINTN)UsbCmdRegPtr);
> +  UsbCmdReg.RST = 1;
> +  MmioWrite32 ((UINTN)UsbCmdRegPtr, UsbCmdReg.AsUint32);
> +
> +  // Wait for controller reset to complete
> +  Status = RegisterWaitBit (
> +             UsbCmdRegPtr,
> +             IMX_USB_CMD_REG_RESET,
> +             FALSE,
> +             USB_EHCI_STOP_RESET_TIMEOUT_USEC);
> +
> +  if (Status != EFI_SUCCESS) {
> +    ASSERT_EFI_ERROR (Status);
> +    DEBUG ((DEBUG_ERROR, "Failed to reset EHCI controller (PHY %d)\n",
> +            (UINT32)ImxUsbPhyId));
> +    return Status;
> +  }
> +
> +  // Force OTG port into Host mode. We have seen that ID_PIN can be
> +  // unreliable in some board designs (e.g. SABRESED).
> +  // If the OTG port is not forced into Host mode, the USB stack fails to
> +  // start.
> +  if (ImxUsbPhyId == IMX_USBPHY0) {
> +    DEBUG ((DEBUG_INFO, "Switching USB OTG Port to Host\n"));
> +
> +    UsbModeRegPtr = (USB_USBMODE_REG *) (IMX_USBCORE_BASE + IMX_USBMODE_OFFSET);
> +    UsbModeReg.AsUint32 = MmioRead32 ((UINTN)UsbModeRegPtr);
> +    UsbModeReg.CM = IMX_USBMODE_HOST;
> +    MmioWrite32 ((UINTN)UsbModeRegPtr, UsbModeReg.AsUint32);
> +
> +    UsbModeReg.AsUint32 = MmioRead32 ((UINTN)UsbModeRegPtr);
> +    ASSERT (UsbModeReg.CM == IMX_USBMODE_HOST);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Initialize a USB PHY
> +**/
> +EFI_STATUS
> +ImxUsbPhyInit (
> +  IN  IMX_USBPHY_ID   ImxUsbPhyId
> +  )
> +{
> +  volatile IMX_USBANA_REGISTERS       *UsbAnaRegsPtr;
> +  volatile IMX_USBANA_USB_REGISTERS   *UsbAnaUsbRegsPtr;
> +  volatile USBNC_USB_UH_CTRL_REG      *UsbNcUhCtrlRegPtr;
> +  volatile IMX_USBNONCORE_REGISTERS   *UsbNonCoreRegPtr;
> +  volatile IMX_USBPHY_REGISTERS       *UsbPhyRegsPtr;
> +  EFI_STATUS                          Status;
> +  USB_ANALOG_USB_CHRG_DETECT_REG      UsbAnaChrgDetReg;
> +  USB_ANALOG_USB_MISC_REG             UsbAnaMicReg;
> +  USBNC_USB_UH_CTRL_REG               UsbNcHcCtrlReg;
> +  USBPHYx_CTRL_REG                    UsbPhyCtrlReg;
> +
> +  UsbAnaRegsPtr = (IMX_USBANA_REGISTERS *)IMX_USBANA_BASE;
> +  UsbNonCoreRegPtr = (IMX_USBNONCORE_REGISTERS *)IMX_USBNONCORE_BASE;
> +
> +  switch (ImxUsbPhyId) {
> +  case IMX_USBPHY0:
> +    UsbPhyRegsPtr = (IMX_USBPHY_REGISTERS *)IMX_USBPHY1_BASE;
> +    UsbAnaUsbRegsPtr = &UsbAnaRegsPtr->USBANA[0];
> +    UsbNcUhCtrlRegPtr = (USBNC_USB_UH_CTRL_REG *)
> +                        &UsbNonCoreRegPtr->USBNC_USB_OTG_CTRL;
> +    break;
> +  case IMX_USBPHY1:
> +    UsbPhyRegsPtr = (IMX_USBPHY_REGISTERS *)IMX_USBPHY2_BASE;
> +    UsbAnaUsbRegsPtr = &UsbAnaRegsPtr->USBANA[1];
> +    UsbNcUhCtrlRegPtr = (USBNC_USB_UH_CTRL_REG *)
> +                        &UsbNonCoreRegPtr->USBNC_USB_UH1_CTRL;
> +    break;
> +  default:
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // USB power configuration:
> +  // Set power polarity
> +  UsbNcHcCtrlReg.AsUint32 = MmioRead32 ((UINTN)UsbNcUhCtrlRegPtr);
> +  UsbNcHcCtrlReg.PWR_POL = 1;
> +  UsbNcHcCtrlReg.AsUint32 |= 0x2;     // Reserved bit

Urgh! Please don't do this. If we're doing bitfield structs, let's do
them consistently. Using the full 32-bit union alias to zero or read
is fine, but oring things into it is too much.

> +  MmioWrite32 ((UINTN)UsbNcUhCtrlRegPtr, UsbNcHcCtrlReg.AsUint32);
> +
> +  // Disable external USB charger detector
> +  UsbAnaChrgDetReg.AsUint32 = 0;
> +  UsbAnaChrgDetReg.EN_B = 1;
> +  UsbAnaChrgDetReg.CHK_CHRG_B = 1;
> +  MmioWrite32 ((UINTN)&UsbAnaUsbRegsPtr->USB_ANALOG_USB_CHRG_DETECT_SET,
> +                UsbAnaChrgDetReg.AsUint32);
> +
> +  // Enable the 480Mhz PLL
> +  Status = ImxUsbPhyEnablePll (ImxUsbPhyId);
> +  if (Status != EFI_SUCCESS) {
> +    ASSERT_EFI_ERROR (Status);
> +    DEBUG ((DEBUG_ERROR, "Failed to enable PLL 480Mhz failed for PHY %d\n",
> +            (UINT32)ImxUsbPhyId));
> +    return Status;
> +  }
> +
> +  // Configure Over Current
> +  UsbNcHcCtrlReg.AsUint32 = MmioRead32 ((UINTN)UsbNcUhCtrlRegPtr);
> +  UsbNcHcCtrlReg.OVER_CUR_POL = 0;
> +  UsbNcHcCtrlReg.OVER_CUR_DIS = 1;
> +  MmioWrite32 ((UINTN)UsbNcUhCtrlRegPtr, UsbNcHcCtrlReg.AsUint32);
> +
> +  // Enable USBH PHY clock
> +  UsbPhyCtrlReg.AsUint32 = 0;
> +  UsbPhyCtrlReg.CLKGATE = 1;
> +  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_CLR, UsbPhyCtrlReg.AsUint32);
> +  MicroSecondDelay (10);
> +
> +  // Enable clock to UTMI block
> +  UsbAnaMicReg.AsUint32 = 0;
> +  UsbAnaMicReg.EN_CLK_UTMI = 1;
> +  MmioWrite32 ((UINTN)&UsbAnaUsbRegsPtr->USB_ANALOG_USB_MISC_SET,
> +                UsbAnaMicReg.AsUint32);
> +  MicroSecondDelay (10);
> +
> +  // Enable USBH PHY
> +  // Reset the associated EHCI controller
> +  Status = ImxUsbEhciResetController (ImxUsbPhyId);
> +  if (Status != EFI_SUCCESS) {
> +    return Status;
> +  }
> +
> +  // Reset the PHY
> +  UsbPhyCtrlReg.AsUint32 = 0;
> +  UsbPhyCtrlReg.SFTRST = 1;
> +  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_SET, UsbPhyCtrlReg.AsUint32);
> +  MicroSecondDelay (10);
> +
> +  UsbPhyCtrlReg.AsUint32 = 0;
> +  UsbPhyCtrlReg.SFTRST = 1;
> +  UsbPhyCtrlReg.CLKGATE = 1;
> +  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_CLR, UsbPhyCtrlReg.AsUint32);
> +  MicroSecondDelay (10);
> +
> +  // Power UP the PHY
> +  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_PWD, 0);
> +
> +  // Apply PHY configuration:
> +  // - Enable low/full speed devices.
> +  UsbPhyCtrlReg.AsUint32 = 0;
> +#if defined(CPU_IMX6DQ)
> +  UsbPhyCtrlReg.ENAUTOSET_USBCLKS = 1;
> +  UsbPhyCtrlReg.ENAUTOCLR_USBCLKGATE = 1;
> +  UsbPhyCtrlReg.ENAUTO_PWRON_PLL = 1;
> +#endif
> +  UsbPhyCtrlReg.ENAUTOCLR_PHY_PWD = 1;
> +  UsbPhyCtrlReg.ENAUTOCLR_CLKGATE = 1;
> +  UsbPhyCtrlReg.ENUTMILEVEL2 = 1;
> +  UsbPhyCtrlReg.ENUTMILEVEL3 = 1;
> +  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_CTRL_SET, UsbPhyCtrlReg.AsUint32);
> +#if defined(CPU_IMX6DQ)
> +  MmioWrite32 ((UINTN)&UsbPhyRegsPtr->USBPHY_IP_SET, IMX_USBPHY_IP_FIX);
> +#endif
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
> new file mode 100644
> index 000000000000..30f9f1862747
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
> @@ -0,0 +1,43 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005

I probably commented on some other .inf somewhere, but in case I
didn't - try to bring all of these up to 0x0001001A.

> +  BASE_NAME                      = iMX6UsbPhyLib
> +  FILE_GUID                      = 463989D1-27DC-4AE7-92AE-C7E28C1C605D
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = iMX6UsbPhyLib
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec

Please sort these packages alphabetically.

/
    Leif

> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  IoLib
> +  TimerLib
> +  iMXIoMuxLib
> +
> +[Sources.common]
> +  iMX6UsbPhy.c
> +
> +[FixedPcd]
> +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library
  2018-09-21  8:26 ` [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library Chris Co
@ 2018-12-14 18:12   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 18:12 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:11AM +0000, Chris Co wrote:
> This adds support for managing clocks on NXP i.MX6 SoC. It will
> manipulate the Clock Gating registers (CCGR).
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c         | 1876 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf    |   46 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h |  221 +++
>  3 files changed, 2143 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
> new file mode 100644
> index 000000000000..07958b1e392d
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
> @@ -0,0 +1,1876 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include "iMX6ClkPwr_private.h"
> +
> +static IMX_CLOCK_TREE_CACHE mImxpClockPwrCache;   // Cached clock value

STATIC

> +
> +STATIC CONST IMX_CCGR_INDEX ImxpCcgrIndexMap[] = {

Add m-prefix.

> +  {0, 0},  // MX6_AIPS_TZ1_CLK_ENABLE
> +  {0, 1},  // MX6_AIPS_TZ2_CLK_ENABLE
> +  {0, 2},  // MX6_APBHDMA_HCLK_ENABLE
> +  {0, 3},  // MX6_ASRC_CLK_ENABLE
> +  {0, 4},  // MX6_CAAM_SECURE_MEM_CLK_ENABLE
> +  {0, 5},  // MX6_CAAM_WRAPPER_ACLK_ENABLE
> +  {0, 6},  // MX6_CAAM_WRAPPER_IPG_ENABLE
> +  {0, 7},  // MX6_CAN1_CLK_ENABLE
> +  {0, 8},  // MX6_CAN1_SERIAL_CLK_ENABLE
> +  {0, 9},  // MX6_CAN2_CLK_ENABLE
> +  {0, 10}, // MX6_CAN2_SERIAL_CLK_ENABLE
> +  {0, 11}, // MX6_ARM_DBG_CLK_ENABLE
> +  {0, 12}, // MX6_DCIC1_CLK_ENABLE
> +  {0, 13}, // MX6_DCIC2_CLK_ENABLE
> +  {0, 14}, // MX6_DTCP_CLK_ENABLE
> +  {1, 0},  // MX6_ECSPI1_CLK_ENABLE
> +  {1, 1},  // MX6_ECSPI2_CLK_ENABLE
> +  {1, 2},  // MX6_ECSPI3_CLK_ENABLE
> +  {1, 3},  // MX6_ECSPI4_CLK_ENABLE
> +  {1, 4},  // MX6_ECSPI5_CLK_ENABLE
> +  {1, 5},  // MX6_ENET_CLK_ENABLE
> +  {1, 6},  // MX6_EPIT1_CLK_ENABLE
> +  {1, 7},  // MX6_EPIT2_CLK_ENABLE
> +  {1, 8},  // MX6_ESAI_CLK_ENABLE
> +  {1, 10}, // MX6_GPT_CLK_ENABLE
> +  {1, 11}, // MX6_GPT_SERIAL_CLK_ENABLE
> +  {1, 12}, // MX6_GPU2D_CLK_ENABLE
> +  {1, 13}, // MX6_GPU3D_CLK_ENABLE
> +  {2, 0},  // MX6_HDMI_TX_ENABLE
> +  {2, 2},  // MX6_HDMI_TX_ISFRCLK_ENABLE
> +  {2, 3},  // MX6_I2C1_SERIAL_CLK_ENABLE
> +  {2, 4},  // MX6_I2C2_SERIAL_CLK_ENABLE
> +  {2, 5},  // MX6_I2C3_SERIAL_CLK_ENABLE
> +  {2, 6},  // MX6_IIM_CLK_ENABLE
> +  {2, 7},  // MX6_IOMUX_IPT_CLK_IO_ENABLE
> +  {2, 8},  // MX6_IPMUX1_CLK_ENABLE
> +  {2, 9},  // MX6_IPMUX2_CLK_ENABLE
> +  {2, 10}, // MX6_IPMUX3_CLK_ENABLE
> +  {2, 11}, // MX6_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE
> +  {2, 12}, // MX6_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE
> +  {2, 13}, // MX6_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE
> +  {3, 0},  // MX6_IPU1_IPU_CLK_ENABLE
> +  {3, 1},  // MX6_IPU1_IPU_DI0_CLK_ENABLE
> +  {3, 2},  // MX6_IPU1_IPU_DI1_CLK_ENABLE
> +  {3, 3},  // MX6_IPU2_IPU_CLK_ENABLE
> +  {3, 4},  // MX6_IPU2_IPU_DI0_CLK_ENABLE
> +  {3, 5},  // MX6_IPU2_IPU_DI1_CLK_ENABLE
> +  {3, 6},  // MX6_LDB_DI0_CLK_ENABLE
> +  {3, 7},  // MX6_LDB_DI1_CLK_ENABLE
> +  {3, 8},  // MX6_MIPI_CORE_CFG_CLK_ENABLE
> +  {3, 9},  // MX6_MLB_CLK_ENABLE
> +  {3, 10}, // MX6_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE
> +  {3, 12}, // MX6_MMDC_CORE_IPG_CLK_P0_ENABLE
> +  {3, 14}, // MX6_OCRAM_CLK_ENABLE
> +  {3, 15}, // MX6_OPENVGAXICLK_CLK_ROOT_ENABLE
> +  {4, 0},  // MX6_PCIE_ROOT_ENABLE
> +  {4, 4},  // MX6_PL301_MX6QFAST1_S133CLK_ENABLE
> +  {4, 6},  // MX6_PL301_MX6QPER1_BCHCLK_ENABLE
> +  {4, 7},  // MX6_PL301_MX6QPER2_MAINCLK_ENABLE
> +  {4, 8},  // MX6_PWM1_CLK_ENABLE
> +  {4, 9},  // MX6_PWM2_CLK_ENABLE
> +  {4, 10}, // MX6_PWM3_CLK_ENABLE
> +  {4, 11}, // MX6_PWM4_CLK_ENABLE
> +  {4, 12}, // MX6_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE
> +  {4, 13}, // MX6_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE
> +  {4, 14}, // MX6_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE
> +  {4, 15}, // MX6_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE
> +  {5, 0},  // MX6_ROM_CLK_ENABLE
> +  {5, 2},  // MX6_SATA_CLK_ENABLE
> +  {5, 3},  // MX6_SDMA_CLK_ENABLE
> +  {5, 6},  // MX6_SPBA_CLK_ENABLE
> +  {5, 7},  // MX6_SPDIF_CLK_ENABLE
> +  {5, 9},  // MX6_SSI1_CLK_ENABLE
> +  {5, 10}, // MX6_SSI2_CLK_ENABLE
> +  {5, 11}, // MX6_SSI3_CLK_ENABLE
> +  {5, 12}, // MX6_UART_CLK_ENABLE
> +  {5, 13}, // MX6_UART_SERIAL_CLK_ENABLE
> +  {6, 0},  // MX6_USBOH3_CLK_ENABLE
> +  {6, 1},  // MX6_USDHC1_CLK_ENABLE
> +  {6, 2},  // MX6_USDHC2_CLK_ENABLE
> +  {6, 3},  // MX6_USDHC3_CLK_ENABLE
> +  {6, 4},  // MX6_USDHC4_CLK_ENABLE
> +  {6, 5},  // MX6_EIM_SLOW_CLK_ENABLE
> +  {6, 6},  // MX6_VDOAXICLK_CLK_ENABLE
> +  {6, 7},  // MX6_VPU_CLK_ENABLE
> +};
> +
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +STATIC IMX_CLOCK_CONTEXT ExpectedClocks[] = {

Add m-prefix.

> +  {IMX_OSC_CLK, {24000000, IMX_CLK_NONE}},
> +  {IMX_PLL1_MAIN_CLK, {792000000, IMX_OSC_CLK}},
> +  {IMX_PLL2_MAIN_CLK, {528000000, IMX_OSC_CLK}},
> +  {IMX_PLL2_PFD0, {352000000, IMX_PLL2_MAIN_CLK}},
> +  {IMX_PLL2_PFD1, {594000000, IMX_PLL2_MAIN_CLK}},
> +  {IMX_PLL2_PFD2, {396000000, IMX_PLL2_MAIN_CLK}},
> +  {IMX_PLL3_MAIN_CLK, {480000000, IMX_OSC_CLK}},
> +  {IMX_PLL3_PFD0, {720000000, IMX_PLL3_MAIN_CLK}},
> +  {IMX_PLL3_PFD1, {540000000, IMX_PLL3_MAIN_CLK}},
> +  {IMX_PLL3_PFD2, {508235294, IMX_PLL3_MAIN_CLK}},
> +  {IMX_PLL3_PFD3, {454736842, IMX_PLL3_MAIN_CLK}},
> +  {IMX_AXI_CLK_ROOT, {264000000, IMX_PERIPH_CLK}},
> +  {IMX_MMDC_CH0_CLK_ROOT, {528000000, IMX_PERIPH_CLK}},
> +};
> +#elif defined(CPU_IMX6SDL)
> +STATIC IMX_CLOCK_CONTEXT ExpectedClocks[] = {

Add m-prefix.

> +  {IMX_OSC_CLK, {24000000, IMX_CLK_NONE}},
> +  {IMX_PLL1_MAIN_CLK, {792000000, IMX_OSC_CLK}},
> +  {IMX_PLL2_MAIN_CLK, {528000000, IMX_OSC_CLK}},
> +  {IMX_PLL2_PFD0, {306580645, IMX_PLL2_MAIN_CLK}},
> +  {IMX_PLL2_PFD1, {528000000, IMX_PLL2_MAIN_CLK}},
> +  {IMX_PLL2_PFD2, {396000000, IMX_PLL2_MAIN_CLK}},
> +  {IMX_PLL3_MAIN_CLK, {480000000, IMX_OSC_CLK}},
> +  {IMX_PLL3_PFD0, {720000000, IMX_PLL3_MAIN_CLK}},
> +  {IMX_PLL3_PFD1, {540000000, IMX_PLL3_MAIN_CLK}},
> +  {IMX_PLL3_PFD2, {508235294, IMX_PLL3_MAIN_CLK}},
> +  {IMX_PLL3_PFD3, {454736842, IMX_PLL3_MAIN_CLK}},
> +  {IMX_AXI_CLK_ROOT, {198000000, IMX_PERIPH_CLK}},
> +  {IMX_MMDC_CH0_CLK_ROOT, {396000000, IMX_PERIPH_CLK}},
> +};
> +#endif
> +
> +/**
> +  Get the CCGR register index and gate number for a clock gate.
> +
> +  @param[in]  ClockGate   Specific clock gate to get CCGR index
> +**/
> +IMX_CCGR_INDEX
> +ImxpCcgrIndexFromClkGate (
> +  IN  IMX_CLK_GATE    ClockGate
> +  )
> +{
> +  return ImxpCcgrIndexMap[ClockGate];
> +}
> +
> +CONST CHAR16*
> +StringFromImxClk (
> +  IN  IMX_CLK   Value
> +  )
> +{
> +  switch (Value) {
> +  case IMX_CLK_NONE:
> +    return L"(none)";

Is this swithch really worth it?
Could this string be added to the structs above instead?

> +  case IMX_OSC_CLK:
> +    return L"OSC_CLK";
> +  case IMX_PLL1_MAIN_CLK:
> +    return L"PLL1_MAIN_CLK";
> +  case IMX_PLL2_MAIN_CLK:
> +    return L"PLL2_MAIN_CLK";
> +  case IMX_PLL2_PFD0:
> +    return L"PLL2_PFD0";
> +  case IMX_PLL2_PFD1:
> +    return L"PLL2_PFD1";
> +  case IMX_PLL2_PFD2:
> +    return L"PLL2_PFD2";
> +  case IMX_PLL3_MAIN_CLK:
> +    return L"PLL3_MAIN_CLK";
> +  case IMX_PLL3_PFD0:
> +    return L"PLL3_PFD0";
> +  case IMX_PLL3_PFD1:
> +    return L"PLL3_PFD1";
> +  case IMX_PLL3_PFD2:
> +    return L"PLL3_PFD2";
> +  case IMX_PLL3_PFD3:
> +    return L"PLL3_PFD3";
> +  case IMX_PLL4_MAIN_CLK:
> +    return L"PLL4_MAIN_CLK";
> +  case IMX_PLL5_MAIN_CLK:
> +    return L"PLL5_MAIN_CLK";
> +  case IMX_CLK1:
> +    return L"CLK1";
> +  case IMX_CLK2:
> +    return L"CLK2";
> +  case IMX_PLL1_SW_CLK:
> +    return L"PLL1_SW_CLK";
> +  case IMX_STEP_CLK:
> +    return L"STEP_CLK";
> +  case IMX_PLL3_SW_CLK:
> +    return L"PLL3_SW_CLK";
> +  case IMX_AXI_ALT:
> +    return L"AXI_ALT";
> +  case IMX_AXI_CLK_ROOT:
> +    return L"AXI_CLK_ROOT";
> +  case IMX_PERIPH_CLK2:
> +    return L"PERIPH_CLK2";
> +  case IMX_PERIPH_CLK:
> +    return L"PERIPH_CLK";
> +  case IMX_PRE_PERIPH_CLK:
> +    return L"PRE_PERIPH_CLK";
> +  case IMX_PRE_PERIPH2_CLK:
> +    return L"PRE_PERIPH2_CLK";
> +  case IMX_PERIPH2_CLK:
> +    return L"PERIPH2_CLK";
> +  case IMX_ARM_CLK_ROOT:
> +    return L"ARM_CLK_ROOT";
> +  case IMX_MMDC_CH0_CLK_ROOT:
> +    return L"MMDC_CH0_CLK_ROOT";
> +  case IMX_MMDC_CH1_CLK_ROOT:
> +    return L"MMDC_CH1_CLK_ROOT";
> +  case IMX_AHB_CLK_ROOT:
> +    return L"AHB_CLK_ROOT";
> +  case IMX_IPG_CLK_ROOT:
> +    return L"IPG_CLK_ROOT";
> +  case IMX_PERCLK_CLK_ROOT:
> +    return L"PERCLK_CLK_ROOT";
> +  case IMX_USDHC1_CLK_ROOT:
> +    return L"USDHC1_CLK_ROOT";
> +  case IMX_USDHC2_CLK_ROOT:
> +    return L"USDHC2_CLK_ROOT";
> +  case IMX_USDHC3_CLK_ROOT:
> +    return L"USDHC3_CLK_ROOT";
> +  case IMX_USDHC4_CLK_ROOT:
> +    return L"USDHC4_CLK_ROOT";
> +  case IMX_SSI1_CLK_ROOT:
> +    return L"SSI1_CLK_ROOT";
> +  case IMX_SSI2_CLK_ROOT:
> +    return L"SSI2_CLK_ROOT";
> +  case IMX_SSI3_CLK_ROOT:
> +    return L"SSI3_CLK_ROOT";
> +  case IMX_GPU2D_AXI_CLK_ROOT:
> +    return L"GPU2D_AXI_CLK_ROOT";
> +  case IMX_GPU3D_AXI_CLK_ROOT:
> +    return L"GPU3D_AXI_CLK_ROOT";
> +  case IMX_PCIE_AXI_CLK_ROOT:
> +    return L"PCIE_AXI_CLK_ROOT";
> +  case IMX_VDO_AXI_CLK_ROOT:
> +    return L"VDO_AXI_CLK_ROOT";
> +  case IMX_IPU1_HSP_CLK_ROOT:
> +    return L"IPU1_HSP_CLK_ROOT";
> +  case IMX_GPU2D_CORE_CLK_ROOT:
> +    return L"GPU2D_CORE_CLK_ROOT";
> +  case IMX_ACLK_EIM_SLOW_CLK_ROOT:
> +    return L"ACLK_EIM_SLOW_CLK_ROOT";
> +  case IMX_ACLK_CLK_ROOT:
> +    return L"ACLK_CLK_ROOT";
> +  case IMX_ENFC_CLK_ROOT:
> +    return L"ENFC_CLK_ROOT";
> +  case IMX_GPU3D_CORE_CLK_ROOT:
> +    return L"GPU3D_CORE_CLK_ROOT";
> +  case IMX_GPU3D_SHADER_CLK_ROOT:
> +    return L"GPU3D_SHADER_CLK_ROOT";
> +  case IMX_VPU_AXI_CLK_ROOT:
> +    return L"VPU_AXI_CLK_ROOT";
> +  case IMX_IPU1_DI0_CLK_ROOT:
> +    return L"IPU1_DI0_CLK_ROOT";
> +  case IMX_IPU1_DI1_CLK_ROOT:
> +    return L"IPU1_DI1_CLK_ROOT";
> +  case IMX_LDB_DI0_SERIAL_CLK_ROOT:
> +    return L"LDB_DI0_SERIAL_CLK_ROOT";
> +  case IMX_LDB_DI0_IPU:
> +    return L"LDB_DI0_IPU";
> +  case IMX_LDB_DI1_SERIAL_CLK_ROOT:
> +    return L"LDB_DI1_SERIAL_CLK_ROOT";
> +  case IMX_LDB_DI1_IPU:
> +    return L"LDB_DI1_IPU";
> +  case IMX_SPDIF0_CLK_ROOT:
> +    return L"SPDIF0_CLK_ROOT";
> +  case IMX_SPDIF1_CLK_ROOT:
> +    return L"SPDIF1_CLK_ROOT";
> +  case IMX_ESAI_CLK_ROOT:
> +    return L"ESAI_CLK_ROOT";
> +  case IMX_HSI_TX_CLK_ROOT:
> +    return L"HSI_TX_CLK_ROOT";
> +  case IMX_CAN_CLK_ROOT:
> +    return L"CAN_CLK_ROOT";
> +  case IMX_ECSPI_CLK_ROOT:
> +    return L"ECSPI_CLK_ROOT";
> +  case IMX_UART_CLK_ROOT:
> +    return L"UART_CLK_ROOT";
> +  case IMX_VIDEO_27M_CLK_ROOT:
> +    return L"VIDEO_27M_CLK_ROOT";
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +  case IMX_IPU2_HSP_CLK_ROOT:
> +    return L"IPU2_HSP_CLK_ROOT";
> +  case IMX_IPU2_DI0_CLK_ROOT:
> +    return L"IPU2_DI0_CLK_ROOT";
> +  case IMX_IPU2_DI1_CLK_ROOT:
> +    return L"IPU2_DI1_CLK_ROOT";
> +#endif
> +  default:
> +    ASSERT (FALSE);
> +    return L"[Invalid IMX_CLK value]";
> +  }
> +}
> +
> +IMX_CLK
> +ImxpClkFromBypassClkSource (

This (and other) helper functions appear to only be called from this
file. Could they be made STATIC and dropped from the
iMX6ClkPwr_private.h, or are they expected to be used elsewhere in
future?

> +  IN  IMX_PLL_BYPASS_CLK_SRC    BypassClockSource
> +  )
> +{
> +  switch (BypassClockSource) {
> +  case IMX_PLL_BYPASS_CLK_SRC_REF_CLK_24M:
> +    return IMX_OSC_CLK;
> +  case IMX_PLL_BYPASS_CLK_SRC_CLK1:
> +    return IMX_CLK1;
> +  case IMX_PLL_BYPASS_CLK_SRC_CLK2:
> +    return IMX_CLK2;
> +  case IMX_PLL_BYPASS_CLK_SRC_XOR:
> +  default:
> +    ASSERT (FALSE);
> +    return IMX_CLK_NONE;
> +  }
> +}
> +
> +/**
> +  Configure the GPU clock tree so that GPU2D and GPU3D are clocked from
> +  the AXI clock root and are within the allowed frequency range.
> +
> +  The GPU must be powered down, and GPU clocks must be gated when this
> +  function is called.
> +**/
> +VOID
> +ImxCcmConfigureGpuClockTree (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;

No Hungarian notation please. Please search/replace '*p' with '*'
throughout the set. (Yes, I have accidentally let some through in the
past, we'll get around to cleaning those up in the future.)

> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +
> +  CbcmrReg.gpu2d_axi_clk_sel = IMX_CCM_GPU2D_AXI_CLK_SEL_AXI;
> +  CbcmrReg.gpu3d_axi_clk_sel = IMX_CCM_GPU3D_AXI_CLK_SEL_AXI;
> +  CbcmrReg.gpu2d_core_clk_sel = IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0;
> +  CbcmrReg.gpu3d_core_clk_sel = IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI;
> +  CbcmrReg.gpu3d_shader_clk_sel = IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI;
> +  CbcmrReg.gpu2d_core_clk_podf = 0;
> +  CbcmrReg.gpu3d_core_podf = 0;
> +  CbcmrReg.gpu3d_shader_podf = 0;
> +
> +  ImxpClkPwrCacheReset ();
> +  MmioWrite32 ((UINTN) &pCcmRegisters->CBCMR, CbcmrReg.AsUint32);
> +}
> +
> +/**
> +  Configure all of DIx clock tree for both IPU1 and IPU2. For flexibility
> +  purpose use PLL5 (PLL Video) as main reference clock. PLL 5 has flexible
> +  divider making it easily configurable. Muxing and clock programming needs
> +  when to be updated when supporting multiple display.
> +**/
> +VOID
> +ImxCcmConfigureIPUDIxClockTree (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CHSCCDR_REG         ChscddrReg;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  ChscddrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CHSCCDR);
> +
> +  // Setup muxing to pre-mux
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    ChscddrReg.ipu1_di0_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK;
> +    ChscddrReg.ipu1_di1_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK;
> +  } else {
> +    ChscddrReg.ipu1_di0_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_PREMUX;
> +    ChscddrReg.ipu1_di1_clk_sel = IMX_CHSCCDR_IPU1_DI1_CLK_SEL_PREMUX;
> +  }
> +  ChscddrReg.ipu1_di0_podf = IMX_CHSCCDR_IPU1_DI0_PODF_DIV_1;
> +  ChscddrReg.ipu1_di1_podf = IMX_CHSCCDR_IPU1_DI1_PODF_DIV_1;
> +  ChscddrReg.ipu1_di0_pre_clk_sel = IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL5;
> +  ChscddrReg.ipu1_di1_pre_clk_sel = IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL5;
> +
> +  MmioWrite32 ((UINTN)&pCcmRegisters->CHSCCDR, ChscddrReg.AsUint32);
> +}
> +
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +/**
> +    Configure both LDB0/1 to use PLL5 clock
> +**/
> +VOID
> +ImxCcmConfigureIPULDBxClockTree (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS *pCcmRegisters;
> +  IMX_CCM_CS2CDR_REG Cs2cdrReg;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Cs2cdrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CS2CDR);
> +
> +  Cs2cdrReg.ldb_di0_clk_sel = 0x0;
> +  Cs2cdrReg.ldb_di1_clk_sel = 0x0;
> +
> +  MmioWrite32 ((UINTN)&pCcmRegisters->CS2CDR, Cs2cdrReg.AsUint32);
> +}
> +#endif
> +
> +/**
> +    Configure PLL 5 clock rate to the desired clock rate
> +**/
> +VOID
> +ImxSetClockRatePLL5 (
> +  IN  UINT32                                  ClockRate,
> +  IN  IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT  PostDivSelect
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
> +  UINT32                              Counter;
> +  UINT32                              Denom;
> +  UINT32                              DivSelect;
> +  UINT32                              Numerator;
> +  IMX_CCM_PLL_VIDEO_CTRL_REG          PllVideoCtrlClearReg;
> +  IMX_CCM_PLL_VIDEO_CTRL_REG          PllVideoCtrlReg;
> +  IMX_CCM_PLL_VIDEO_CTRL_REG          PllVideoCtrlSetReg;
> +
> +  // Use clock rate as Denom for simple fractional calculation
> +  Denom = IMX_REF_CLK_24M_FREQ;
> +  DivSelect = ClockRate / IMX_REF_CLK_24M_FREQ;
> +  Numerator = ClockRate % IMX_REF_CLK_24M_FREQ;
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
> +  PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
> +
> +  ASSERT (Numerator < Denom);
> +  ASSERT ((DivSelect >= 27) && (DivSelect <= 54));
> +
> +  // PLL output frequency = Fref * (DIV_SELECT + NUM / DENOM)
> +  PllVideoCtrlReg.DIV_SELECT = DivSelect;
> +  PllVideoCtrlReg.POST_DIV_SELECT = PostDivSelect;
> +
> +  MmioWrite32 (
> +    (UINTN)&pCcmAnalogRegisters->PLL_VIDEO, PllVideoCtrlReg.AsUint32);
> +  MmioWrite32 (
> +    (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_NUM, Numerator);
> +  MmioWrite32 (
> +    (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_DENOM, Denom);
> +
> +  PllVideoCtrlReg.AsUint32 = MmioRead32 (
> +                               (UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
> +
> +  // Check to see if pll is locked, if not attempt to enable it
> +  if (PllVideoCtrlReg.LOCK == 0) {
> +    PllVideoCtrlClearReg.AsUint32 = 0;
> +    PllVideoCtrlClearReg.POWERDOWN = 1;
> +    MmioWrite32 (
> +      (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_CLR,
> +      PllVideoCtrlClearReg.AsUint32);
> +    PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
> +
> +    PllVideoCtrlSetReg.AsUint32 = 0;
> +    PllVideoCtrlSetReg.ENABLE = 1;
> +    MmioWrite32 (
> +      (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_SET,
> +      PllVideoCtrlSetReg.AsUint32);
> +    PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
> +
> +    PllVideoCtrlClearReg.AsUint32 = 0;
> +    PllVideoCtrlClearReg.BYPASS = 1;
> +    MmioWrite32 (
> +      (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_CLR,
> +      PllVideoCtrlClearReg.AsUint32);
> +    PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
> +
> +    for (Counter = 0; Counter < 10000; Counter++) {
> +      PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO);
> +      if (PllVideoCtrlReg.LOCK == 1) {
> +        DEBUG ((DEBUG_VERBOSE, "%a: PLL5 Video locked.\n", __FUNCTION__));
> +        break;
> +      }
> +    }
> +    if (PllVideoCtrlReg.LOCK == 0) {
> +      DEBUG ((DEBUG_ERROR, "%a: PLL5 Video not locked.\n", __FUNCTION__));
> +    }
> +  }
> +}
> +
> +EFI_STATUS
> +ImxpGetPll2PfdClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  IN      IMX_PLL_PFD           PfdIndex,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters;
> +  IMX_CLOCK_INFO                    ParentInfo;
> +  IMX_CCM_PFD_528_REG               Pfd528Reg;
> +  UINT32                            PfdFrac;

Fraction?

> +  EFI_STATUS                        Status;
> +
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
> +  Pfd528Reg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PFD_528);
> +  switch (PfdIndex) {
> +  case IMX_PLL_PFD0:
> +    PfdFrac = Pfd528Reg.PFD0_FRAC;
> +    break;
> +  case IMX_PLL_PFD1:
> +    PfdFrac = Pfd528Reg.PFD1_FRAC;
> +    break;
> +  case IMX_PLL_PFD2:
> +    PfdFrac = Pfd528Reg.PFD2_FRAC;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, IMX_PLL2_MAIN_CLK, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // The resulting frequency shall be 528*18/PFDn_FRAC
> +  // where PFD0_FRAC is in the range 12-35.
> +  ASSERT ((PfdFrac >= 12) && (PfdFrac <= 35));
> +  ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * 18 / PfdFrac);
> +  ClockInfo->Parent = IMX_PLL2_MAIN_CLK;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetAxiClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCDR_REG           CbcdrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
> +
> +  if (CbcdrReg.axi_sel == IMX_CCM_AXI_SEL_PERIPH_CLK) {
> +    Parent = IMX_PERIPH_CLK;
> +  } else {
> +    ASSERT (CbcdrReg.axi_sel == IMX_CCM_AXI_SEL_AXI_ALT);
> +    Parent = IMX_AXI_ALT;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.axi_podf);
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetGpu2dCoreClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +  switch (CbcmrReg.gpu2d_core_clk_sel) {
> +  case IMX_CCM_GPU2D_CORE_CLK_SEL_AXI:
> +    Parent = IMX_AXI_CLK_ROOT;
> +    break;
> +  case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL3_SW:
> +    Parent = IMX_PLL3_SW_CLK;
> +    break;
> +  case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0:
> +    Parent = IMX_PLL2_PFD0;
> +    break;
> +  case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD2:
> +    Parent = IMX_PLL2_PFD2;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu2d_core_clk_podf);
> +  ClockInfo->Parent = Parent;
> +  if (ClockInfo->Frequency > IMX_GPU2D_CORE_CLK_MAX) {
> +    DEBUG ((
> +            DEBUG_WARN,
> +            "%a: GPU2D_CORE_CLK exceeds maximum. (Value = %d, Max = %d)\n",
> +            __FUNCTION__,
> +            ClockInfo->Frequency,
> +            IMX_GPU2D_CORE_CLK_MAX));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetGpu3dCoreClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +  switch (CbcmrReg.gpu3d_core_clk_sel) {
> +  case IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI:
> +    Parent = IMX_MMDC_CH0_CLK_ROOT;
> +    break;
> +  case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL3_SW:
> +    Parent = IMX_PLL3_SW_CLK;
> +    break;
> +  case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD1:
> +    Parent = IMX_PLL2_PFD1;
> +    break;
> +  case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD2:
> +    Parent = IMX_PLL2_PFD2;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu3d_core_podf);
> +  ClockInfo->Parent = Parent;
> +  if (ClockInfo->Frequency > IMX_GPU3D_CORE_CLK_MAX) {
> +    DEBUG ((
> +            DEBUG_WARN,
> +            "%a: GPU3D_CORE_CLK exceeds maximum. (Value = %d, Max = %d)\n",
> +            __FUNCTION__,
> +            ClockInfo->Frequency,
> +            IMX_GPU3D_CORE_CLK_MAX));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetGpu3dShaderClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +  switch (CbcmrReg.gpu3d_shader_clk_sel) {
> +  case IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI:
> +    Parent = IMX_MMDC_CH0_CLK_ROOT;
> +    break;
> +  case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_SW:
> +    Parent = IMX_PLL3_SW_CLK;
> +    break;
> +  case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL2_PFD1:
> +    Parent = IMX_PLL2_PFD1;
> +    break;
> +  case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_PFD0:
> +    Parent = IMX_PLL3_PFD0;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu3d_shader_podf);
> +  ClockInfo->Parent = Parent;
> +
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +  if (ClockInfo->Frequency > IMX_GPU3D_SHADER_CLK_MAX) {
> +    DEBUG ((
> +            DEBUG_WARN,
> +            "%a: GPU3D_SHADER_CLK exceeds maximum. (Value = %d, Max = %d)",
> +            __FUNCTION__,
> +            ClockInfo->Frequency,
> +            IMX_GPU3D_SHADER_CLK_MAX));
> +  }
> +#endif
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPeriphClk2Info (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS *pCcmRegisters;
> +  IMX_CCM_CBCDR_REG CbcdrReg;
> +  IMX_CCM_CBCMR_REG CbcmrReg;
> +  IMX_CLK Parent;
> +  IMX_CLOCK_INFO ParentInfo;
> +  EFI_STATUS Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +  switch (CbcmrReg.periph_clk2_sel) {
> +  case IMX_CCM_PERIPH_CLK2_SEL_PLL3_SW_CLK:
> +    Parent = IMX_PLL3_SW_CLK;
> +    break;
> +  case IMX_CCM_PERIPH_CLK2_SEL_OSC_CLK:
> +    Parent = IMX_OSC_CLK;
> +    break;
> +  case IMX_CCM_PERIPH_CLK2_SEL_PLL2:
> +    Parent = IMX_PLL2_MAIN_CLK;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.periph_clk2_podf);
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPeriphClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCDR_REG           CbcdrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
> +
> +  // NOTE: periph_clk_sel is OR'd with PLL_bypass_en2 (from jtag) to
> +  //       produce the input value to the MUX. We assume PLL_bypass_en2 is 0.
> +  if (CbcdrReg.periph_clk_sel == 0) {
> +    Parent = IMX_PRE_PERIPH_CLK;
> +  } else {
> +    ASSERT (CbcdrReg.periph_clk_sel == 1);
> +    Parent = IMX_PERIPH_CLK2;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.mmdc_ch0_axi_podf);
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetMmdcCh0ClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCDR_REG           CbcdrReg;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Status = ImxpGetClockInfo (Cache, IMX_PERIPH_CLK, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.mmdc_ch0_axi_podf);
> +  ClockInfo->Parent = IMX_PERIPH_CLK;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetGpu2dAxiClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +  if (CbcmrReg.gpu2d_axi_clk_sel == IMX_CCM_GPU2D_AXI_CLK_SEL_AXI) {
> +    Parent = IMX_AXI_CLK_ROOT;
> +  } else {
> +    ASSERT (CbcmrReg.gpu2d_axi_clk_sel == IMX_CCM_GPU2D_AXI_CLK_SEL_AHB);
> +    Parent = IMX_AHB_CLK_ROOT;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency;
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetGpu3dAxiClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);
> +  if (CbcmrReg.gpu3d_axi_clk_sel == IMX_CCM_GPU3D_AXI_CLK_SEL_AXI) {
> +    Parent = IMX_AXI_CLK_ROOT;
> +  } else {
> +    ASSERT (CbcmrReg.gpu3d_axi_clk_sel == IMX_CCM_GPU3D_AXI_CLK_SEL_AHB);
> +    Parent = IMX_AHB_CLK_ROOT;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency;
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +ImxEnableGpuVpuPowerDomain (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pAnalogRegisters;
> +  volatile IMX_GPC_REGISTERS          *pGpcRegisters;
> +  volatile IMX_GPC_PGC_REGISTERS      *pGpuPgcRegisters;
> +  IMX_GPC_CNTR_REG                    GpcCntrReg;
> +  IMX_PMU_REG_CORE_REG                PmuCoreReg;
> +  IMX_GPC_PGC_PUPSCR_REG              PupscrReg;
> +
> +  pAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
> +  pGpcRegisters = (IMX_GPC_REGISTERS *) IMX_GPC_BASE;
> +  pGpuPgcRegisters = &pGpcRegisters->PGC_GPU;
> +
> +  // Configure GPC/PGC PUPSCR Register SW2ISO bits
> +  PupscrReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->PUPSCR);
> +  PupscrReg.SW = IMX_GPC_PGC_PUPSCR_SW_DEFAULT;
> +  PupscrReg.SW2ISO = IMX_GPC_PGC_PUPSCR_SW2ISO_DEFAULT;
> +  MmioWrite32 ((UINTN) &pGpuPgcRegisters->PUPSCR, PupscrReg.AsUint32);
> +
> +  // Turn on LDO_PU to 1.250V
> +  PmuCoreReg.AsUint32 = 0;
> +  PmuCoreReg.REG1_TARG = 0x1f;
> +  MmioWrite32 ((UINTN) &pAnalogRegisters->PMU_REG_CORE_CLR, PmuCoreReg.AsUint32);
> +  PmuCoreReg.REG1_TARG = 22;
> +  MmioWrite32 ((UINTN) &pAnalogRegisters->PMU_REG_CORE_SET, PmuCoreReg.AsUint32);
> +  MicroSecondDelay (100);
> +
> +  // Assert power up request
> +  GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
> +  GpcCntrReg.gpu_vpu_pdn_req = 0;
> +  GpcCntrReg.gpu_vpu_pup_req = 1;
> +  MmioWrite32 ((UINTN) &pGpcRegisters->CNTR, GpcCntrReg.AsUint32);
> +
> +  // Wait for power up request to complete
> +  do {
> +    GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
> +  } while (GpcCntrReg.gpu_vpu_pup_req != 0);
> +}
> +
> +VOID
> +ImxDisableGpuVpuPowerDomain (
> +  VOID
> +  )
> +{
> +  volatile IMX_GPC_REGISTERS      *pGpcRegisters;
> +  volatile IMX_GPC_PGC_REGISTERS  *pGpuPgcRegisters;
> +  IMX_GPC_PGC_PGCR_REG            CtrlReg;
> +  IMX_GPC_CNTR_REG                GpcCntrReg;
> +  IMX_GPC_PGC_PDNSCR_REG          PdnscrReg;
> +
> +  pGpcRegisters = (IMX_GPC_REGISTERS *) IMX_GPC_BASE;
> +  pGpuPgcRegisters = &pGpcRegisters->PGC_GPU;
> +
> +  // Configure GPC/PGC PDNSCR Register ISO bits
> +  PdnscrReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->PDNSCR);
> +  PdnscrReg.ISO = IMX_GPC_PGC_PDNSCR_ISO_DEFAULT;
> +  PdnscrReg.ISO2SW = IMX_GPC_PGC_PDNSCR_ISO2SW_DEFAULT;
> +  MmioWrite32 ((UINTN) &pGpuPgcRegisters->PDNSCR, PdnscrReg.AsUint32);
> +
> +  // Configure GPC/PGC CTRL[PCR] bit to allow power down of the blocks
> +  CtrlReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->CTRL);
> +  CtrlReg.PCR = 1;    // Enable powering down of the blocks
> +  MmioWrite32 ((UINTN) &pGpuPgcRegisters->CTRL, CtrlReg.AsUint32);
> +
> +  // Assert power down request
> +  GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
> +  GpcCntrReg.gpu_vpu_pdn_req = 1;
> +  GpcCntrReg.gpu_vpu_pup_req = 0;
> +  MmioWrite32 ((UINTN) &pGpcRegisters->CNTR, GpcCntrReg.AsUint32);
> +
> +  // Wait for power down request to complete
> +  do {
> +    GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR);
> +  } while (GpcCntrReg.gpu_vpu_pdn_req != 0);
> +}
> +
> +EFI_STATUS
> +ImxpGetClockInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  IN      IMX_CLK               ClockId,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  UINTN       CacheValidBits;
> +  EFI_STATUS  Status;
> +
> +  ASSERT (ClockId < ARRAYSIZE (Cache->Table));
> +
> +  // First try to satisfy from cache
> +  CacheValidBits = Cache->Valid[ClockId / _BITS_PER_UINTN];
> +  if (CacheValidBits & (1 << (ClockId % _BITS_PER_UINTN))) {
> +    *ClockInfo = Cache->Table[ClockId];
> +    return EFI_SUCCESS;
> +  }

Is this cache the purpose of this function?
If so, are these really called repeatedly often enough to motivate
this level of added complexity?

> +
> +  switch (ClockId) {
> +  case IMX_OSC_CLK:
> +    ImxpGetOsc24ClkInfo (ClockInfo);
> +    Status = EFI_SUCCESS;
> +    break;
> +  case IMX_PLL1_MAIN_CLK:
> +    Status = ImxpGetPll1MainClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_PLL2_MAIN_CLK:
> +    Status = ImxpGetPll2MainClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_PLL2_PFD0:
> +    Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD0, ClockInfo);
> +    break;
> +  case IMX_PLL2_PFD1:
> +    Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD1, ClockInfo);
> +    break;
> +  case IMX_PLL2_PFD2:
> +    Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD2, ClockInfo);
> +    break;
> +  case IMX_PLL3_MAIN_CLK:
> +    Status = ImxpGetPll3MainClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_PLL3_PFD0:
> +    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD0, ClockInfo);
> +    break;
> +  case IMX_PLL3_PFD1:
> +    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD1, ClockInfo);
> +    break;
> +  case IMX_PLL3_PFD2:
> +    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD2, ClockInfo);
> +    break;
> +  case IMX_PLL3_PFD3:
> +    Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD3, ClockInfo);
> +    break;
> +  case IMX_PLL3_SW_CLK:
> +    Status = ImxpGetPll3SwClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_AXI_CLK_ROOT:
> +    Status = ImxpGetAxiClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_PERIPH_CLK2:
> +    Status = ImxpGetPeriphClk2Info (Cache, ClockInfo);
> +    break;
> +  case IMX_PERIPH_CLK:
> +    Status = ImxpGetPeriphClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_PRE_PERIPH_CLK:
> +    Status = ImxpGetPrePeriphClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_ARM_CLK_ROOT:
> +    Status = ImxpGetArmClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_MMDC_CH0_CLK_ROOT:
> +    Status = ImxpGetMmdcCh0ClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_AHB_CLK_ROOT:
> +    Status = ImxpGetAhbClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_IPG_CLK_ROOT:
> +    Status = ImxpGetIpgClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_GPU2D_AXI_CLK_ROOT:
> +    Status = ImxpGetGpu2dAxiClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_GPU3D_AXI_CLK_ROOT:
> +    Status = ImxpGetGpu3dAxiClkRootInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_GPU2D_CORE_CLK_ROOT:
> +    Status = ImxpGetGpu2dCoreClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_GPU3D_CORE_CLK_ROOT:
> +    Status = ImxpGetGpu3dCoreClkInfo (Cache, ClockInfo);
> +    break;
> +  case IMX_GPU3D_SHADER_CLK_ROOT:
> +    Status = ImxpGetGpu3dShaderClkInfo (Cache, ClockInfo);
> +    break;
> +  default:
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // Update the cache
> +  Cache->Table[ClockId] = *ClockInfo;
> +  Cache->Valid[ClockId / _BITS_PER_UINTN] |= (1 << (ClockId % _BITS_PER_UINTN));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Power on and clock the GPU2D/GPU3D blocks.
> +
> +  Follow the datasheet recommended sequence for clocking and powering:
> +    Gate clocks -> unpower module ->
> +    configure muxes/dividers -> power module -> Ungate clocks
> +**/
> +EFI_STATUS
> +ImxClkPwrGpuEnable (
> +  VOID
> +  )
> +{
> +#if !defined(MDEPKG_NDEBUG)
> +  // Precondition: clock and power should be disabled
> +  ASSERT (ImxClkPwrGetClockGate (IMX_GPU3D_CLK_ENABLE) == IMX_CLOCK_GATE_STATE_OFF);
> +  ASSERT (ImxClkPwrGetClockGate (IMX_GPU2D_CLK_ENABLE) == IMX_CLOCK_GATE_STATE_OFF);
> +  ASSERT (ImxClkPwrGetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE) == IMX_CLOCK_GATE_STATE_OFF);

I'm OK with the first two lines being slightly longer than 80
characters, but the third one really is too long. Wrap?

> +#endif
> +
> +  // Ensure clocks are gated
> +  ImxClkPwrSetClockGate (IMX_GPU3D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_OFF);
> +  ImxClkPwrSetClockGate (IMX_GPU2D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_OFF);
> +  ImxClkPwrSetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
> +                         IMX_CLOCK_GATE_STATE_OFF);
> +
> +  // Ensure GPU powered down (GPU should be powered down anyway)
> +  ImxDisableGpuVpuPowerDomain ();
> +
> +  // Configure clock muxes and dividers for GPU3D, GPU2D, and OpenVG
> +  ImxCcmConfigureGpuClockTree ();
> +
> +  // Power on the GPU
> +  ImxEnableGpuVpuPowerDomain ();
> +
> +  // Ungate the GPU clocks
> +  ImxClkPwrSetClockGate (IMX_GPU3D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_ON);
> +  ImxClkPwrSetClockGate (IMX_GPU2D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_ON);
> +  ImxClkPwrSetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE,
> +                         IMX_CLOCK_GATE_STATE_ON);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxClkPwrIpuDIxEnable (
> +  VOID
> +  )
> +{
> +  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +  ImxClkPwrSetClockGate (IMX_IPU1_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +  ImxClkPwrSetClockGate (IMX_IPU2_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +  ImxClkPwrSetClockGate (IMX_IPU2_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +#endif
> +  ImxCcmConfigureIPUDIxClockTree();
> +  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON);
> +
> +  // Setup PLL to 65MHz as expected from UBOOT although transition
> +  // might be so fast that UBOOT screen would not be displayed

?

> +  ImxSetPll5ReferenceRate (65000000);
> +  return EFI_SUCCESS;
> +}
> +
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +/**
> +    Setup the clock tree for LDB0/1
> +**/
> +EFI_STATUS
> +ImxClkPwrIpuLDBxEnable (
> +  VOID
> +  )
> +{
> +  ImxClkPwrSetClockGate (IMX_LDB_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +  ImxClkPwrSetClockGate (IMX_LDB_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +  ImxCcmConfigureIPULDBxClockTree();
> +  ImxClkPwrSetClockGate (IMX_LDB_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON);
> +  ImxClkPwrSetClockGate (IMX_LDB_DI1_CLK_ENABLE, IMX_CCM_CCGR_ON);
> +
> +  return EFI_SUCCESS;
> +}
> +#endif
> +
> +/**
> +    Configure PLL5 to the desired clock rate for all Display Interface (DI).
> +    Currently only support one display to IPU1 DI0.
> +**/
> +EFI_STATUS
> +ImxSetPll5ReferenceRate (
> +  IN  UINT32  ClockRate
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS              *pCcmRegisters;
> +  IMX_CCM_CHSCCDR_REG                     ChscddrReg;
> +  UINT32                                  DxPodfDivider;
> +  BOOLEAN                                 FoundConfig;
> +  IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT  postDivSelect[3];

p -> P

> +  UINT32                                  PostDivSelectCount;
> +  UINT32                                  PostDivSelectValue[3];
> +  UINT32                                  TargetFreq;
> +
> +  FoundConfig = FALSE;
> +  PostDivSelectValue[0] = 1;
> +  PostDivSelectValue[1] = 2;
> +  PostDivSelectValue[2] = 4;
> +  postDivSelect[0] = IMX_POST_DIV_SELECT_DIVIDE_1;
> +  postDivSelect[1] = IMX_POST_DIV_SELECT_DIVIDE_2;
> +  postDivSelect[2] = IMX_POST_DIV_SELECT_DIVIDE_4;
> +
> +  for (PostDivSelectCount = 0;
> +       PostDivSelectCount < ARRAYSIZE (PostDivSelectValue);
> +       ++PostDivSelectCount) {
> +    for (DxPodfDivider = 1; DxPodfDivider < 9; ++DxPodfDivider) {
> +      TargetFreq = DxPodfDivider * ClockRate * PostDivSelectValue[PostDivSelectCount];
> +      // The valid range for PPL loop divider is 27-54 so target freq needs
> +      //   to fit within the valid range.
> +      if ((TargetFreq >= PLL5_MIN_FREQ) &&
> +          (TargetFreq <= PLL5_MAX_FREQ)) {
> +        FoundConfig = TRUE;
> +        break;
> +      }
> +    }
> +
> +    if (FoundConfig == TRUE) {
> +      break;
> +    }
> +  }
> +
> +  if (FoundConfig == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: ClockRate %d\n", __FUNCTION__, ClockRate));
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  DEBUG ((
> +          DEBUG_INFO,
> +          "%a: PLL 5 setting (%d) Target Freq %d Divider %d PostDiv %d\n",
> +          __FUNCTION__,
> +          ClockRate,
> +          TargetFreq,
> +          DxPodfDivider,
> +          PostDivSelectValue[PostDivSelectCount]
> +        ));
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  ChscddrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CHSCCDR);
> +  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +  ImxClkPwrSetClockGate (IMX_IPU1_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +  ImxClkPwrSetClockGate (IMX_IPU2_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +  ImxClkPwrSetClockGate (IMX_IPU2_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF);
> +#endif
> +  ChscddrReg.ipu1_di0_podf = DxPodfDivider - 1;
> +  ChscddrReg.ipu1_di1_podf = DxPodfDivider - 1;
> +  MmioWrite32 ((UINTN)&pCcmRegisters->CHSCCDR, ChscddrReg.AsUint32);
> +
> +  ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON);
> +  ImxSetClockRatePLL5 (TargetFreq, postDivSelect[PostDivSelectCount]);
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxClkPwrClkOut1Enable (
> +  IN  IMX_CLK   Clock,
> +  IN  UINT32    Divider
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CCOSR_REG           CcosrReg;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  if ((Divider < 1) || (Divider > 8)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CcosrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCOSR);
> +  switch (Clock) {
> +  case IMX_OSC_CLK:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_OSC_CLK;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  case IMX_PLL2_MAIN_CLK:
> +    CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_PLL2_MAIN_CLK_2;
> +    CcosrReg.CLKO1_DIV = Divider - 1;
> +    CcosrReg.CLKO1_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1;
> +    break;
> +
> +  case IMX_AXI_CLK_ROOT:
> +    CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_AXI_CLK_ROOT;
> +    CcosrReg.CLKO1_DIV = Divider - 1;
> +    CcosrReg.CLKO1_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1;
> +    break;
> +
> +  case IMX_IPG_CLK_ROOT:
> +    CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_IPG_CLK_ROOT;
> +    CcosrReg.CLKO1_DIV = Divider - 1;
> +    CcosrReg.CLKO1_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1;
> +    break;
> +
> +  case IMX_GPU2D_AXI_CLK_ROOT:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU2D_AXI_CLK_ROOT;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  case IMX_GPU3D_AXI_CLK_ROOT:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_AXI_CLK_ROOT;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  case IMX_GPU2D_CORE_CLK_ROOT:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU2D_CORE_CLK_ROOT;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  case IMX_GPU3D_CORE_CLK_ROOT:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_CORE_CLK_ROOT;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  case IMX_GPU3D_SHADER_CLK_ROOT:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_SHADER_CLK_ROOT;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  case IMX_UART_CLK_ROOT:
> +    CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_UART_CLK_ROOT;
> +    CcosrReg.CLKO2_DIV = Divider - 1;
> +    CcosrReg.CLKO2_EN = 1;
> +    CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2;
> +    break;
> +
> +  default:
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  MmioWrite32 ((UINTN) &pCcmRegisters->CCOSR, CcosrReg.AsUint32);
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +ImxClkPwrClkOut1Disable (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CCOSR_REG           CcosrReg;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CcosrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCOSR);
> +  CcosrReg.CLKO1_EN = 0;
> +  CcosrReg.CLKO2_EN = 0;
> +  MmioWrite32 ((UINTN) &pCcmRegisters->CCOSR, CcosrReg.AsUint32);
> +}
> +
> +EFI_STATUS
> +ImxClkPwrValidateClocks (
> +  VOID
> +  )
> +{
> +  IMX_CLOCK_INFO  ActualInfo;
> +  UINT32          i;
> +  BOOLEAN         Invalid;
> +  EFI_STATUS      Status;
> +
> +  Invalid = FALSE;
> +  for (i = 0; i < ARRAYSIZE (ExpectedClocks); ++i) {
> +    DEBUG ((
> +            DEBUG_INFO,
> +            "%a: Validating clock %s. Expecting: Frequency = %d (%d Mhz), Parent = %s\n",
> +            __FUNCTION__,
> +            StringFromImxClk (ExpectedClocks[i].Clock),
> +            ExpectedClocks[i].Info.Frequency,
> +            ExpectedClocks[i].Info.Frequency / 1000000,
> +            StringFromImxClk (ExpectedClocks[i].Info.Parent)
> +          ));
> +    Status = ImxClkPwrGetClockInfo (ExpectedClocks[i].Clock, &ActualInfo);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +              DEBUG_ERROR,
> +              "%a: Failed to get clock info. (Clock = %s, Status = 0x%x)\n",
> +              __FUNCTION__,
> +              StringFromImxClk (ExpectedClocks[i].Clock),
> +              Status
> +            ));
> +      return Status;
> +    }
> +    if ((ActualInfo.Frequency != ExpectedClocks[i].Info.Frequency) ||
> +        (ActualInfo.Parent != ExpectedClocks[i].Info.Parent)) {
> +      DEBUG ((
> +              DEBUG_ERROR,
> +              "%a: Clock settings do not match expected! Clock = %s (Expected, Actual) "
> +              "Frequency: %d, %d. Parent: %s, %s\n",
> +              __FUNCTION__,
> +              StringFromImxClk (ExpectedClocks[i].Clock),
> +              ExpectedClocks[i].Info.Frequency,
> +              ActualInfo.Frequency,
> +              StringFromImxClk (ExpectedClocks[i].Info.Parent),
> +              StringFromImxClk (ActualInfo.Parent)
> +            ));
> +      Invalid = TRUE;
> +    }
> +  }
> +
> +  return Invalid ? EFI_DEVICE_ERROR : EFI_SUCCESS;
> +}
> +
> +/**
> +  Reset/invalidate the clock tree cache.
> +
> +  The clock tree cache must be invalidated whenever the clock tree is modified,
> +  e.g. when changing PLL configuration, clock mux, or divider.
> +
> +**/
> +VOID
> +ImxpClkPwrCacheReset (
> +  VOID
> +  )
> +{
> +  SetMem (&mImxpClockPwrCache.Valid, sizeof (mImxpClockPwrCache.Valid), 0);
> +}
> +
> +/**
> +  Configure clock gating for the specified clock signal.
> +
> +  @param[in]  ClockGate   Specific clock signal to configure.
> +  @param[in]  State       State to set the clock signal to.
> +**/
> +VOID
> +ImxClkPwrSetClockGate (
> +  IN  IMX_CLK_GATE          ClockGate,
> +  IN  IMX_CLOCK_GATE_STATE  State
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  UINTN                       EndBit;
> +  IMX_CCGR_INDEX              Index;
> +  UINTN                       StartBit;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;

(No space after '(').

> +
> +  // Extract register index
> +  Index = ImxpCcgrIndexFromClkGate (ClockGate);
> +  StartBit = Index.GateNumber * 2;
> +  EndBit = StartBit + 1;
> +
> +  MmioBitFieldWrite32 (
> +    (UINTN) &pCcmRegisters->CCGR[Index.RegisterIndex],
> +    StartBit,
> +    EndBit,
> +    State);
> +}
> +
> +/**
> +  Determine if gating TZASC1_IPG_MASTER_CLK should be skipped.
> + **/
> +BOOLEAN
> +ImxClkPwrShouldSkipTZASC1 (
> +  VOID
> +  )
> +{
> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +  IMX_IOMUXC_GPR_REGISTERS  *IoMuxMmioBasePtr;
> +  UINTN                     IomuxGPR9;
> +#endif

Could we break this block up a bit with a blank line please?

> +  BOOLEAN                   Skip;
> +
> +  Skip = FALSE;

And again, blank line?

> +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP)
> +  IoMuxMmioBasePtr = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
> +
> +  IomuxGPR9 = MmioRead32 ((UINTN) &IoMuxMmioBasePtr->GPR9);
> +  if (IomuxGPR9 & IMX_IOMUXC_TZASC1_BYP) {
> +    // TZASC-1 is active.
> +    Skip = TRUE;
> +  }
> +#endif
> +
> +  return Skip;
> +}
> +
> +/**
> +  Determine if a clock gate should be skipped
> +
> +  @param[in]  ClockGate   Specific clock signal to configure.
> + **/
> +BOOLEAN
> +ImxClkPwrShouldSkipGate (
> +  IN  IMX_CLK_GATE  ClockGate
> +  )
> +{
> +  switch (ClockGate) {
> +  case IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE:
> +    return ImxClkPwrShouldSkipTZASC1 ();
> +
> +  default:
> +    return FALSE;
> +  }
> +}
> +
> +/**
> +  Set multiple clock signals to a given state.
> +
> +  @param[in]  ClockGateList   Pointer to list of possible clock signals.
> +  @param[in]  ClockGateCount  Number of clock signals to gate.
> +  @param[in]  State           State to set the clock signal to.
> +**/
> +VOID
> +ImxClkPwrSetClockGates (
> +  CONST IMX_CLK_GATE *ClockGateList,
> +  UINTN ClockGateCount,
> +  IMX_CLOCK_GATE_STATE State
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  UINTN                       i;
> +  IMX_CCGR_INDEX              Index;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +
> +  // Read all CCGR registers to local copy
> +  UINT32 ccgrRegisters[ARRAYSIZE (pCcmRegisters->CCGR)];
> +  for (i = 0; i < ARRAYSIZE (ccgrRegisters); ++i) {
> +    ccgrRegisters[i] = MmioRead32 ((UINTN) &pCcmRegisters->CCGR[i]);
> +  }
> +
> +  // Compute new CCGR register values
> +  for (i = 0; i < ClockGateCount; ++i) {
> +    if (ImxClkPwrShouldSkipGate (ClockGateList[i])) {
> +      continue;
> +    }
> +
> +    Index = ImxpCcgrIndexFromClkGate (ClockGateList[i]);
> +    ccgrRegisters[Index.RegisterIndex] =
> +      (ccgrRegisters[Index.RegisterIndex] & ~(0x3 << (2 * Index.GateNumber))) |
> +      (State << (2 * Index.GateNumber));
> +  }
> +
> +  // Write back to registers
> +  for (i = 0; i < ARRAYSIZE (ccgrRegisters); ++i) {
> +    MmioWrite32 ((UINTN) &pCcmRegisters->CCGR[i], ccgrRegisters[i]);
> +  }
> +}
> +
> +/**
> +  Get the current clock gating setting for the specified clock gate.
> +
> +  @param[in]  ClockGate     Specific clock signal to fetch clock gate info from.
> +**/
> +IMX_CLOCK_GATE_STATE
> +ImxClkPwrGetClockGate (
> +  IN  IMX_CLK_GATE  ClockGate
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  UINTN                       EndBit;
> +  IMX_CCGR_INDEX              Index;
> +  UINTN                       StartBit;
> +  UINT32                      Value;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Index = ImxpCcgrIndexFromClkGate (ClockGate);
> +  StartBit = Index.GateNumber * 2;
> +  EndBit = StartBit + 1;
> +
> +  Value = MmioBitFieldRead32 (
> +            (UINTN) &pCcmRegisters->CCGR[Index.RegisterIndex],
> +            StartBit,
> +            EndBit);
> +
> +  if ((Value != IMX_CCM_CCGR_OFF) &&
> +      (Value != IMX_CCM_CCGR_ON_RUN) &&
> +      (Value != IMX_CCM_CCGR_ON)) {
> +    ASSERT (FALSE);
> +  }
> +
> +  return (IMX_CLOCK_GATE_STATE) Value;
> +}
> +
> +EFI_STATUS
> +ImxpGetPll3MainClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
> +  IMX_CLK                             Parent;
> +  IMX_CLOCK_INFO                      ParentInfo;
> +  IMX_CCM_ANALOG_PLL_USB1_REG         PllUsb1Reg;
> +  EFI_STATUS                          Status;
> +
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
> +  PllUsb1Reg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_USB1);
> +  Parent = ImxpClkFromBypassClkSource (PllUsb1Reg.BYPASS_CLK_SRC);

Add blank line?

> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (PllUsb1Reg.DIV_SELECT == 0) {
> +    ClockInfo->Frequency = ParentInfo.Frequency * 20;
> +  } else {
> +    ClockInfo->Frequency = ParentInfo.Frequency * 22;

Why the 20/22? A comment here would be useful.

> +  }
> +
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPll3PfdClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  IN      IMX_PLL_PFD           PfdIndex,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
> +  IMX_CLOCK_INFO                      ParentInfo;
> +  IMX_CCM_PFD_480_REG                 Pfd480Reg;
> +  UINT32                              PfdFrac;
> +  EFI_STATUS                          Status;
> +
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
> +  Pfd480Reg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PFD_480);

No space after ) when casting.

> +  switch (PfdIndex) {
> +  case IMX_PLL_PFD0:
> +    PfdFrac = Pfd480Reg.PFD0_FRAC;
> +    break;
> +  case IMX_PLL_PFD1:
> +    PfdFrac = Pfd480Reg.PFD1_FRAC;
> +    break;
> +  case IMX_PLL_PFD2:
> +    PfdFrac = Pfd480Reg.PFD2_FRAC;
> +    break;
> +  case IMX_PLL_PFD3:
> +    PfdFrac = Pfd480Reg.PFD3_FRAC;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, IMX_PLL3_MAIN_CLK, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // The resulting frequency shall be 480*18/PFDn_FRAC

What exactly does 480 mean here?

> +  // where PFD0_FRAC is in the range 12-35.
> +  ASSERT ((PfdFrac >= 12) && (PfdFrac <= 35));
> +  ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * 18 / PfdFrac);

No space after ) when casting.
I think that 18 could to with a #define.

> +  ClockInfo->Parent = IMX_PLL3_MAIN_CLK;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPll3SwClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CCSR_REG            CcsrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CcsrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCSR);
> +  if (CcsrReg.pll3_sw_clk_sel == IMX_CCM_PLL3_SW_CLK_SEL_PLL3_MAIN_CLK) {
> +    Parent = IMX_PLL3_MAIN_CLK;
> +  } else {
> +    ASSERT (CcsrReg.pll3_sw_clk_sel == IMX_CCM_PLL3_SW_CLK_SEL_PLL3_BYPASS_CLK);
> +    ASSERT (!"Not implemented");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ClockInfo->Frequency = ParentInfo.Frequency;
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPll1MainClkInfo  (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
> +  IMX_CLK                             Parent;
> +  IMX_CLOCK_INFO                      ParentInfo;
> +  IMX_CCM_ANALOG_PLL_ARM_REG          PllArmReg;
> +  EFI_STATUS                          Status;
> +
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
> +  PllArmReg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PLL_ARM);
> +  Parent = ImxpClkFromBypassClkSource (PllArmReg.BYPASS_CLK_SRC);
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (PllArmReg.BYPASS != 0) {
> +    ClockInfo->Frequency = ParentInfo.Frequency;
> +    ClockInfo->Parent = Parent;
> +    return EFI_SUCCESS;
> +  }
> +
> +  ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * PllArmReg.DIV_SELECT / 2);
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPll2MainClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
> +  IMX_CLK                             Parent;
> +  IMX_CLOCK_INFO                      ParentInfo;
> +  IMX_CCM_ANALOG_PLL_SYS_REG          PllSysReg;
> +  EFI_STATUS                          Status;
> +
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE;
> +  PllSysReg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PLL_SYS);
> +  // Determine the reference clock source
> +  Parent = ImxpClkFromBypassClkSource (PllSysReg.BYPASS_CLK_SRC);

Add blank line?

> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (PllSysReg.BYPASS != 0) {
> +    ClockInfo->Frequency = ParentInfo.Frequency;
> +    ClockInfo->Parent = Parent;
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (PllSysReg.DIV_SELECT == 0) {
> +    ClockInfo->Frequency = ParentInfo.Frequency * 20;
> +  } else {
> +    ASSERT (PllSysReg.DIV_SELECT == 1);
> +    ClockInfo->Frequency = ParentInfo.Frequency * 22;
> +  }

This pattern seems to be repeating - add as helper function?

> +
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetArmClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CACRR_REG           CacrrReg;
> +  IMX_CLOCK_INFO              Pll1Info;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Status = ImxpGetClockInfo (Cache, IMX_PLL1_MAIN_CLK, &Pll1Info);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  CacrrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CACRR);
> +  ClockInfo->Frequency = Pll1Info.Frequency / (1 + CacrrReg.arm_podf);
> +  ClockInfo->Parent = IMX_PLL1_MAIN_CLK;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetPrePeriphClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCMR_REG           CbcmrReg;
> +  IMX_CLK                     Parent;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR);

Insert blank line?

> +  switch (CbcmrReg.pre_periph_clk_sel) {
> +  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2:
> +    Parent = IMX_PLL2_MAIN_CLK;
> +    break;
> +  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2:
> +    Parent = IMX_PLL2_PFD2;
> +    break;
> +  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD0:
> +    Parent = IMX_PLL2_PFD0;
> +    break;
> +  case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2:
> +    Parent = IMX_PLL2_PFD2;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (CbcmrReg.pre_periph_clk_sel == IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2) {
> +    ClockInfo->Frequency = ParentInfo.Frequency / 2;
> +  } else {
> +    ClockInfo->Frequency = ParentInfo.Frequency;
> +  }
> +
> +  ClockInfo->Parent = Parent;
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +ImxpGetOsc24ClkInfo (
> +  OUT IMX_CLOCK_INFO  *ClockInfo
> +  )
> +{
> +  ClockInfo->Frequency = IMX_REF_CLK_24M_FREQ;
> +  ClockInfo->Parent = IMX_CLK_NONE;
> +}
> +
> +EFI_STATUS
> +ImxpGetAhbClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCDR_REG           CbcdrReg;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Status = ImxpGetClockInfo (Cache, IMX_PERIPH_CLK, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.ahb_podf);
> +  ClockInfo->Parent = IMX_PERIPH_CLK;

Insert blank line?

> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxpGetIpgClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmRegisters;
> +  IMX_CCM_CBCDR_REG           CbcdrReg;
> +  IMX_CLOCK_INFO              ParentInfo;
> +  EFI_STATUS                  Status;
> +
> +  pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Status = ImxpGetClockInfo (Cache, IMX_AHB_CLK_ROOT, &ParentInfo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR);
> +  ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.ipg_podf);
> +  ClockInfo->Parent = IMX_AHB_CLK_ROOT;

Insert blank line?

> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ImxClkPwrGetClockInfo (
> +  IN  IMX_CLK         ClockId,
> +  OUT IMX_CLOCK_INFO  *ClockInfo
> +  )
> +{
> +  return ImxpGetClockInfo (&mImxpClockPwrCache, ClockId, ClockInfo);
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
> new file mode 100644
> index 000000000000..5e4603131471
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
> @@ -0,0 +1,46 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = iMX6ClkPwrLib
> +  FILE_GUID                      = 8DB4B460-9201-435A-B86A-24B58CED9A9E
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = iMX6ClkPwrLib
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  iMXIoMuxLib
> +  IoLib
> +  TimerLib

I am OK with these being sorted either case-sensitively or
case-insensitively, as long as it's consistent (and I have seen both
in this set).

> +
> +[Sources.common]
> +  iMX6ClkPwr.c
> +
> +[FeaturePcd]
> +  giMX6TokenSpaceGuid.PcdLvdsEnable
> +
> +[FixedPcd]
> +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
> new file mode 100644
> index 000000000000..2de1f62c7740
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
> @@ -0,0 +1,221 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_CLK_PWR_PRIVATE_H_
> +#define _IMX6_CLK_PWR_PRIVATE_H_
> +
> +#ifndef ARRAYSIZE
> +#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
> +#endif // ARRAYSIZE

Please use Base.h ARRAY_SIZE macro instead.

> +
> +#define _BITS_PER_UINTN (8 * sizeof(UINTN))

No _ in macro names, please.
Space between sizeof and '('.

/
    Leif

> +
> +typedef enum {
> +  IMX_PLL_PFD0,
> +  IMX_PLL_PFD1,
> +  IMX_PLL_PFD2,
> +  IMX_PLL_PFD3,
> +} IMX_PLL_PFD;
> +
> +typedef struct {
> +  IMX_CLK Clock;
> +  IMX_CLOCK_INFO Info;
> +} IMX_CLOCK_CONTEXT;
> +
> +typedef struct {
> +  UINT16 RegisterIndex;   // Register index (0-6)
> +  UINT16 GateNumber;      // Gate number within register (0-15)
> +} IMX_CCGR_INDEX;
> +
> +typedef struct {
> +  UINTN Valid[(IMX_CLK_MAX + _BITS_PER_UINTN) / _BITS_PER_UINTN];
> +  IMX_CLOCK_INFO Table[IMX_CLK_MAX];
> +} IMX_CLOCK_TREE_CACHE;
> +
> +IMX_CCGR_INDEX
> +ImxpCcgrIndexFromClkGate (
> +  IN  IMX_CLK_GATE    ClockGate
> +  );
> +
> +VOID
> +ImxpClkPwrCacheReset (
> +  VOID
> +  );
> +
> +IMX_CLK
> +ImxpClkFromBypassClkSource (
> +  IN  IMX_PLL_BYPASS_CLK_SRC    BypassClockSource
> +  );
> +
> +VOID
> +ImxCcmConfigureGpuClockTree (
> +  VOID
> +  );
> +
> +VOID
> +ImxCcmConfigureIPUDIxClockTree (
> +  VOID
> +  );
> +
> +VOID
> +ImxCcmConfigureIPULDBxClockTree (
> +  VOID
> +  );
> +
> +VOID
> +ImxSetClockRatePLL5 (
> +  IN  UINT32                                  ClockRate,
> +  IN  IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT  PostDivSelect
> +  );
> +
> +EFI_STATUS
> +ImxpGetClockInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  IN      IMX_CLK               ClockId,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +VOID
> +ImxpGetOsc24ClkInfo (
> +  OUT IMX_CLOCK_INFO  *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPll1MainClkInfo  (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPll2MainClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPll2PfdClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  IN      IMX_PLL_PFD           PfdIndex,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPll3MainClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPll3PfdClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  IN      IMX_PLL_PFD           PfdIndex,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPll3SwClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetAxiClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPeriphClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPrePeriphClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetPeriphClk2Info (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetArmClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetMmdcCh0ClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetAhbClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetIpgClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetGpu2dAxiClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetGpu3dAxiClkRootInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetGpu2dCoreClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetGpu3dCoreClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +EFI_STATUS
> +ImxpGetGpu3dShaderClkInfo (
> +  IN OUT  IMX_CLOCK_TREE_CACHE  *Cache,
> +  OUT     IMX_CLOCK_INFO        *ClockInfo
> +  );
> +
> +VOID
> +ImxEnableGpuVpuPowerDomain (
> +  VOID
> +  );
> +
> +VOID
> +ImxDisableGpuVpuPowerDomain (
> +  VOID
> +  );
> +
> +#endif // _IMX6_CLK_PWR_PRIVATE_H_
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
  2018-09-21  8:26 ` [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables Chris Co
@ 2018-12-14 19:53   ` Leif Lindholm
  2018-12-17 11:14   ` Ard Biesheuvel
  1 sibling, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 19:53 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:12AM +0000, Chris Co wrote:
> This adds baseline ACPI table support for booting Windows on
> NXP i.MX6 SoCs.  Platforms may override these tables as necessary.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc         | 408 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc         | 142 +++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h     | 106 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl     | 106 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl      |  74 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl     |  55 +++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl      |  67 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl     | 298 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl | 106 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl      |  85 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl     | 133 +++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl      | 103 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl     |  33 ++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc         |  60 +++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc         | 120 ++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc         |  92 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc         |  95 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc         |  53 +++
>  18 files changed, 2136 insertions(+)

Shouldn't there be a .inf in this patch as well?
Oh, no, this is used as an include directory, and ... hmm.
This gets a bit grotty later.

Ard, could you suggest a better way of laying this out?

> 
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
> new file mode 100644
> index 000000000000..82c2420a2b7e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
> @@ -0,0 +1,408 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include "../Include/Platform.h"
> +#include "../Include/iMX6.h"

#include <Platform.h>
#include <iMX6.h>
should just work here, since any user must declare use of
Silicon/NXP/iMX6Pkg/iMX6Pkg.dec anyway, and that puts the package
Include in the include path.

> +
> +#pragma pack(push, iMX6Csrt, 1)
> +
> +// Timer Resource Group
> +// Each timer consumes 4K of address space.
> +#define TIMER_ADDRES_SIZE 0x1000
> +#define TIMER_CAP_ALWAYS_ON     0x00000001 // Timer is always ON.
> +#define TIMER_CAP_UP_COUNTER    0x00000002 // Up counter vs. down counter (0)
> +#define TIMER_CAP_READABLE      0x00000004 // Counter has a software interface.
> +#define TIMER_CAP_PERIODIC      0x00000008 // Can generate periodic interrupts.
> +#define TIMER_CAP_DRIVES_IRQ    0x00000010 // Timer interrupt drives a physical IRQ.
> +#define TIMER_CAP_ONE_SHOT      0x00000020 // Counter can generate one-shot interrupts
> +
> +// Timer source clock codes
> +typedef enum {
> +  GPT_CLOCK_NONE        = 0,
> +  GPT_CLOCK_PERIPHERAL  = 1,
> +  GPT_CLOCK_HI_FREQ     = 2,
> +  GPT_CLOCK_EXT         = 3,
> +  GPT_CLOCK_LOW_FREQ    = 4,
> +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> +  GPT_CLOCK_OSC_DIV_8   = 5,
> +  GPT_CLOCK_OSC         = 7,
> +#elif (defined(CPU_IMX6SDL) || defined(CPU_IMX6SX))
> +  GPT_CLOCK_OSC         = 5,
> +#else
> +#error iMX6 CPU Type Not Defined (Preprocessor Flag)
> +#endif
> +} GPT_SOURCE_CLOCK;
> +
> +// EPIT timer source clock codes
> +typedef enum {
> +  EPIT_CLOCK_NONE        = 0,
> +  EPIT_CLOCK_PERIPHERAL  = 1,
> +  EPIT_CLOCK_HI_FREQ     = 2,
> +  EPIT_CLOCK_LOW_FREQ    = 3,
> +} EPIT_SOURCE_CLOCK;
> +
> +// Timer descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
> +  UINT32 Capabilities;
> +  UINT32 Width;
> +  UINT32 Source;
> +  UINT32 Frequency;
> +  UINT32 FrequencyScale;
> +  UINT32 BaseAddress;
> +  UINT32 Size;
> +  UINT32 Interrupt;
> +  UINT32 ChipType;
> +} RD_TIMER;
> +
> +// Resource Group Shared Info
> +typedef struct {
> +  UINT16 RevMajor;
> +  UINT16 RevMinor;
> +  UINT32 ChipType;
> +} RG_PLATFORM_INFORMATION;
> +
> +// Timer group descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
> +  RG_PLATFORM_INFORMATION PlatformInfo;
> +#if defined(CPU_IMX6SDL)
> +  RD_TIMER Timers[3];
> +#else
> +  RD_TIMER Timers[4];
> +#endif
> +} RG_TIMER;
> +
> +// PL310 L2 Cache Controller Resource Group
> +#define CSRT_PL310_MINIMUM_VERSION   1
> +#define CSRT_PL310_VERSION_2         2
> +#define CSRT_PL310_RAW_PROTOCOL      0
> +#define CSRT_PL310_SMC_PROTOCOL      1
> +
> +// We use PSCI_CPU_ON to turn on the L2 cache, with special value
> +// 0x00100000 for the Core ID. PSCI sees this core ID and knows
> +// this is an L2 cache operation, then looks at R2 for the
> +// operation to perform.
> +#define PSCI_FID_CPU_ON                        0x84000003
> +#define L2CACHE_SMC_R1                         0x00100000
> +#define L2CACHE_OP_ENABLE                      1
> +#define L2CACHE_OP_DISABLE                     2
> +#define L2CACHE_OP_ENABLE_WRITEBACK            3
> +#define L2CACHE_OP_DISABLE_WRITEBACK           4
> +#define L2CACHE_OP_ENABLE_WFLZ                 5
> +
> +typedef struct {
> +  UINT32 Immediate;
> +  UINT32 R0;
> +  UINT32 R1;
> +  UINT32 R2;
> +  UINT32 R3;
> +  UINT32 R12;
> +} CSRT_SMC_INVOCATION_BLOCK;
> +
> +// L2 cache descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
> +  UINT32 Version;
> +  UINT32 ManagementProtocol;
> +  UINT64 Address;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeEnable;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeDisable;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeEnableWriteback;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeDisableWriteback;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeEnableWFLZ;
> +} RD_L2_CACHE;
> +
> +// PL310 L2 cache controller descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
> +  RD_L2_CACHE L2Cache;
> +} RG_L2_CACHE;
> +
> +// SmartDMA (SDMA) Controller Resource Group
> +enum IMX_SDMA_CORE_CLOCK_RATIO {
> +  IMX_SDMA_CORE_CLOCK_TWICE_CORE_FREQ = 0,
> +  IMX_SDMA_CORE_CLOCK_EQUALS_CORE_FREQ = 1
> +};
> +
> +// SDMA controller descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
> +  UINT32 ChipType; // IMX_CHIP_TYPE
> +  UINT64 RegistersBaseAddress;
> +  UINT64 IoMuxGPR0Address;
> +  UINT32 Interrupt;
> +  UINT32 SdmaCoreClockRatio; // IMX_SDMA_CORE_CLOCK_RATIO
> +} RD_SDMA;
> +
> +// SDMA controller group descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
> +  RD_SDMA Sdma;
> +} RG_SDMA;
> +
> +
> +// CSRT structure for this platform
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER CsrtHeader; // Standard ACPI Header
> +  RG_TIMER TimerResourceGroup;            // Timer Resource Group
> +#ifndef CONFIG_L2CACHE_OFF
> +  RG_L2_CACHE L2CacheResourceGroup;       // PL310 L2 Cache Resource Group
> +#endif
> +  RG_SDMA SdmaResourceGroup;              // SDMA Resource Group
> +} EFI_ACPI_CSRT_TABLE;
> +
> +#pragma pack (pop, iMX6Csrt)
> +
> +EFI_ACPI_CSRT_TABLE Csrt = {
> +  // CSRT Header
> +  {
> +    EFI_ACPI_5_0_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE,  // Signature "CSRT"
> +    sizeof (EFI_ACPI_DESCRIPTION_HEADER) +              // Length
> +    sizeof (RG_TIMER)
> +#ifndef CONFIG_L2CACHE_OFF
> +    + sizeof (RG_L2_CACHE)
> +#endif
> +    + sizeof (RG_SDMA),
> +    EFI_ACPI_5_0_CSRT_REVISION,                         // Revision
> +    0x00,                                               // Checksum calculated at runtime.
> +    EFI_ACPI_OEM_ID,                                    // OEMID is a 6 bytes long field.
> +    EFI_ACPI_OEM_TABLE_ID,                              // OEM table identification(8 bytes long).
> +    EFI_ACPI_OEM_REVISION,                              // OEM revision number.
> +    EFI_ACPI_CREATOR_ID,                                // ASL compiler vendor ID.
> +    EFI_ACPI_CREATOR_REVISION,                          // ASL compiler revision number.
> +  },
> +
> +  // TimerResourceGroup
> +  {
> +    // Timer group header
> +    {
> +      sizeof (RG_TIMER),              // Resource Group Length
> +      EFI_ACPI_VENDOR_ID,             // VendorId
> +      0,                              // SubvendorId
> +      0x0101,                         // DeviceId
> +      0,                              // SubdeviceId
> +      0,                              // Revision
> +      0,                              // Reserved
> +      sizeof (RG_PLATFORM_INFORMATION) // Platform Information shared info
> +    },
> +
> +    // Platform Information
> +    {
> +      0x0001,                        // RevMajor
> +      0x0000,                        // RevMinor
> +      0,                             // IMX_CHIP_TYPE (not used)
> +    },
> +
> +    // Timers
> +    {
> +      // Counter (GPT)
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          3,                              // ResourceId
> +        },
> +        TIMER_CAP_READABLE | TIMER_CAP_UP_COUNTER, // Capabilities
> +        32,                                 // Timer width (bits)
> +        GPT_CLOCK_OSC,                      // Source is 111b for QD, 101b for SDL
> +        SOC_OSC_FREQUENCY_REF_HZ,           // Frequency 24 MHz
> +        24,                                 // divider to make 1 MHz
> +        CSP_BASE_REG_PA_GPT,                // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        0,                                  // N.B. No interrupt on this counter
> +      },
> +
> +      // Timer0 (EPIT1)
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          4,                              // ResourceId
> +        },
> +        TIMER_CAP_ONE_SHOT | TIMER_CAP_PERIODIC | // Capabilities
> +        TIMER_CAP_ALWAYS_ON | TIMER_CAP_DRIVES_IRQ,
> +        32,                                 // Timer width (bits)
> +        EPIT_CLOCK_LOW_FREQ,                // Source
> +        SOC_LOW_FREQ_REF_HZ,                // Frequency
> +        1,                                  // Frequency scale
> +        CSP_BASE_REG_PA_EPIT1,              // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        IRQ_EPIT1,                          // Interrupt
> +      },
> +
> +      // Timer1 (EPIT2)
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          5,                              // ResourceId
> +        },
> +        TIMER_CAP_ONE_SHOT | TIMER_CAP_PERIODIC | // Capabilities
> +        TIMER_CAP_ALWAYS_ON | TIMER_CAP_DRIVES_IRQ,
> +        32,                                 // Timer width (bits)
> +        EPIT_CLOCK_LOW_FREQ,                // Source
> +        SOC_LOW_FREQ_REF_HZ,                // Frequency
> +        1,                                  // Frequency scale
> +        CSP_BASE_REG_PA_EPIT2,              // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        IRQ_EPIT2,                          // Interrupt
> +      },
> +
> +#if defined(CPU_IMX6DQ)
> +      // SNVS LP Real Time Counter
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          6,                              // ResourceId
> +        },
> +        TIMER_CAP_UP_COUNTER |              // Capabilities
> +        TIMER_CAP_READABLE |
> +        TIMER_CAP_ALWAYS_ON,
> +        47,                                 // Timer width (bits)
> +        0,                                  // Source (NA)
> +        SOC_LOW_FREQ_REF_HZ,                // Frequency
> +        1,                                  // Frequency scale
> +        IMX_SNVS_BASE,                      // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        IMX_SNVS_IRQ,                       // Interrupt
> +      },
> +#endif
> +    }
> +  },
> +
> +#ifndef CONFIG_L2CACHE_OFF
> +  // L2CacheResourceGroup
> +  {
> +    // L2 cache group header
> +    {
> +      sizeof (RG_L2_CACHE),           // Resource Group Length
> +      SIGNATURE_32 ('A', 'R', 'M', 'H'), // VendorId
> +      SIGNATURE_32 ('A', 'R', 'M', 'H'), // SubvendorId
> +      0x0310,                         // DeviceId
> +      0,                              // SubdeviceId
> +      0,                              // Revision
> +      0,                              // Reserved
> +      0                               // No shared info
> +    },
> +
> +    // PL310 L2 cache controller
> +    {
> +      {
> +        sizeof (RD_L2_CACHE),           // Resource Descriptor Length
> +        EFI_ACPI_CSRT_RD_TYPE_CACHE,    // Resource Type
> +        EFI_ACPI_CSRT_RD_SUBTYPE_CACHE, // Resource Subtype
> +        0,                              // UID
> +      },
> +      CSRT_PL310_VERSION_2,               // Version
> +      CSRT_PL310_SMC_PROTOCOL,            // Management Protocol
> +      CSP_BASE_REG_PA_PL310,              // 64 bit Physical address
> +      // InvokeEnable
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_ENABLE,              // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeDisable
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_DISABLE,             // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeEnableWriteback
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_ENABLE_WRITEBACK,    // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeDisableWriteback
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_DISABLE_WRITEBACK,   // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeEnableWFLZ
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_ENABLE_WFLZ,         // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +    },
> +  },
> +#endif
> +
> +  // SdmaResourceGroup
> +  {
> +    // SDMA group header
> +    {
> +      sizeof (RG_SDMA),               // Resource Group Length
> +      EFI_ACPI_VENDOR_ID,             // VendorId
> +      0,                              // SubvendorId
> +      0x0111,                         // DeviceId
> +      0,                              // SubdeviceId
> +      0,                              // Revision
> +      0,                              // Reserved
> +      0                               // No shared info
> +    },
> +
> +    // SDMA controller resource
> +    {
> +      {
> +        sizeof (RD_SDMA),                           // Resource Descriptor Length
> +        EFI_ACPI_CSRT_RD_TYPE_DMA,                  // Resource Type
> +        EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CONTROLLER,    // Resource Subtype
> +        0,                                          // UID
> +      },
> +      0,                                    // IMX_CHIP_TYPE (not used)
> +      CSP_BASE_REG_PA_SDMA,                 // SDMA registers base physical address
> +      IOMUXC_GPR_BASE_ADDRESS,              // IoMuxGPR0 physical address
> +      IRQ_SDMA,                             // IRQ number
> +      IMX_SDMA_CORE_CLOCK_TWICE_CORE_FREQ,  // DMA/SDMA Core Clock Ratio:
> +    },
> +  }
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  // Reference the table being generated to prevent the optimizer from removing the
> +  // data structure from the executable
> +  return (VOID *)&Csrt;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
> new file mode 100644
> index 000000000000..65ce03d470ee
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
> @@ -0,0 +1,142 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Platform.h>
> +
> +#include "iMX6.h"

#include <iMX6.h>

> +
> +// DBG2 Definitions
> +#pragma pack (1)
> +
> +typedef enum {
> +  DBG2_TYPE_SERIAL = 0x8000,
> +  DBG2_TYPE_1394,
> +  DBG2_TYPE_USB,
> +  DBG2_TYPE_NET
> +} DBG2_PORT_TYPE;
> +
> +#define EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION 0x00000000
> +#define UART_NAME_SPACE_STRING_LENGTH               sizeof("\\_SB.UAR1")
> +#define UART_IMX6_UART_ADDRESS_SIZE       0x000000BC
> +
> +#if FixedPcdGet32(PcdKdUartInstance) == 1
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART1
> +#define KD_UART_ACPI_PATH "\\_SB.UAR1"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 2
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART2
> +#define KD_UART_ACPI_PATH "\\_SB.UAR2"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 3
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART3
> +#define KD_UART_ACPI_PATH "\\_SB.UAR3"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 4
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART4
> +#define KD_UART_ACPI_PATH "\\_SB.UAR4"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 5
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART5
> +#define KD_UART_ACPI_PATH "\\_SB.UAR5"
> +#else
> +#error "Invalid PcdKdUartInstance. Must be 1, 2, 3, 4, or 5"
> +#endif
> +
> +// ACPI 5.0 DBG2 structure
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER   Header;
> +  UINT32                        OffsetDbgDeviceInfo;
> +  UINT32                        NumberDbgdeviceInfo;
> +} EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER;
> +
> +typedef struct {
> +  UINT8 Revision;
> +  UINT16 Length;
> +  UINT8 NumberofGenericAddressRegisters;
> +  UINT16 NameSpaceStringLength;
> +  UINT16 NameSpaceStringOffset;
> +  UINT16 OemDataLength;
> +  UINT16 OemDataOffset;
> +  UINT16 PortType;
> +  UINT16 PortSubtype;
> +  UINT16 Reserved;
> +  UINT16 BaseAddressRegisterOffset;
> +  UINT16 AddressSizeOffset;
> +} DEBUG_DEVICE_INFO;
> +
> +typedef struct {
> +  DEBUG_DEVICE_INFO DeviceInfo;
> +  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> +  UINT32 AddressSize;
> +  char NameSpaceString[UART_NAME_SPACE_STRING_LENGTH];
> +} DEBUG_DEVICE_INFO_UART;
> +
> +typedef struct {
> +  EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER Header;
> +  DEBUG_DEVICE_INFO_UART Uart;
> +} EFI_ACPI_5_0_DEBUG_PORT_2_TABLE;
> +
> +#pragma pack ()
> +
> +// Debug Port 2 table
> +EFI_ACPI_5_0_DEBUG_PORT_2_TABLE Dbg2 = {
> +  {
> +    // Header
> +    {
> +      EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_SIGNATURE,     // Signature "DBG2"
> +      sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE),      // Length
> +      EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION,          // Revision
> +      EFI_ACPI_5_0_UNDEFINED,                        // Checksum - updated at runtime
> +      EFI_ACPI_OEM_ID,                               // OEM ID[6]
> +      EFI_ACPI_OEM_TABLE_ID,                         // OEM Table ID
> +      EFI_ACPI_OEM_REVISION,                         // OEM Revision
> +      EFI_ACPI_CREATOR_ID,                           // Creator ID
> +      EFI_ACPI_CREATOR_REVISION                      // Creator Revision
> +    },
> +    sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER), // OffsetDbgDeviceinfo
> +    1,                                               // NumberDbgDeviceInfo
> +  },
> +  {
> +    // Uart
> +    {
> +      // DeviceInfo
> +      EFI_ACPI_RESERVED_BYTE,                                 // Revision
> +      sizeof (DEBUG_DEVICE_INFO_UART),                        // Length
> +      1,                                                      // NumberofGenericAddressRegisters
> +      UART_NAME_SPACE_STRING_LENGTH,                          // NameSpaceStringLength
> +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, NameSpaceString),    // NameSpaceStringOffset
> +      0,                                                      // OemDataLength
> +      EFI_ACPI_RESERVED_WORD,                                 // OemDataOffset
> +      DBG2_TYPE_SERIAL,                                       // PortType
> +      DBG_PORT_SUBTYPE_IMX6,                                  // PortSubtype 000Ch
> +      EFI_ACPI_RESERVED_WORD,                                 // Reserved
> +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, BaseAddressRegister), // BaseAddressRegisterOffset
> +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, AddressSize),        // AddressSizeOffset
> +    },
> +    {
> +      // BaseAddressRegister
> +      EFI_ACPI_5_0_SYSTEM_MEMORY,                             // AddressSpaceId
> +      0x20,                                                   // RegisterBitWidth = 32
> +      0,                                                      // RegisterBitOffset = 0
> +      0x20,                                                   // AccessSize = 32
> +      KD_UART_BASE_ADDR,                                      // Address
> +    },
> +    UART_IMX6_UART_ADDRESS_SIZE,                                // AddressSize
> +    KD_UART_ACPI_PATH,                                          // NameSpaceString
> +  },
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (void *) &Dbg2;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> new file mode 100644
> index 000000000000..4e4a3522e842
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> @@ -0,0 +1,106 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// IMX alternate settings codes
> +#define IMX_ALT0 0x0
> +#define IMX_ALT1 0x1
> +#define IMX_ALT2 0x2
> +#define IMX_ALT3 0x3
> +#define IMX_ALT4 0x4
> +#define IMX_ALT5 0x5
> +#define IMX_ALT6 0x6
> +#define IMX_ALT7 0x7
> +
> +// IMX SDMA request lines.
> +// These are logical values, the mapping to the SOC
> +// actual DMA request lines are done in the HAL extension.
> +#define SDMA_REQ_VPU 0
> +#define SDMA_REQ_IPU2 1
> +#define SDMA_REQ_IPU1 2
> +#define SDMA_REQ_HDMI_AUDIO 3
> +#define SDMA_REQ_ECSPI1_RX 4
> +#define SDMA_REQ_ECSPI1_TX 5
> +#define SDMA_REQ_ECSPI2_RX 6
> +#define SDMA_REQ_ECSPI2_TX 7
> +#define SDMA_REQ_ECSPI3_RX 8
> +#define SDMA_REQ_ECSPI3_TX 9
> +#define SDMA_REQ_ECSPI4_RX 10
> +#define SDMA_REQ_ECSPI4_TX 11
> +#define SDMA_REQ_ECSPI5_RX 12
> +#define SDMA_REQ_ECSPI5_TX 13
> +#define SDMA_REQ_I2C1_RX 14
> +#define SDMA_REQ_I2C1_TX 15
> +#define SDMA_REQ_I2C2_RX 16
> +#define SDMA_REQ_I2C2_TX 17
> +#define SDMA_REQ_I2C3_RX 18
> +#define SDMA_REQ_I2C3_TX 19
> +#define SDMA_REQ_UART1_RX 20
> +#define SDMA_REQ_UART1_TX 21
> +#define SDMA_REQ_UART2_RX 22
> +#define SDMA_REQ_UART2_TX 23
> +#define SDMA_REQ_UART3_RX 24
> +#define SDMA_REQ_UART3_TX 25
> +#define SDMA_REQ_UART4_RX 26
> +#define SDMA_REQ_UART4_TX 27
> +#define SDMA_REQ_UART5_RX 28
> +#define SDMA_REQ_UART5_TX 29
> +#define SDMA_REQ_SPDIF_RX 30
> +#define SDMA_REQ_SPDIF_TX 31
> +#define SDMA_REQ_EPIT1 32
> +#define SDMA_REQ_EPIT2 33
> +#define SDMA_REQ_GPT 34
> +#define SDMA_REQ_ASRC_RXA 35
> +#define SDMA_REQ_ASRC_RXB 36
> +#define SDMA_REQ_ASRC_RXC 37
> +#define SDMA_REQ_ASRC_TXA 38
> +#define SDMA_REQ_ASRC_TXB 39
> +#define SDMA_REQ_ASRC_TXC 40
> +#define SDMA_REQ_ESAI_RX 41
> +#define SDMA_REQ_ESAI_TX 42
> +#define SDMA_REQ_ASRC_TXA_2_ESAI_TX 43
> +#define SDMA_REQ_ASRC_TXB_2_ESAI_TX 44
> +#define SDMA_REQ_ASRC_TXC_2_ESAI_TX 45
> +#define SDMA_REQ_SSI1_RX1 46
> +#define SDMA_REQ_SSI1_TX1 47
> +#define SDMA_REQ_SSI1_RX0 48
> +#define SDMA_REQ_SSI1_TX0 49
> +#define SDMA_REQ_SSI2_RX1 50
> +#define SDMA_REQ_SSI2_TX1 51
> +#define SDMA_REQ_SSI2_RX0 52
> +#define SDMA_REQ_SSI2_TX0 53
> +#define SDMA_REQ_SSI3_RX1 54
> +#define SDMA_REQ_SSI3_TX1 55
> +#define SDMA_REQ_SSI3_RX0 56
> +#define SDMA_REQ_SSI3_TX0 57
> +#define SDMA_REQ_EXT1 58
> +#define SDMA_REQ_EXT2 59
> +#define SDMA_REQ_UART6_RX 60
> +#define SDMA_REQ_UART6_TX 61
> +#define SDMA_REQ_ADC1 62
> +#define SDMA_REQ_ADC2 63
> +#define SDMA_REQ_I2C4_RX 64
> +#define SDMA_REQ_I2C4_TX 65
> +#define SDMA_REQ_CSI1 66
> +#define SDMA_REQ_CSI2 67
> +#define SDMA_REQ_PXP 68
> +#define SDMA_REQ_LCDIF1 69
> +#define SDMA_REQ_LCDIF2 70
> +#define SDMA_REQ_QSPI1_RX 71
> +#define SDMA_REQ_QSPI1_TX 72
> +#define SDMA_REQ_QSPI2_RX 73
> +#define SDMA_REQ_QSPI2_TX 74
> +#define SDMA_REQ_SAI1_TX 75
> +#define SDMA_REQ_SAI1_RX 76
> +#define SDMA_REQ_SAI2_TX 77
> +#define SDMA_REQ_SAI2_RX 78
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> new file mode 100644
> index 000000000000..eded7cdae7d0
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> @@ -0,0 +1,106 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (ENET)
> +{
> +  Name (_HID, "NXP010D")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xF)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // ENET MAC Core Base address
> +      MEMORY32FIXED (ReadWrite, 0x02188000, 0x4000, )
> +
> +      // ENET MAC 0 Core IRQ
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 150 }
> +
> +      // ENET MAC 0 1588 Timer interrupt
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 151 }
> +
> +      // Errata ERR006687: workaround for GPIO interrupt to connect Enet interrupt
> +      // to the GPC
> +      GpioInt (Level, ActiveHigh, Shared, PullDefault, 0, "\\_SB.GPIO",) { 6 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Name (MAC, Buffer (6) {})
> +  CreateDWordField (MAC, 0x00, MACL)
> +  CreateWordField (MAC, 0x04, MACH)
> +
> +  // Device Specific Method takes 4 args:
> +  //  Arg0 : Buffer containing a UUID [16 bytes]
> +  //  Arg1 : Integer containing the Revision ID
> +  //  Arg2 : Integer containing the Function Index
> +  //  Arg3 : Package that contains function-specific arguments
> +  Method (_DSM, 0x4, NotSerialized) {
> +    switch (ToBuffer (Arg0)) {
> +    // iMX Enet interface identifier
> +    case (ToUUID ("4EBBCB9D-4087-4791-80BD-8F8C08024206")) {
> +        // Function selector
> +        switch (Arg2) {
> +        // Function 0: Query support
> +        //   Bit  Description
> +        //   ---  -------------------------------
> +        //     0  Get property (Function 0)
> +        //     1  Enet PHY address on MDIO bus (Function 1)
> +        //     2  Get Mac Address (Function 2)
> +        //     3  Get MDIO BAse Address (Function 3)
> +        case (0) {
> +            // Revision selector
> +            switch (Arg1) {
> +            case (0) {
> +                // Functions {0,1,2} supported
> +                Return (Buffer() { 0x07 });
> +              }
> +            default {
> +                Return (Buffer() { 0x00 });
> +              }
> +            }
> +          }
> +
> +        // Function 1: Return Enet PHY address on MDIO bus.
> +        case (1) {
> +            Return (0x00);
> +          }
> +
> +        // Function 2: Return Mac Address
> +        case (2) {
> +            if (LEqual (SIGN, 0x474C424C)) {
> +              if (LEqual (REVN, 1)) {
> +                if (Lequal (MC0V, 1)) {
> +                  Store (MC0L, MACL);
> +                  Store (MC0H, MACH);
> +                  Return (MAC)
> +                }
> +              }
> +            }
> +            Return (Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
> +          }
> +
> +        default {
> +            Return (Buffer() { 0x00 });
> +          }
> +        }
> +      }
> +    default {
> +        Return (Buffer() { 0x00 });
> +      }
> +    }
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> new file mode 100644
> index 000000000000..eec71864210e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> @@ -0,0 +1,74 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (VPU0)
> +{
> +  Name (_HID, "NXP0109")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0x0)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02040000, 0x3C000, )
> +
> +      // JPEG codec interrupt request
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 35 }
> +
> +      // VPU interrupt request
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 44 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +// Description: Graphics Processing Unit (GPU)
> +Device (GPU0)
> +{
> +  Name (_HID, "VERI2000")
> +  Name (_CID, "VERI2000")
> +  Name (_UID, 0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // GPU 3D (GC2000)
> +      MEMORY32FIXED (ReadWrite, 0x00130000, 0x4000, )
> +
> +      // GPU 2D (GC320)
> +      MEMORY32FIXED (ReadWrite, 0x00134000, 0x4000, )
> +
> +      // IPU Base
> +      MEMORY32FIXED (ReadWrite, 0x02600000, 0x400000, )
> +
> +      // HDMI PHY
> +      MEMORY32FIXED (ReadWrite, 0x00120000, 0x9000, )
> +
> +      // GC2000
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 41 }
> +
> +      // GC320
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
> +
> +      // IPU1 sync interrupt request
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 38 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> new file mode 100644
> index 000000000000..d9a5d2f8500a
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> @@ -0,0 +1,55 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (GPIO)
> +{
> +  Name (_HID, "NXP0103")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // GPIO1-7
> +      MEMORY32FIXED (ReadWrite, 0x0209C000, 0x1C000, )
> +
> +      // IOMUXC
> +      MEMORY32FIXED (ReadWrite, 0x020E0000, 0x4000, )
> +
> +      // GPIO1 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 98, 99 }
> +
> +      // GPIO2 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 100, 101 }
> +
> +      // GPIO3 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 102, 103 }
> +
> +      // GPIO4 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 104, 105 }
> +
> +      // GPIO5 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 106, 107 }
> +
> +      // GPIO6 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 108, 109 }
> +
> +      // GPIO7 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 110, 111 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> new file mode 100644
> index 000000000000..af9f17890b97
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> @@ -0,0 +1,67 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (I2C1)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (I2C2)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A4000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 69 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (I2C3)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> new file mode 100644
> index 000000000000..1e0627f93000
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> @@ -0,0 +1,298 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (PCI0)
> +{
> +  Name (_HID, "PNP0A08")
> +  Name (_UID, 0)
> +  Name (_STR, Unicode ("PCIe 0 Device"))
> +  Name (_BBN, 0)
> +  Name (_SEG, 0)
> +
> +  // PCIE_PL memory map
> +  OperationRegion (PLGC, SystemMemory, 0x01FFC700, 0x220)
> +  Field (PLGC, DWordAcc, NoLock, Preserve) {
> +    Offset (0x2C),  // Skip to register 0x01FFC72C
> +    DBG1, 32,       // PCIE_PL_DEBUG1
> +  }
> +
> +  // IOMUXC memory map
> +  OperationRegion (IMXC, SystemMemory, 0x020E0000, 0x4000)
> +  Field (IMXC, DWordAcc, NoLock, Preserve) {
> +    Offset (0x04),  // Skip to register 0x020E0004
> +    GPR1, 32,       // IOMUXC_GPR1
> +  }
> +
> +  // PCIe is only available if PCIe PHY reference clock is enabled and link is up
> +  Method (_STA) {
> +    Name (LNK, 0x0);
> +    Name (GPR, 0x0);
> +    Store (GPR1, GPR);  // read IOMUXC_GPR1 register
> +
> +    // Check if the PCIe PHY reference clock is enabled
> +    If (LNotEqual (And (GPR, 0x00010000), 0x00010000)) {
> +      Return (0x0)
> +    }
> +
> +    Store (DBG1, LNK);  // read PCIE_PL_DEBUG1 register
> +
> +    // Check if link is already up and is not in training
> +    //  Bit4  : [36]: xmlh_link_up LTSSM reports PHY link up
> +    //  Bit29  : [61]: xmlh_link_in_training LTSSM performing link training
> +    If (LAnd (And (DBG1, 0x00000010), Lequal (And (DBG1, 0x20000000), 0x00))) {
> +      Return (0xF)
> +    } else {
> +      Return (0x0)
> +    }
> +  }
> +
> +  // Declare the resources assigned to this root complex.
> +  Method (_CRS, 0, Serialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      WordBusNumber (
> +        ResourceProducer, // Specify bus ranged is passed to child devices
> +        MinFixed,         // Specify min address is fixed
> +        MaxFixed,         // Specify max address is fixed
> +        PosDecode,        // Positive decode of bus number
> +        0,                // AddressGranularity 2 power of 0
> +        0,                // AddressMinimum - Minimum Bus Number
> +        1,                // AddressMaximum - Maximum Bus Number
> +        0,                // AddressTranslation - Set to 0
> +        2)                // RangeLength - Number of Busses
> +
> +      // PCI memory space
> +      Memory32Fixed (ReadWrite, 0x01100000, 0x00E00000, )
> +    })
> +    Return (RBUF)
> +  }
> +
> +  // Declare the PCI Routing Table.
> +  Name (_PRT, Package() {
> +    // Routing for device 0, all functions.
> +    // Note: ARM doesn't support LNK nodes, so the third param
> +    // is 0 and the fourth param is the SPI number of the interrupt
> +    // line.
> +    Package() {0x0000FFFF, 0, 0, 155}, // INTA
> +    Package() {0x0000FFFF, 1, 0, 154}, // INTB
> +    Package() {0x0000FFFF, 2, 0, 153}, // INTC
> +    Package() {0x0000FFFF, 3, 0, 152}, // INTD/MSI
> +  })
> +
> +  Name (SUPP, 0) // PCI _OSC Support Field value
> +  Name (CTRL, 0) // PCI _OSC Control Field value
> +
> +  // Declare an _OSC (OS Control Hand-off) method which takes 4 arguments.
> +  //
> +  // Arguments:
> +  //   Arg0  A Buffer containing a UUID
> +  //   Arg1  An Integer containing a Revision ID of the buffer format
> +  //   Arg2  An Integer containing a count of entries in Arg3
> +  //   Arg3  A Buffer containing a list of DWORD capabilities
> +  // Return Value:
> +  //   A Buffer containing a list of capabilities
> +  Method (_OSC, 4) {
> +
> +    // Create DWord-addressable fields from the Capabilities Buffer
> +    // Create CDW1 outside the test as it's used in the else clause.
> +    // The first DWORD in the _OSC Capabilities Buffer contains bits
> +    // that are generic to _OSC
> +    // PCI Firmware Specification - 4.5.1.
> +    //
> +    // ACPI - 6.2.10
> +    // CDW return value information
> +    // Bit 0 - Reserved (not used)
> +    // Bit 1 - _OSC failure. Platform Firmware was unable to process the request or query
> +    // Bit 2 - Unrecognized UUID
> +    // Bit 3 - Unrecognized Revision
> +    // Bit 4 - Capabilities Masked
> +    // All others reserved
> +
> +    CreateDWordField (Arg3, 0, CDW1)
> +    If (LEqual (Arg0, ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
> +      CreateDWordField (Arg3, 4, CDW2)
> +      CreateDWordField (Arg3, 8, CDW3)
> +
> +      // Save Capabilities DWord 2 & 3
> +      // The second DWORD in the _OSC Capabilities Buffer is the Support Field
> +      // The third DWORD in the _OSC Capabilities Buffer is the Control Field
> +      // PCI Firmware Specification - 4.5.1.
> +      // Supported feature should be set in the control field
> +      //
> +      // Support field
> +      // Bit 0 - Extended PCI Config operation regions supported
> +      // Bit 1 - Active State Power Management supported
> +      // Bit 2 - Clock Power Management Capability supported
> +      // Bit 3 - PCI Segment Groups supported
> +      // Bit 4 - MSI supported
> +      // Bit 5 - Optimized Buffer Flush and Fill supported
> +      // Bit 6 - ASPM Optionality supported
> +      //
> +      // Control field
> +      // Bit 0 - PCI Express Native Hot Plug control
> +      // Bit 1 - SHPC Native Hot Plug control
> +      // Bit 2 - PCI Express Native Power Management Events control
> +      // Bit 3 - PCI Express Advanced Error Reporting control
> +      // Bit 4 - PCI Express Capability Structure control
> +      // Bit 5 - Latency Tolerance Reporting control
> +
> +      Store (CDW2, SUPP)
> +      Store (CDW3, CTRL)
> +
> +      // Only allow native hot plug control if OS supports:
> +      //  ASPM
> +      //  Clock PM
> +      //  MSI/MSI-X
> +      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
> +        And (CTRL, 0x1E, CTRL)
> +      }
> +
> +      // Spec does not mention if standard hot plug is supported
> +      // so unmask the bit
> +      And (CTRL, 0x1D, CTRL)
> +
> +      // Check for unknown revision.
> +      If (LNotEqual (Arg1, One)) {
> +        Or (CDW1, 0x08, CDW1)
> +      }
> +
> +      // Check if capabilities bits were masked.
> +      If (LNotEqual (CDW3, CTRL)) {
> +        Or (CDW1, 0x10, CDW1)
> +      }
> +
> +      // Update DWORD3 in the buffer.
> +      Store (CTRL, CDW3)
> +      Return (Arg3)
> +    } else {
> +      // Unrecognized UUID
> +      Or (CDW1, 4, CDW1)
> +      Return (Arg3)
> +    }
> +  }
> +
> +  // Declare a _DSM method for various functions called by the OS.
> +  // See the APCI spec, Section 9.14.1,
> +  // and the PCI FW spec, Section 4.6.
> +  // See also:
> +  // http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/PCI-rsc.doc
> +  Method (_DSM, 0x4, Serialized) {
> +    // Match against the _DSM PCI UUID. PCI firmware spec - 4.6.1
> +    //     Arg0 - UUID
> +    //     Arg1 - Revision ID
> +    //     Arg2 - Function Index
> +    //     Arg3 - Empty Package
> +    //
> +    // Revision 1 & 2
> +    //     Function 1 - PCI Express Slot Information
> +    //     Function 2 - PCI Express Slot Number
> +    //     Function 3 - Vendor-specific Token ID
> +    //     Function 4 - PCI Bus Capabilities
> +    //     Function 5 - Ignore PCI Boot Configuration
> +    // Revision 2 only
> +    //     Function 6 - LTR Maximum Latency
> +    //     Function 7 - Express device under OS
> +    If (LEqual (Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
> +
> +      switch (ToInteger (Arg2)) {
> +      // Function 0: Return supported functions as a bit-field
> +      // with one bit for each supported function.
> +      // Bit 0 must always be set, as that represents
> +      // function 0 (which is what is being called here).
> +      // Support for different functions may depend on
> +      // the revision ID of the interface, passed as Arg1.
> +
> +      // Function 0: Get supported functions
> +      case (0) {
> +          // Functions 0,1,5 are supported.
> +          if (LEqual (Arg1, 1)) {
> +            return (Buffer() { 0x23 })
> +          }
> +
> +          // Functions 0,1,5,7 are supported.
> +          if (LEqual (Arg1, 2)) {
> +            return (Buffer() { 0xA3 })
> +          }
> +
> +          // Functions 0,1,5,7 are supported for
> +          // future revision. Expect backward compatibility
> +          return (Buffer() { 0xA3 })
> +        }
> +
> +      // Function 1: PCI Express Slot Information
> +      // PCI firmware spec - 4.6.1
> +      case (1) {
> +          // Package item 1:
> +          //    0: Failure
> +          //    1: Success
> +          // Package item 2:
> +          //  Integer 1:Bit Position
> +          //        0 Supports x1
> +          //        1 Supports x2
> +          //        2 Supports x4
> +          //        3 Supports x8
> +          //        4 Supports x12
> +          //        5 Supports x16
> +          //  Integer 2:
> +          //        0h Unknown
> +          //        1h PCI Express Card Slot
> +          //        2h PCI Express Server I/O Module Slot
> +          //        3h PCI Express ExpressCard* Slot
> +          //        4h PCI Express Mini Card Slot
> +          //        5h PCI Express Wireless Form Factor Slot
> +          //        Others Reserved
> +          //  Integer 3:
> +          //        0 SMBus signal
> +          //        1 WAKE# signal
> +          return ( Package (2) {
> +            0x01, // Status success (1)
> +            Package() {
> +              0, // Supports x1
> +              4, // PCI Express Mini Card Slot
> +              1  // Supported signals (no SMBus, WAKE#)
> +            }
> +          })
> +        }
> +
> +      // Function 5: Ignore PCI Boot Configurations
> +      // PCI firmware spec - 4.6.5
> +      case (5) {
> +          // Always allow OS to rebalance
> +          return (0x01)
> +        }
> +
> +      // Function 7: Naming a PCI or PCI Express Device Under
> +      //             Operating Systems
> +      // PCI firmware spec - 4.6.7
> +      case (7) {
> +          // Verify revision 2
> +          if (LEqual (Arg1, 2)) {
> +            // PCI Express Slot Parsing
> +            Return ( Package (2) {
> +              1,            // Instance of the enumeration
> +              "PCIe Slot 1" // String name which matches the label on the chassis
> +            })
> +          }
> +        }
> +      }
> +    }
> +    return (Buffer() { 0 })
> +  }
> +
> +  // Root Port 0 Device within the Root Complex.
> +  Device (RP0) {
> +    Name (_ADR, 0)  // Device 0, Function 0
> +    Name (_S0W, 4)  // Supports wake
> +  }
> +
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> new file mode 100644
> index 000000000000..0bdc78080d26
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> @@ -0,0 +1,106 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +OperationRegion (GLBL, SystemMemory, 0x10817000, 0x10)
> +Field (GLBL, AnyAcc, Nolock, Preserve)
> +{
> +  Offset (0),       // Miscellaneous Dynamic Registers:
> +  SIGN, 32,         // Global Page Signature 'GLBL'
> +  REVN, 8,          // Revision
> +      , 8,          // Reserved
> +      , 8,          // Reserved
> +      , 8,          // Reserved
> +  M0ID, 8,          // MAC 0 ID
> +  MC0V, 8,          // MAC 0 Valid
> +  MC0L, 32,         // MAC Address 0 Low
> +  MC0H, 16,         // MAC Address 0 High
> +}
> +
> +Device (CPU0)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +Device (CPU1)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +Device (CPU2)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +Device (CPU3)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +// Timers HAL extension
> +Device (EPIT)
> +{
> +  Name (_HID, "NXP0101")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +// Platform Extension Plugin
> +Device (PEP0)
> +{
> +  Name (_HID, "NXP0102")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // CCM request 1
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 119 }
> +
> +      // CCM request 2
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 120 }
> +
> +      // GPC request 1
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 121 }
> +
> +      // UART1
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> new file mode 100644
> index 000000000000..22bab0cff575
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> @@ -0,0 +1,85 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (PWM1)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (PWM2)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02084000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 116 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (PWM3)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02088000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 117 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (PWM4)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x4)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0208C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 118 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> new file mode 100644
> index 000000000000..fad33d2e9d6c
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> @@ -0,0 +1,133 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// uSDHC1
> +Device (SDH1)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  // Child node to represent the only SD/MMC slot on this SD/MMC bus
> +  // In theory an SDHC can be connected to multiple SD/MMC slots at
> +  // the same time, but only 1 device will be selected and active at
> +  // a time
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC2
> +Device (SDH2)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC3
> +Device (SDH3)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC4
> +Device (SDH4)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x4)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0219C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 57 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> new file mode 100644
> index 000000000000..f68a7f306ecc
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> @@ -0,0 +1,103 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (SPI1)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02008000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 63 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI2)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI3)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02010000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 65 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI4)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x4)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02014000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 66 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI5)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x5)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02018000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 67 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> new file mode 100644
> index 000000000000..83975792bcaf
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> @@ -0,0 +1,33 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (TREE)
> +{
> +  Name (_HID, "NXP010F")
> +  Name (_CID, "TrEECSMP")
> +  Name (_UID, 0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // OP-TEE Shared memory area.
> +      // Needs to match: PcdTrustZoneSharedMemoryBase, PcdTrustZoneSharedMemorySize
> +      MEMORY32FIXED (ReadWrite, 0x12800000, 0x00200000, )
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> new file mode 100644
> index 000000000000..58181ee9eda7
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> @@ -0,0 +1,60 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// Advertise support for PSCI
> +#define FADT_ARM_BOOT_ARCH       0x01
> +
> +char FACP[268] = {
> +  0x46, 0x41, 0x43, 0x50,                         // Signature : 'FACP'
> +  0x0C, 0x01, 0x00, 0x00,                         // Length
> +  0x05,                                           // Revision
> +  0x00,                                           // Checksum
> +  0x4E, 0x58, 0x50, 0x4D, 0x58, 0x36,             // OEMID : 'NXPMX6'
> +  0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, // OEMTABLE : 'EDK2'
> +  0x01, 0x00, 0x00, 0x00,                         // OEM Revision
> +  0x4D, 0x53, 0x46, 0x54,                         // CreatorID : 'MSFT'
> +  0x01, 0x00, 0x00, 0x00,                         // Creator revision
> +  0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x04, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C,
> +  0x00, 0x00, 0x21, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, FADT_ARM_BOOT_ARCH,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (void *) &FACP;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> new file mode 100644
> index 000000000000..1c382306c780
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> @@ -0,0 +1,120 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Library/AcpiLib.h>
> +
> +#include <Platform.h>
> +#include <iMX6.h>
> +
> +#define GICC_BASE                 FixedPcdGet64 (PcdGicInterruptInterfaceBase)
> +#define GICD_BASE                 FixedPcdGet64 (PcdGicDistributorBase)
> +
> +// Virtualization related fields. Not supported on IMX6
> +#define GICH_BASE                 0
> +#define GICV_BASE                 0
> +#define VGIC_MAINT_INT            0
> +#define PMU_INTERRUPT             0
> +
> +#pragma pack(push, 1)
> +typedef struct {
> +  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
> +  EFI_ACPI_6_0_GIC_STRUCTURE GicC[FixedPcdGet32 (PcdCoreCount)];
> +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE GicD;
> +} ACPI_6_0_MADT_STRUCTURE;
> +#pragma pack(pop)
> +
> +ACPI_6_0_MADT_STRUCTURE Madt = {
> +  {
> +    {
> +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, // Signature
> +      sizeof (ACPI_6_0_MADT_STRUCTURE),                       // Length
> +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,  // Revision
> +      0,                                                      // Checksum
> +      EFI_ACPI_OEM_ID,                                        // OemId[6]
> +      EFI_ACPI_OEM_TABLE_ID,                                  // OemTableId
> +      EFI_ACPI_OEM_REVISION,                                  // OemRevision
> +      EFI_ACPI_CREATOR_ID,                                    // CreatorId
> +      EFI_ACPI_CREATOR_REVISION                               // CreatorRevision
> +    },
> +    0,      // LocalApicAddress
> +    0       // Flags
> +  },
> +  {
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (0,                        // GicId
> +                                      0x000,                     // AcpiCpuUid
> +                                      0x000,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +#if FixedPcdGet32(PcdCoreCount) > 1
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (1,                        // GicId
> +                                      0x001,                     // AcpiCpuUid
> +                                      0x001,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +#if FixedPcdGet32(PcdCoreCount) > 2
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (2,                        // GicId
> +                                      0x002,                     // AcpiCpuUid
> +                                      0x002,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (3,                        // GicId
> +                                      0x003,                     // AcpiCpuUid
> +                                      0x003,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +#endif
> +#endif
> +  },
> +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (0x0,                   // GicDistHwId
> +                                     GICD_BASE,             // GicDistBase
> +                                     IC_DIST_VECTOR_BASE,   // GicDistVector
> +                                     EFI_ACPI_6_0_GIC_V1    // GicVersion
> +                                    )
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&Madt;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> new file mode 100644
> index 000000000000..3e9d163cb52e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> @@ -0,0 +1,92 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Platform.h>
> +
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#include "iMX6.h"

#include <iMX6.h>

> +#include "../Drivers/PciExpress/iMX6PciExpress.h"

That include file should live in iMX6Pkg/Include/Drivers and be
included as
#include <Drivers/iMX6PciExpress.h>

Apply these patterns throughout.

> +
> +#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
> +
> +// Size in bytes a single bus consumes in ECAM space
> +// Configuration size = 4K
> +// Max device = 32
> +// Max function = 8
> +// Max bus size = 4K * 32 * 8
> +#define ECAM_BUS_ADDR_SIZE  (1 << 20)
> +
> +// Provide 2 differenct base PCI space address. The first list would represent
> +// the host config space and the second list would be the device config space.
> +// Windows is expected to be able to parse the information.
> +#define NUM_PCI 2
> +
> +// MCFG structure
> +// PCI Firmware specification Table 4-2
> +#pragma pack(push, 1)
> +
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER Header;
> +  UINT64                      Reserved;
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE AllocationStructure[NUM_PCI];
> +} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;
> +
> +#pragma pack(pop)
> +
> +//
> +// Multiple APIC Description Table
> +//
> +EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg = {
> +  {
> +    EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE),
> +    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
> +    0x00,                           // Checksum will be updated at runtime
> +    EFI_ACPI_OEM_ID,                // OEMID
> +    EFI_ACPI_OEM_TABLE_ID,          // OEM Table ID
> +    EFI_ACPI_OEM_MCFG_REVISION,     // OEM Revision
> +    EFI_ACPI_CREATOR_ID,            // Creator ID
> +    EFI_ACPI_CREATOR_REVISION,      // Creator revision
> +  },
> +  0x00,                             // Reserved
> +
> +  {
> +    // PCIe Host
> +    {
> +      PCIE_HOST_CONFIG_BASE_REG,        // PCIE Host Config Base Address
> +      0x00,                             // PciSegmentGroupNumber (_SEG)
> +      0x00,                             // StartBusNumber
> +      0x00,                             // EndBusNumber
> +      0x00000000                        // Reserved
> +    },
> +
> +    // PCIe Device
> +    {
> +      PCIE_DEVICE_CONFIG_BASE_REG - ECAM_BUS_ADDR_SIZE,  // BaseAddress
> +      0x00,                              // PciSegmentGroupNumber (_SEG)
> +      0x01,                              // StartBusNumber
> +      0x01,                              // EndBusNumber
> +      0x00000000                         // Reserved
> +    }
> +  }
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&Mcfg;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> new file mode 100644
> index 000000000000..603422a737c4
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> @@ -0,0 +1,95 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include "Platform.h"

Same thing, but here resolved via iMXPlatformPkg.dec.

/
    Leif

> +#include "iMX6.h"
> +
> +// Ensure proper structure formats
> +#pragma pack (1)
> +
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER Header;
> +  UINT8 Interface_Type;
> +  UINT8 Reserved1[3];
> +  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> +  UINT8 Interrupt_Type;
> +  UINT8 PCAT_compatible_IRQ;
> +  UINT32 Interrupt;
> +  UINT8 Baud_Rate;
> +  UINT8 Parity;
> +  UINT8 Stop_Bits;
> +  UINT8 Flow_Control;
> +  UINT8 Terminal_Type;
> +  UINT8 Reserved2;
> +  UINT16 PCI_Device_ID;
> +  UINT16 PCI_Vender_ID;
> +  UINT8 PCI_Bus;
> +  UINT8 PCI_Device;
> +  UINT8 PCI_Function;
> +  UINT32 PCI_Flags;
> +  UINT8 PCI_Segment;
> +  UINT32 Reserved3;
> +} EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE;
> +
> +#pragma pack ()
> +
> +EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE SPCR = {
> +  {
> +    EFI_ACPI_5_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE),
> +    0x02,
> +    0x00,                           // Checksum will be updated at runtime
> +    EFI_ACPI_OEM_ID,
> +    EFI_ACPI_OEM_TABLE_ID,
> +    EFI_ACPI_OEM_REVISION,
> +    EFI_ACPI_CREATOR_ID,
> +    EFI_ACPI_CREATOR_REVISION,
> +  },
> +  DBG_PORT_SUBTYPE_IMX6,   // Serial Interface type = Serial Port Subtypes of the DBG2
> +  {0x00, 0x00, 0x00},      // Reserved
> +
> +  // ACPI Generic Address Structure. Set to all zeroes to disable console redirection
> +  {
> +    EFI_ACPI_5_0_SYSTEM_MEMORY,         // AddressSpaceId: SystemMemory
> +    0x20,                               // RegisterBitWidth
> +    0,                                  // RegisterBitOffset
> +    EFI_ACPI_5_0_DWORD,                 // AccessSize
> +    (UINT64)CSP_BASE_REG_PA_UART3       // Address UART3
> +  },
> +  0x08,        // Interrupt Type = Bit[3] ARMH GIC interrupt. 0 means not supported.
> +  0x00,        // IRQ. Not used since Bit[0] of the Interrupt Type field is not set
> +  0x3c,        // Global System Interrupt used by the UART (UART3 interrupt 60)
> +  0x07,        // Baud Rate
> +  0x00,        // No Parity
> +  0x01,        // One Stop Bit
> +  0x00,        // Flow Control: None
> +  0x03,        // Terminal Type: ANSI
> +  0X00,        // Reserved
> +  0xffff,      // 0xFFFF - not a PCI device
> +  0xffff,      // 0xFFFF - not a PCI device
> +  0x00,        // Bus Number. 0 - not a PCI device
> +  0x00,        // Device Number. 0 - not a PCI device
> +  0x00,        // Function. 0 - not a PCI device
> +  0x00000000,  // PCI Flags
> +  0x00,        // PCI Segment
> +  0x00000000,  //Reserved
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&SPCR;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> new file mode 100644
> index 000000000000..a5abb2bf15d1
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> @@ -0,0 +1,53 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <IndustryStandard/Tpm2Acpi.h>
> +
> +#include <Library/PcdLib.h>
> +
> +#include <Platform.h>
> +#include "iMX6.h"
> +
> +// Definition is missing from MdePkg/Include/IndustryStandard/Tpm2Acpi.h
> +#ifdef EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE
> +#error "EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE is defined elsewhere."
> +#else
> +#define EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE 9
> +#endif
> +
> +EFI_TPM2_ACPI_TABLE Tpm2Table = {
> +  {
> +    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
> +    sizeof (EFI_TPM2_ACPI_TABLE),
> +    EFI_TPM2_ACPI_TABLE_REVISION,
> +    0,                          // Checksum will be updated at runtime
> +    EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
> +    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
> +    EFI_ACPI_OEM_REVISION,      // OEM revision number
> +    EFI_ACPI_CREATOR_ID,        // Creator vendor ID
> +    EFI_ACPI_CREATOR_REVISION,  // Creator revision number
> +  },
> +  0,                            // Flags
> +  FixedPcdGet64 (PcdTpm2AcpiBufferBase),  // Control Area
> +  // StartMethod
> +  EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE,
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&Tpm2Table;
> +}
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 20/27] Silicon/NXP: Add i.MX6 Board init library
  2018-09-21  8:26 ` [PATCH edk2-platforms 20/27] Silicon/NXP: Add i.MX6 Board init library Chris Co
@ 2018-12-14 20:12   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 20:12 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:12AM +0000, Chris Co wrote:
> This adds support for board initialization which is common to
> NXP i.MX6-based platforms.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S   |  89 ++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c      | 110 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c        |  88 ++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c | 107 +++++++++++++++++++
>  4 files changed, 394 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
> new file mode 100644
> index 000000000000..979e98888a6b
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
> @@ -0,0 +1,89 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +#include <AsmMacroIoLib.h>
> +#include <AutoGen.h>
> +#include <Base.h>
> +#include <Library/ArmLib.h>
> +#include <Library/PcdLib.h>

Are all of these really used?

> +
> +.text
> +.align 2
> +
> +// GIC Cpu interface
> +#define ARM_GIC_ICCICR  0x00  // CPU Interface Control Register
> +#define ARM_GIC_ICCPMR  0x04  // Interrupt Priority Mask Register
> +#define ARM_GIC_ICCBPR  0x08  // Binary Point Register
> +#define ARM_GIC_ICCIAR  0x0C  // Interrupt Acknowledge Register
> +#define ARM_GIC_ICCEIOR 0x10  // End Of Interrupt Register
> +#define ARM_GIC_ICCRPR  0x14  // Running Priority Register
> +#define ARM_GIC_ICCPIR  0x18  // Highest Pending Interrupt Register
> +#define ARM_GIC_ICCABPR 0x1C  // Aliased Binary Point Register
> +#define ARM_GIC_ICCIDR  0xFC  // Identification Register

Why do you need to access these directly from asm?
Hmm, they also look unused?

> +
> +// SRC (System Reset Controller) register offsets & masks
> +#define IMX6_SRC_SCR     0x0
> +#define IMX6_SRC_GPR1    0x20
> +#define IMX6_SRC_GPR2    0x24
> +#define IMX6_SRC_GPR3    0x28
> +#define IMX6_SRC_GPR4    0x2C
> +#define IMX6_SRC_GPR5    0x30
> +#define IMX6_SRC_GPR6    0x34
> +#define IMX6_SRC_GPR7    0x38
> +#define IMX6_SRC_GPR8    0x3C
> +#define IMX6_SRC_GPR9    0x40
> +#define IMX6_SRC_GPR10   0x44

As do these?

> +
> +GCC_ASM_EXPORT(ArmPlatformPeiBootAction)
> +GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)
> +GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)
> +GCC_ASM_EXPORT(ArmPlatformGetCorePosition)
> +
> +//UINTN
> +//ArmPlatformGetPrimaryCoreMpId (
> +//  VOID
> +//  );
> +ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
> +  MOV32 (r0, FixedPcdGet32 (PcdArmPrimaryCore))
> +  ldr   r0, [r0]
> +  bx    lr
> +
> +//UINTN
> +//ArmPlatformIsPrimaryCore (
> +//  IN UINTN MpId
> +//  );
> +ASM_PFX(ArmPlatformIsPrimaryCore):
> +  mrc   p15,0,r0,c0,c0,5
> +  ands  r0,r0,#3
> +  moveq r0,#1
> +  movne r0,#0

Sprinkle some spaces after commas above please.

> +  bx    lr
> +
> +//UINTN
> +//ArmPlatformGetCorePosition (
> +//  IN UINTN MpId
> +//  );
> +ASM_PFX(ArmPlatformGetCorePosition):
> +  and   r0, r0, #ARM_CORE_MASK
> +  bx    lr
> +
> +ASM_PFX(ArmPlatformPeiBootAction):
> +  // enable unaligned access
> +  mrc   p15, 0, r1, c1, c0, 0
> +  bic   r1, r1, #0x2
> +  mcr   p15, 0, r1, c1, c0, 0
> +  isb
> +  bx r14
> +
> +ASM_FUNCTION_REMOVE_IF_UNREFERENCED
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
> new file mode 100644
> index 000000000000..a2b601ec9c52
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
> @@ -0,0 +1,110 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +
> +#include "iMX6.h"

<>

> +
> +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS  8
> +
> +/**
> +  Return the Virtual Memory Map of your platform
> +
> +  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
> +  on your platform.
> +
> +  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR describing
> +                                    a Physical-to-Virtual Memory mapping. This
> +                                    array must be ended by a zero-filled entry
> +
> +**/
> +VOID
> +ArmPlatformGetVirtualMemoryMap (
> +  IN ARM_MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap
> +  )
> +{
> +  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
> +  UINTN                         Index = 0;
> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
> +
> +  ASSERT (VirtualMemoryMap != NULL);
> +
> +  DEBUG ((DEBUG_VERBOSE, "Enter: ArmPlatformGetVirtualMemoryMap\n"));
> +
> +  VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR *)AllocatePages (
> +                         EFI_SIZE_TO_PAGES (sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
> +                             MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
> +  if (VirtualMemoryTable == NULL) {
> +    return;
> +  }
> +
> +  CacheAttributes = DDR_ATTRIBUTES_CACHED;
> +  DEBUG ((DEBUG_VERBOSE, "CacheAttributes=0x%d\n", CacheAttributes));
> +
> +  // SOC registers region 1 (0x00100000 size 0x00C00000)
> +  VirtualMemoryTable[Index].PhysicalBase   = SOC_REGISTERS_PHYSICAL_BASE1;
> +  VirtualMemoryTable[Index].VirtualBase    = SOC_REGISTERS_PHYSICAL_BASE1;
> +  VirtualMemoryTable[Index].Length         = SOC_REGISTERS_PHYSICAL_LENGTH1;
> +  VirtualMemoryTable[Index].Attributes     = SOC_REGISTERS_ATTRIBUTES;
> +
> +  // PCIE Registers (0x01000000 size 0x01000000)
> +  VirtualMemoryTable[++Index].PhysicalBase = PCIE_REGISTERS_PHYSICAL_BASE;
> +  VirtualMemoryTable[Index].VirtualBase    = PCIE_REGISTERS_PHYSICAL_BASE;
> +  VirtualMemoryTable[Index].Length         = PCIE_REGISTERS_PHYSICAL_LENGTH;
> +  VirtualMemoryTable[Index].Attributes     = SOC_REGISTERS_ATTRIBUTES;
> +
> +  // SOC registers region 2 (excluding EIM) (0x02000000 size 0x00A00000)
> +  VirtualMemoryTable[++Index].PhysicalBase = SOC_REGISTERS_PHYSICAL_BASE2;
> +  VirtualMemoryTable[Index].VirtualBase    = SOC_REGISTERS_PHYSICAL_BASE2;
> +  VirtualMemoryTable[Index].Length         = SOC_REGISTERS_PHYSICAL_LENGTH2;
> +  VirtualMemoryTable[Index].Attributes     = SOC_REGISTERS_ATTRIBUTES;
> +
> +  // Framebuffer
> +  VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet32 (PcdFrameBufferBase);
> +  VirtualMemoryTable[Index].VirtualBase    = FixedPcdGet32 (PcdFrameBufferBase);
> +  VirtualMemoryTable[Index].Length         = FixedPcdGet32 (PcdFrameBufferSize);
> +  VirtualMemoryTable[Index].Attributes     = DDR_ATTRIBUTES_UNCACHED;
> +
> +  // Boot (UEFI) DRAM region (kernel.img & boot working DRAM) (0x10800000 size 0x001D0000)
> +  VirtualMemoryTable[++Index].PhysicalBase   = BOOT_IMAGE_PHYSICAL_BASE;
> +  VirtualMemoryTable[Index].VirtualBase      = BOOT_IMAGE_PHYSICAL_BASE;
> +  VirtualMemoryTable[Index].Length           = BOOT_IMAGE_PHYSICAL_LENGTH;
> +  VirtualMemoryTable[Index].Attributes       = BOOT_IMAGE_ATTRIBUTES;
> +
> +  // TrustZone Shared Memory
> +  VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdTrustZoneSharedMemoryBase);
> +  VirtualMemoryTable[Index].VirtualBase    = FixedPcdGet64 (PcdTrustZoneSharedMemoryBase);
> +  VirtualMemoryTable[Index].Length         = FixedPcdGet64 (PcdTrustZoneSharedMemorySize);
> +  VirtualMemoryTable[Index].Attributes     = CacheAttributes;
> +
> +  // Base SDRAM
> +  VirtualMemoryTable[++Index].PhysicalBase = PcdGet64 (PcdSystemMemoryBase);
> +  VirtualMemoryTable[Index].VirtualBase    = PcdGet64 (PcdSystemMemoryBase);
> +  VirtualMemoryTable[Index].Length         = PcdGet64 (PcdSystemMemorySize);
> +  VirtualMemoryTable[Index].Attributes     = CacheAttributes;
> +
> +  // End of Table
> +  VirtualMemoryTable[++Index].PhysicalBase = 0;
> +  VirtualMemoryTable[Index].VirtualBase    = 0;
> +  VirtualMemoryTable[Index].Length         = 0;
> +  VirtualMemoryTable[Index].Attributes     = (ARM_MEMORY_REGION_ATTRIBUTES)0;
> +
> +  ASSERT ((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
> +
> +  *VirtualMemoryMap = VirtualMemoryTable;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
> new file mode 100644
> index 000000000000..3f45527981a7
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
> @@ -0,0 +1,88 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <IndustryStandard/Tpm20.h>
> +#include <IndustryStandard/Tpm2Acpi.h>
> +
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/SerialPortLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6BoardLib.h>
> +#include <iMX6Timer.h>
> +
> +VOID __DoNothing() {}
> +VOID SdhcInit () __attribute__ ((weak, alias ("__DoNothing")));
> +VOID EhciInit () __attribute__ ((weak, alias ("__DoNothing")));
> +VOID EnetInit () __attribute__ ((weak, alias ("__DoNothing")));
> +VOID I2cInit () __attribute__ ((weak, alias ("__DoNothing")));
> +VOID SpiInit () __attribute__ ((weak, alias ("__DoNothing")));
> +VOID PcieInit () __attribute__ ((weak, alias ("__DoNothing")));
> +VOID SetupAudio () __attribute__ ((weak, alias ("__DoNothing")));

This is very unidiomatic for EDK2.
It would be nicer to install a board-specific protocol that was
discovered here and returned a set of function pointers (and a
version?) which could then be called if populated.
And give this library its own .inf, that added a depex on the
board-specific protocol.

/
    Leif

> +
> +/**
> +  Initialize controllers that must setup at the early stage
> +**/
> +RETURN_STATUS
> +ArmPlatformInitialize (
> +  IN  UINTN                     MpId
> +  )
> +{
> +  if (!ArmPlatformIsPrimaryCore (MpId)) {
> +    return RETURN_SUCCESS;
> +  }
> +
> +  ImxClkPwrInit ();
> +
> +  // Initialize default UEFI debug port early so we can use its debug output
> +  SerialPortInitialize ();
> +  SerialPortWrite (
> +    (UINT8 *)SERIAL_DEBUG_PORT_INIT_MSG,
> +    (UINTN)sizeof (SERIAL_DEBUG_PORT_INIT_MSG));
> +
> +  // Initialize timer early on because the following init path will be calling
> +  // delay functions. PrePi.c calls ArmPlatformInitialize before it calls
> +  // TimerConstructor to initialize the timer.
> +  TimerConstructor ();
> +
> +  SdhcInit ();
> +  EhciInit ();
> +  EnetInit ();
> +  I2cInit ();
> +  SpiInit ();
> +  PcieInit ();
> +  SetupAudio ();
> +
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Return the current Boot Mode
> +
> +  This function returns the boot reason on the platform
> +
> +**/
> +EFI_BOOT_MODE
> +ArmPlatformGetBootMode (
> +  VOID
> +  )
> +{
> +  return BOOT_WITH_FULL_CONFIGURATION;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
> new file mode 100644
> index 000000000000..b59f9fe6f01f
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
> @@ -0,0 +1,107 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +
> +#include <Ppi/ArmMpCoreInfo.h>
> +
> +ARM_CORE_INFO iMX6Ppi[] = {
> +  {
> +    // Cluster 0, Core 0
> +    0x0, 0x0,
> +
> +    // MP Core MailBox Set/Get/Clear Addresses and Clear Value.
> +    // Not used with i.MX6, set to 0
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (UINT64)0
> +  },
> +
> +#if FixedPcdGet32(PcdCoreCount) > 1
> +  {
> +    // Cluster 0, Core 1
> +    0x0, 0x1,
> +
> +    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
> +    // Not used with i.MX6, set to 0
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (UINT64)0
> +  },
> +#endif // FixedPcdGet32(PcdCoreCount) > 1
> +
> +#if FixedPcdGet32(PcdCoreCount) > 2
> +  {
> +    // Cluster 0, Core 2
> +    0x0, 0x2,
> +
> +    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
> +    // Not used with i.MX6, set to 0
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (UINT64)0
> +  },
> +
> +  {
> +    // Cluster 0, Core 3
> +    0x0, 0x3,
> +
> +    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
> +    // Not used with i.MX6, set to 0
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (EFI_PHYSICAL_ADDRESS)0x00000000,
> +    (UINT64)0
> +  }
> +#endif // FixedPcdGet32(PcdCoreCount) > 2
> +};
> +
> +EFI_STATUS
> +PrePeiCoreGetMpCoreInfo (
> +  OUT UINTN                   *CoreCount,
> +  OUT ARM_CORE_INFO           **ArmCoreTable
> +  )
> +{
> +  // Only support one cluster
> +  *CoreCount    = sizeof (iMX6Ppi) / sizeof (ARM_CORE_INFO);
> +  ASSERT (*CoreCount == FixedPcdGet32 (PcdCoreCount));
> +  *ArmCoreTable = iMX6Ppi;
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_GUID mArmMpCoreInfoPpiGuid = ARM_MP_CORE_INFO_PPI_GUID;
> +ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo };
> +EFI_PEI_PPI_DESCRIPTOR      gPlatformPpiTable[] = {
> +  {
> +    EFI_PEI_PPI_DESCRIPTOR_PPI,
> +    &mArmMpCoreInfoPpiGuid,
> +    &mMpCoreInfoPpi
> +  }
> +};
> +
> +VOID
> +ArmPlatformGetPlatformPpiList (
> +  OUT UINTN                   *PpiListSize,
> +  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
> +  )
> +{
> +  *PpiListSize = sizeof (gPlatformPpiTable);
> +  *PpiList = gPlatformPpiTable;
> +}
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 21/27] Silicon/NXP: Add i.MX6 PCIe DXE driver
  2018-09-21  8:26 ` [PATCH edk2-platforms 21/27] Silicon/NXP: Add i.MX6 PCIe DXE driver Chris Co
@ 2018-12-14 21:59   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 21:59 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:13AM +0000, Chris Co wrote:
> This adds DXE driver support for PCIe on NXP i.MX6 SoCs.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c   | 1139 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h   |  145 +++
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf |   66 ++
>  3 files changed, 1350 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
> new file mode 100644
> index 000000000000..424ab2d77227
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
> @@ -0,0 +1,1139 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/PciIo.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMX6IoMux.h>
> +#include "iMX6PciExpress.h"
> +
> +PCI_RESOURCE PcieResource[] = {
> +  // Memory resource
> +  {
> +    PCIE_MEMORY_SPACE_BASE,
> +    PCIE_MEMORY_SPACE_SIZE,
> +    PCIE_MEMORY_SPACE_BASE
> +  },
> +};
> +
> +// Pcie read and write function
> +EFI_STATUS
> +PciePciWrite (
> +  IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> +  IN UINTN Address,
> +  IN UINTN Count,
> +  IN VOID *Buffer
> +  );
> +
> +EFI_STATUS
> +PciePciRead (
> +  IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> +  IN UINTN Address,
> +  IN UINTN Count,
> +  IN VOID *Buffer
> +  );
> +
> +// Internal Address Translation Unit configuration table. Map the Pcie device
> +// configuration baesd on configuration. Pci IO space is not supported on
> +// Windows. Memory space segment is just mapped back to the same address.
> +//
> +// The following table is used to setup basic translation setting on various
> +// ATU (Address Translation Unit). The ATU is responsible to retranslate
> +// address for inbound and outbound message.
> +//
> +// Address match mode address translation is based on the following formula :
> +//     Address = Address - Base Address + Target Address
> +//
> +// There really isnt a need to retranslate the address for iMX6 however proceed
> +// the program the ATU to for configuration and memory message.
> +IATU_SETTINGS iMX6iAtuSettings[] = {
> +  // Configuration message
> +  {
> +    OUTBOUND,
> +    0,
> +    CFG0_TYPE,
> +    PCIE_DEVICE_CONFIG_BASE_REG,
> +    0,
> +    PCIE_DEVICE_CONFIG_BASE_REG + PCIE_DEVICE_CONFIG_SIZE - 1,
> +    PCIE_DEVICE_CONFIG_BASE_REG,
> +    0,
> +    REGION_ENABLE,
> +  },
> +
> +  // Memory message
> +  {
> +    OUTBOUND,
> +    2,
> +    MEMORY_TYPE,
> +    PCIE_MEMORY_SPACE_BASE,
> +    0,
> +    PCIE_MEMORY_SPACE_BASE + PCIE_MEMORY_SPACE_SIZE - 1,
> +    PCIE_MEMORY_SPACE_BASE,
> +    0,
> +    REGION_ENABLE,
> +  },
> +};
> +
> +VOID
> +PcieSetupiAtu (
> +  IN  IATU_SETTINGS   *SettingsPtr
> +  )
> +{
> +  volatile CSP_PCIE_PL_REGS *pPortLogicRegs;

The volatile pointer antipattern again.
You're using it for register offsets here, so having it of
CSP_PCIE_PL_REGS * is fine, I guess, but the volatile has no effect.
And please drop the Hungarian notation.

Applies throughout.

> +
> +  ASSERT (SettingsPtr->RegionIndex < MAX_iATU_REGION);
> +  pPortLogicRegs = (CSP_PCIE_PL_REGS *)PCIE_CTRL_PORT_LOGIG_BASE_REG;
> +
> +  // Program specific ATU region
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATUVR,
> +    (SettingsPtr->RegionDirection << 31 | SettingsPtr->RegionIndex));
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURC2,
> +    REGION_DISABLE);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURLBA,
> +    SettingsPtr->LowerBaseAddr);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURUBA,
> +    SettingsPtr->UpperBaseAddr);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURLA,
> +    SettingsPtr->LimitAddr);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURLTA,
> +    SettingsPtr->LowerTargetAddr);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURUTA,
> +    SettingsPtr->UpperTargetAddr);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURC1,
> +    SettingsPtr->Type);
> +
> +  MmioWrite32 (
> +    (UINTN)&pPortLogicRegs->PCIE_PL_iATURC2,
> +    SettingsPtr->State);
> +}
> +
> +VOID
> +PcieSetupiAtuSettings (
> +  VOID
> +  )
> +{
> +  UINT32 i;
> +
> +  // Initialize internal Address Translation Unit based on settings specify
> +  // in iMX6iAtuSettings table.
> +  for (i = 0; i < ARRAYSIZE (iMX6iAtuSettings); ++i) {
> +    PcieSetupiAtu (&iMX6iAtuSettings[i]);
> +  }
> +
> +  return;
> +}
> +
> +EFI_STATUS
> +PcieSetPhyState (
> +  IN  BOOLEAN   State
> +  )
> +{
> +  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcGprRegisters;
> +  IMX_IOMUXC_GPR1_REG                 Gpr1Reg;
> +
> +  pIoMuxcGprRegisters = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
> +  Gpr1Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR1);
> +  if (State == TRUE) {
> +#if defined(CPU_IMX6DQP)
> +    Gpr1Reg.PCIE_SW_RST = 0;
> +#endif
> +    Gpr1Reg.REF_SSP_EN = 1;     // Enable Pcie PHY
> +    Gpr1Reg.TEST_POWERDOWN = 0; // Power down is not requested
> +  } else {
> +    Gpr1Reg.REF_SSP_EN = 0;     // Disable Pcie PHY
> +    Gpr1Reg.TEST_POWERDOWN = 1; // Power down is requested
> +  }
> +  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR1, Gpr1Reg.AsUint32);
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +PcieSetupInitSetting (
> +  VOID
> +  )
> +{
> +  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcGprRegisters;
> +  EFI_STATUS                          Status;
> +  IMX_IOMUXC_GPR1_REG                 Gpr1Reg;
> +  IMX_IOMUXC_GPR12_REG                Gpr12Reg;
> +  IMX_IOMUXC_GPR8_REG                 Gpr8Reg;
> +
> +  pIoMuxcGprRegisters = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
> +
> +  // If Pcie PHY is already enabled we are in an unexpected state, just exit
> +  // and assume a bootloader has already setup Pcie and assigned resources.
> +  Gpr1Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR1);
> +  if (Gpr1Reg.REF_SSP_EN == 1) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Disable the PHY first, without this Pci link randomly does not come up
> +  Status = PcieSetPhyState (FALSE);
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to disable Pcie PHY\n");
> +    goto Exit;
> +  }
> +
> +  // First configure Pcie and Pcie PHY default setting
> +  Gpr12Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR12);
> +  Gpr12Reg.APP_LTSSM_ENABLE = 0;          // Set application not ready
> +  Gpr12Reg.DIA_STATUS_BUS_SELECT = 0xB;   // Debug functionality
> +  Gpr12Reg.DEVICE_TYPE = 0x4;             // Set to RC mode
> +  Gpr12Reg.LOS_LEVEL = 0x9;               // Set to 0x9 per reference manual
> +  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR12, Gpr12Reg.AsUint32);
> +
> +  // Gen1 | Gen2 3p5 | Gen2 6 | Swing full 127 | Swing low 127

Can you expand this comment a bit? I genuinely have no idea what this means.

> +  Gpr8Reg.PCS_TX_DEEMPH_GEN1 = 0;
> +  Gpr8Reg.PCS_TX_DEEMPH_GEN2_3P5DB = 0;
> +  Gpr8Reg.PCS_TX_DEEMPH_GEN2_6DB = 20;
> +  Gpr8Reg.PCS_TX_SWING_FULL = 127;
> +  Gpr8Reg.PCS_TX_SWING_LOW = 127;
> +  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR8, Gpr8Reg.AsUint32);
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieSetClockGate (
> +  IN  IMX_CLOCK_GATE_STATE  State
> +  )
> +{
> +  ImxClkPwrSetClockGate (IMX_PCIE_ROOT_ENABLE, State);
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +PcieVerifyClocks (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegisters;
> +  IMX_CCM_ANALOG_PLL_ENET_REG         CcmAnalogPllReg;
> +
> +  pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
> +  CcmAnalogPllReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_ENET);
> +  if ((CcmAnalogPllReg.POWERDOWN == 0) &&
> +      (CcmAnalogPllReg.BYPASS == 0) &&
> +      (CcmAnalogPllReg.ENABLE_125M == 1) &&
> +      (CcmAnalogPllReg.LOCK == 1)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
> +VOID
> +PcieEnablePerstLine (
> +  VOID
> +  )
> +{
> +  // Enable board specific PERST line if one is defined
> +  if (FixedPcdGet32 (PcdPcieResetGpio)) {
> +    ImxGpioWrite (
> +      FixedPcdGet32 (PcdPcieResetGpioBankNumber),
> +      FixedPcdGet32 (PcdPcieResetGpioIoNumber),
> +      IMX_GPIO_HIGH);
> +    gBS->Stall (20000);
> +  }
> +}
> +
> +EFI_STATUS
> +PcieSetupPciBridge (
> +  VOID
> +  )
> +{
> +  UINT8 classCode[0];

c -> C

Also, size 0?

> +
> +  // Setup the bridge class
> +  classCode[0] = PCI_IF_BRIDGE_P2P;
> +  classCode[1] = PCI_CLASS_BRIDGE_P2P;
> +  classCode[2] = PCI_CLASS_BRIDGE;
> +
> +  return PciePciWrite (
> +           EfiPciIoWidthUint8,
> +           PCIE_HOST_CONFIG_BASE_REG + PCI_CLASSCODE_OFFSET,
> +           3,
> +           classCode);
> +}
> +
> +EFI_STATUS
> +PcieSetLinkStatus (
> +  IN  BOOLEAN   State
> +  )
> +{
> +  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcGprRegisters;
> +  IMX_IOMUXC_GPR12_REG                Gpr12Reg;
> +
> +  pIoMuxcGprRegisters = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS;
> +  Gpr12Reg.AsUint32 = MmioRead32 ((UINTN)&pIoMuxcGprRegisters->GPR12);
> +  if (State == TRUE) {
> +    Gpr12Reg.APP_LTSSM_ENABLE = 1; // Enable link
> +  } else {
> +    Gpr12Reg.APP_LTSSM_ENABLE = 0; // Disable link
> +  }
> +  MmioWrite32 ((UINTN)&pIoMuxcGprRegisters->GPR12, Gpr12Reg.AsUint32);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +BOOLEAN
> +PcieIsLinkUp (
> +  VOID
> +  )
> +{
> +  volatile CSP_PCIE_PL_REGS   *pPortLogicRegs;
> +  UINT32                      Debug1Reg;
> +
> +  pPortLogicRegs = (CSP_PCIE_PL_REGS *)PCIE_CTRL_PORT_LOGIG_BASE_REG;
> +  Debug1Reg = MmioRead32 ((UINTN)&pPortLogicRegs->PCIE_PL_DEBUG1);
> +  return (Debug1Reg & PCIE_PL_DEBUG1_PHY_LINK_UP) ? TRUE : FALSE;

I would prefer this to be

  if (Debug1Reg & PCIE_PL_DEBUG1_PHY_LINK_UP) {
    return TRUE;
  }

  return FALSE;

> +}
> +
> +EFI_STATUS
> +PcieWaitForLink (
> +  VOID
> +  )
> +{
> +  UINT32    Counter;
> +  BOOLEAN   LinkStatus;
> +
> +  Counter = 200;
> +  LinkStatus = PcieIsLinkUp ();
> +
> +  // To optimize boot time, consider lowering timeout value
> +  while (LinkStatus == FALSE && Counter > 0) {
> +    --Counter;

Counter--;

> +    gBS->Stall (1000);
> +    LinkStatus = PcieIsLinkUp ();
> +  }
> +
> +  return (LinkStatus) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
> +}
> +
> +EFI_STATUS
> +PcieGetAlignAddress (
> +  IN  UINTN   Address,
> +  IN  UINTN   AlignmentSize,
> +  OUT UINTN   *AlignAddress
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  *AlignAddress = 0;
> +  if ((AlignmentSize & (AlignmentSize - 1)) != 0) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +  // Even though we do not add a (AlignmentSize + 1) to the incoming address
> +  // we would still align to the upper boundary as bit [19:00] is assumed to
> +  // be 0x000FFFFF per Pcie spec.

Why be clever when one can be simple?

> +  *AlignAddress = (Address) & ~(AlignmentSize - 1);

Can you use any of the ALIGN* macros in Base.h?

> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieGetPciConfigAddress (
> +  IN  UINTN   BusNumber,
> +  IN  UINTN   DevNumber,
> +  IN  UINTN   FuncNumber,
> +  IN  UINTN   Register,
> +  OUT UINTN   *Address
> +  )
> +{
> +  UINT64      Offset;
> +  EFI_STATUS  Status;
> +
> +  // For now only support bus 0 and bus 1 with one device in each bus
> +  if (BusNumber == 0 && DevNumber == 0) {
> +    Offset = EFI_PCI_ADDRESS (BusNumber, DevNumber, FuncNumber, Register);
> +    *Address = PCIE_HOST_CONFIG_BASE_REG + Offset;
> +    Status = EFI_SUCCESS;
> +  } else if (BusNumber == 1 && DevNumber == 0) {
> +    Offset = EFI_PCI_ADDRESS (BusNumber, DevNumber, FuncNumber, Register);
> +    Offset -= EFI_PCI_ADDRESS (1, 0, FuncNumber, 0);
> +    *Address = PCIE_DEVICE_CONFIG_BASE_REG + Offset;
> +    Status = EFI_SUCCESS;
> +  } else {
> +    *Address = 0;
> +    Status = EFI_INVALID_PARAMETER;
> +  }
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PciePciRead (
> +  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
> +  IN  UINTN                       Address,
> +  IN  UINTN                       Count,
> +  OUT VOID                        *Buffer
> +  )
> +{
> +  UINT8       *pDest;
> +  EFI_STATUS  Status;
> +  UINTN       Stride;
> +
> +  pDest = (UINT8 *)Buffer;
> +  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
> +  Stride = (UINTN)1 << Width;
> +
> +  switch (Width) {
> +  case EfiPciWidthUint8:
> +    for (; Count > 0; --Count, pDest += Stride, Address += Stride) {

Where you're not specifically trying to affect evaluation order,
please use --suffix rather than prefix. Throughout.

> +      *pDest = MmioRead8 (Address);
> +    }
> +    Status = EFI_SUCCESS;
> +    break;
> +  case EfiPciWidthUint16:
> +    for (; Count > 0; --Count, pDest += Stride, Address += Stride) {
> +      *((UINT16 *)pDest) = MmioRead16 (Address);
> +    }
> +    Status = EFI_SUCCESS;
> +    break;
> +  case EfiPciWidthUint32:
> +    for (; Count > 0; --Count, pDest += Stride, Address += Stride) {
> +      *((UINT32 *)pDest) = MmioRead32 (Address);
> +    }
> +    Status = EFI_SUCCESS;
> +    break;
> +  default:
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PciePciWrite (
> +  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
> +  IN  UINTN                       Address,
> +  IN  UINTN                       Count,
> +  IN  VOID                        *Buffer
> +  )
> +{
> +  UINT8       *pSrc;
> +  EFI_STATUS  Status;
> +  UINTN       Stride;
> +
> +  pSrc = (UINT8 *)Buffer;
> +  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
> +  Stride = (UINTN)1 << Width;
> +
> +  switch (Width) {
> +  case EfiPciWidthUint8:
> +    for (; Count > 0; --Count, pSrc += Stride, Address += Stride) {
> +      MmioWrite8 (Address, *pSrc);
> +    }
> +    Status = EFI_SUCCESS;
> +    break;
> +  case EfiPciWidthUint16:
> +    for (; Count > 0; --Count, pSrc += Stride, Address += Stride) {
> +      MmioWrite16 (Address, *((UINT16 *)pSrc));
> +    }
> +    Status = EFI_SUCCESS;
> +    break;
> +  case EfiPciWidthUint32:
> +    for (; Count > 0; --Count, pSrc += Stride, Address += Stride) {
> +      MmioWrite32 (Address, *((UINT32 *)pSrc));
> +    }
> +    Status = EFI_SUCCESS;
> +    break;
> +  default:
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieDevicePresent (
> +  OUT PCI_TYPE00  *PciDevice,
> +  IN  UINTN       Bus,
> +  IN  UINTN       Device,
> +  IN  UINTN       Func
> +  )
> +{
> +  UINTN       Address;
> +  EFI_STATUS  Status;
> +
> +  // Create Pci address map in terms of Bus, Device, and Func
> +  Status = PcieGetPciConfigAddress (Bus, Device, Func, 0, &Address);
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_NOT_FOUND;
> +    goto Exit;
> +  }
> +
> +  // Read the Vendor ID register
> +  Status = PciePciRead (
> +             EfiPciWidthUint32,
> +             Address,
> +             1,
> +             PciDevice);
> +  if (!EFI_ERROR (Status) && (PciDevice->Hdr).VendorId != 0xffff) {
> +    // Read the entire config header for the device
> +    Status = PciePciRead (
> +               EfiPciWidthUint32,
> +               Address,
> +               sizeof (PCI_TYPE00) / sizeof (UINT32),
> +               PciDevice);
> +    if (EFI_ERROR (Status)) {
> +      PCIE_ERROR ("Failed to read Pci config space\n");
> +    }
> +  } else {
> +    PCIE_INFO ("No Pcie device found\n");
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieGetMemoryBarResource (
> +  IN  UINTN     BarSize,
> +  IN  UINTN     *BarAddress,
> +  IN  BOOLEAN   IsBridgeDevice
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if (BarSize > PcieResource->Size) {
> +    PCIE_ERROR ("Insufficient Pcie memory for 0x%08x (Current size 0x%08x)\n",
> +                BarSize,
> +                PcieResource->Size);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +
> +  *BarAddress = PcieResource->Curr;
> +
> +  if (IsBridgeDevice == FALSE) {
> +    PcieResource->Curr += BarSize;
> +    PcieResource->Size -= BarSize;
> +
> +    PCIE_INFO ("Allocating memory resource 0x%08x size 0x%08x\n",
> +               *BarAddress,
> +               BarSize);
> +  }
> +
> +  PCIE_INFO ("Current memory resource 0x%08x Size 0x%08x\n",
> +             PcieResource->Curr,
> +             PcieResource->Size);
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieParseAssignBar (
> +  IN  UINTN     BaseAddress,
> +  IN  UINTN     MaxBarIndex,
> +  IN  BOOLEAN   IsBridgeDevice
> +  )
> +{
> +  UINT32        AllOne32;
> +  UINT32        AllZero;
> +  UINTN         BarIndex;
> +  UINTN         BarOffset;
> +  UINTN         BarSize;
> +  UINTN         Originalvalue;
> +  UINTN         ResourceAddress;
> +  UINTN         ResponseValue;
> +  EFI_STATUS    Status;
> +
> +  AllZero = 0;
> +  AllOne32 = MAX_UINT32;
> +  for (BarOffset = 0x10, BarIndex = 0;
> +       BarOffset <= 0x24 && BarIndex < MaxBarIndex;
> +       BarOffset += sizeof (UINT32), ++BarIndex) {

Same for ++.

> +
> +    Status = PciePciRead (
> +               EfiPciWidthUint32,
> +               BaseAddress + BarOffset,
> +               1,
> +               &Originalvalue);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint32,
> +               BaseAddress + BarOffset,
> +               1,
> +               &AllOne32);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciRead (
> +               EfiPciWidthUint32,
> +               BaseAddress + BarOffset,
> +               1,
> +               &ResponseValue);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    // No support for IO memory
> +    // Refer : Pci Local Bus Specification (6.2.5.1)
> +    if ((ResponseValue & 0x01) == 0x01) {
> +      Status = PciePciWrite (
> +                 EfiPciIoWidthUint32,
> +                 BaseAddress + BarOffset,
> +                 1,
> +                 &Originalvalue);
> +      ASSERT_EFI_ERROR (Status);
> +      continue;
> +    }
> +
> +    // No support for prefetch memory
> +    if (((ResponseValue & 0x01) == 0x00) &&
> +        ((ResponseValue & 0x08) == 0x08)) {
> +      Status = PciePciWrite (
> +                 EfiPciIoWidthUint32,
> +                 BaseAddress + BarOffset,
> +                 1,
> +                 &Originalvalue);
> +      ASSERT_EFI_ERROR (Status);
> +      continue;
> +    }
> +
> +    BarSize = (~(ResponseValue & 0xFFFFFFF0)) + 1;
> +
> +    Status = PcieGetMemoryBarResource (
> +               BarSize,
> +               &ResourceAddress,
> +               IsBridgeDevice);
> +    if (EFI_ERROR (Status)) {
> +      PCIE_ERROR ("Failed to acquire BAR resource\n");
> +      goto Exit;
> +    }
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint32,
> +               BaseAddress + BarOffset,
> +               1,
> +               &ResourceAddress);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    // The subsequent BAR is the upper 32 bit address
> +    if (((ResponseValue & 0x04) == 0x04) &&
> +        (BarIndex + 1) < MaxBarIndex) {
> +      BarOffset += sizeof (UINT32);
> +      ++BarIndex;
> +
> +      Status = PciePciWrite (
> +                 EfiPciIoWidthUint32,
> +                 BaseAddress + BarOffset,
> +                 1,
> +                 &AllZero);
> +      ASSERT_EFI_ERROR (Status);
> +
> +      continue;
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieConfigureDevice (
> +  IN  PCI_TYPE00  PciDevice,
> +  IN  UINTN       BusNumber,
> +  IN  UINTN       DevNumber,
> +  IN  UINTN       FuncNumber
> +  )
> +{
> +  UINT32      AllZero;
> +  UINTN       BaseAddress;
> +  UINT8       FixedCacheLineSize;
> +  UINT16      PciCommand;
> +  EFI_STATUS  Status;
> +
> +  AllZero = 0;
> +
> +  PCIE_INFO (
> +    "Configuring B:%02d D:%02d F:%02d\n",
> +    BusNumber,
> +    DevNumber,
> +    FuncNumber);
> +
> +  Status = PcieGetPciConfigAddress (
> +             BusNumber,
> +             DevNumber,
> +             FuncNumber,
> +             0,
> +             &BaseAddress);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  // Use a fixed cacheline size
> +  FixedCacheLineSize = 0x10;

Should this be a #define pulled in from a SoC header, or should it be
discovered dynamically by some SoC (or ARM arch) library?

> +
> +  Status = PciePciWrite (
> +             EfiPciIoWidthUint8,
> +             BaseAddress + PCI_CACHELINE_SIZE_OFFSET,
> +             1,
> +             &FixedCacheLineSize);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  if (IS_PCI_BRIDGE (&PciDevice)) {
> +    PCIE_INFO ("Pci Bridge\n");
> +    // Pcie initialization sequence, referenced from
> +    // InitializePpb in MdeModulePkg/Bus/Pci/PciBusDxe
> +    // No support for IO and prefetch memory
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint8,
> +               BaseAddress + 0x1C,

Could there be some #defines for this and the following live coded
numbers?

> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint8,
> +               BaseAddress + 0x1D,
> +               1,
> +               &AllZero);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint16,
> +               BaseAddress + 0x24,
> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint16,
> +               BaseAddress + 0x26,
> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint32,
> +               BaseAddress + 0x28,
> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint32,
> +               BaseAddress + 0x2C,
> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint16,
> +               BaseAddress + 0x30,
> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PciePciWrite (
> +               EfiPciIoWidthUint16,
> +               BaseAddress + 0x32,
> +               1,
> +               &AllZero);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    // Type 1 bridge only has 2 BAR register
> +    Status = PcieParseAssignBar (
> +               BaseAddress,
> +               2,
> +               TRUE);
> +    if (EFI_ERROR (Status)) {
> +      PCIE_ERROR ("Failed to assign resource to Pci bridge\n");
> +      goto Exit;
> +    }
> +  } else {
> +    // Device specific configuration should be implemented here
> +    PCIE_INFO ("Pci device\n");
> +
> +    Status = PcieParseAssignBar (
> +               BaseAddress,
> +               PCI_MAX_BAR,
> +               FALSE);
> +    if (EFI_ERROR (Status)) {
> +      PCIE_ERROR ("Failed to assign resource to Pci device\n");
> +      goto Exit;
> +    }
> +  }
> +
> +  Status = PciePciRead (
> +             EfiPciIoWidthUint16,
> +             BaseAddress + PCI_COMMAND_OFFSET,
> +             1,
> +             &PciCommand);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  PciCommand |=
> +    (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
> +
> +  Status = PciePciWrite (
> +             EfiPciIoWidthUint16,
> +             BaseAddress + PCI_COMMAND_OFFSET,
> +             1,
> +             &PciCommand);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieSimpleScanBusAndAssignResource (
> +  IN  UINTN   BusNumber
> +  )
> +{
> +  UINTN         BridgeMemory;
> +  UINTN         BridgeMemoryBase;
> +  UINTN         BridgeMemoryLimit;
> +  UINTN         BusBaseRegisterAddress;
> +  UINT16        BusRegister;
> +  UINTN         DevNumber;
> +  UINTN         FunctionNumber;
> +  PCI_TYPE00    PciDevice;
> +  UINTN         ResourceAddress;
> +  EFI_STATUS    Status;
> +  UINT8         SubBus;
> +
> +  for (DevNumber = 0; DevNumber <= PCI_MAX_DEVICE; ++DevNumber) {
> +    for (FunctionNumber = 0; FunctionNumber <= PCI_MAX_FUNC; ++FunctionNumber) {
> +      PCIE_INFO ("Scanning device B: %02d D: %02d F: %02d\n",
> +                 BusNumber,
> +                 DevNumber,
> +                 FunctionNumber);
> +
> +      Status = PcieDevicePresent (
> +                 &PciDevice,
> +                 BusNumber,
> +                 DevNumber,
> +                 FunctionNumber);
> +      if (Status == EFI_NOT_FOUND) {
> +        PCIE_INFO ("No Pci device found\n");
> +        Status = EFI_SUCCESS;
> +        goto Exit;
> +      } else if (EFI_ERROR (Status)) {
> +        PCIE_ERROR ("Error detecting Pci device\n");
> +        goto Exit;
> +      }
> +
> +      Status = PcieConfigureDevice (
> +                 PciDevice,
> +                 BusNumber,
> +                 DevNumber,
> +                 FunctionNumber);
> +      if (EFI_ERROR (Status)) {
> +        PCIE_ERROR (
> +          "Failed to configure device B:%02d D:%02d F:%02d\n",
> +          BusNumber,
> +          DevNumber,
> +          FunctionNumber);
> +        continue;
> +      }
> +
> +      if (IS_PCI_BRIDGE (&PciDevice)) {
> +        BusRegister = (UINT16) (((BusNumber + 1) << 8) | (UINT16)BusNumber);
> +        Status = PcieGetPciConfigAddress (
> +                   BusNumber,
> +                   DevNumber,
> +                   FunctionNumber,
> +                   0,
> +                   &BusBaseRegisterAddress);
> +
> +        ASSERT_EFI_ERROR (Status);
> +
> +        Status = PciePciWrite (
> +                   EfiPciWidthUint16,
> +                   BusBaseRegisterAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> +                   1,
> +                   &BusRegister);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR ("Failed to update bridge bus number %d\n", BusNumber);
> +          continue;
> +        }
> +
> +        // Temporarily set maximum subordinate bus number, although for now
> +        // only support 2 buses.
> +        SubBus = 0XFF;
> +        Status = PciePciWrite (
> +                   EfiPciWidthUint8,
> +                   BusBaseRegisterAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET,
> +                   1,
> +                   &SubBus);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR ("Failed to update bridge bus number %d\n", BusNumber);
> +          continue;
> +        }
> +
> +        // Setup the memory base.
> +        Status = PcieGetMemoryBarResource (
> +                   0,
> +                   &BridgeMemoryBase,
> +                   TRUE);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR ("Failed to acquire BAR resource\n");
> +          goto Exit;
> +        }
> +
> +        BridgeMemory = (BridgeMemoryBase >> 16) & 0xFFF0;
> +
> +        Status = PciePciWrite (
> +                   EfiPciIoWidthUint32,
> +                   BusBaseRegisterAddress + 0x20,
> +                   1,
> +                   &BridgeMemory);
> +        ASSERT_EFI_ERROR (Status);
> +
> +        Status = PcieSimpleScanBusAndAssignResource (
> +                   BusNumber + 1);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR ("Failed to scan new bus %d\n", BusNumber + 1);
> +          continue;
> +        }
> +
> +        // Setup the memory limit.
> +        Status = PcieGetMemoryBarResource (
> +                   0,
> +                   &ResourceAddress,
> +                   TRUE);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR ("Failed to acquire BAR resource\n");
> +          goto Exit;
> +        }
> +
> +        ASSERT (BridgeMemoryBase != ResourceAddress);
> +
> +        // Per spec align address has to be 1MB boundary
> +        PcieGetAlignAddress (
> +          ResourceAddress,
> +          0x00100000,
> +          &BridgeMemoryLimit);
> +        ASSERT_EFI_ERROR (Status);
> +
> +        BridgeMemory |= BridgeMemoryLimit;
> +
> +        Status = PciePciWrite (
> +                   EfiPciIoWidthUint32,
> +                   BusBaseRegisterAddress + 0x20,
> +                   1,
> +                   &BridgeMemory);
> +        ASSERT_EFI_ERROR (Status);
> +
> +        SubBus = (BusNumber + 1);
> +        Status = PciePciWrite (
> +                   EfiPciWidthUint8,
> +                   BusBaseRegisterAddress +
> +                   PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET,
> +                   1,
> +                   &SubBus);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR (
> +            "Failed to update subordinate bus number %d\n",
> +            BusNumber);
> +          continue;
> +        }
> +
> +        // Claim any memory that is used for padding
> +        Status = PcieGetMemoryBarResource (
> +                   (BridgeMemoryLimit + 0x00100000) - ResourceAddress,

SIZE_1MB?

> +                   &ResourceAddress,
> +                   FALSE);
> +        if (EFI_ERROR (Status)) {
> +          PCIE_ERROR ("Failed to realign resource\n");
> +          goto Exit;
> +        }
> +      }
> +
> +      // Skip sub functions, this is not a multi function device
> +      if (FunctionNumber == 0 && !IS_PCI_MULTI_FUNC (&PciDevice)) {
> +        FunctionNumber = PCI_MAX_FUNC;
> +      }
> +    }
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieInitialize (
> +  IN  EFI_HANDLE        ImageHandle,
> +  IN  EFI_SYSTEM_TABLE  *SystemTablePtr
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = PcieSetupInitSetting ();
> +  if (EFI_ERROR (Status)) {
> +    // EFI_DEVICE_ERROR indicates that a bootloader has already setup the
> +    // Pcie controller. In this case just return success immediately
> +    if (Status == EFI_DEVICE_ERROR) {
> +      Status = EFI_SUCCESS;
> +      PCIE_WARNING ("Pcie already initialized\n");
> +      goto Exit;
> +    }
> +
> +    PCIE_ERROR ("Failed to enable Pcie gates\n");
> +    goto Exit;
> +  }
> +
> +  Status = PcieSetClockGate (IMX_CLOCK_GATE_STATE_ON);
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to enable Pcie gates\n");
> +    goto Exit;
> +  }
> +
> +  Status = PcieVerifyClocks ();
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to verify Pcie clocks, not configured!\n");
> +    goto Exit;
> +  }
> +
> +  Status = PcieSetPhyState (TRUE);
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to enable Pcie PHY\n");
> +    goto Exit;
> +  }
> +
> +  // Very important to wait for Pcie PHY to settle here or the controller
> +  // behaviour becomes unpredictable.
> +  gBS->Stall (50000);
> +
> +  PcieEnablePerstLine ();

Perst?

> +
> +  Status = PcieSetupPciBridge ();
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to setup Pci bridge\n");
> +    goto Exit;
> +  }
> +
> +  Status = PcieSetLinkStatus (TRUE);
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to enable Pcie link\n");
> +    goto Exit;
> +  }
> +
> +  Status = PcieWaitForLink ();
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Pci link never came up\n");
> +    goto Exit;
> +  }
> +
> +  PcieSetupiAtuSettings ();
> +
> +  // Start scanning from bus 0 onward
> +  Status = PcieSimpleScanBusAndAssignResource (0);
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("PcieSimpleScanBusAndAssignResource failed %r\n", Status);
> +    goto Exit;
> +  }
> +
> +#ifdef DEBUG
> +  volatile UINT32   *pPrintAddr;
> +  UINT32            PrintIndex;
> +
> +  pPrintAddr = (UINT32 *)PCIE_HOST_CONFIG_BASE_REG;
> +
> +  PCIE_INFO ("===============================\n");
> +  PCIE_INFO ("Host Device Configuration space\n");
> +  PCIE_INFO ("===============================\n");
> +  for (PrintIndex = 0; PrintIndex < 16; ++PrintIndex) {
> +    PCIE_INFO ("PCI [%02x] 0x%08x 0x%08x 0x%08x 0x%08x\n", \
> +                PrintIndex * 16, \
> +                pPrintAddr[0], \
> +                pPrintAddr[1], \
> +                pPrintAddr[2], \
> +                pPrintAddr[3]);
> +
> +    pPrintAddr += 4;
> +  }
> +
> +  PCIE_INFO ("===============================\n");
> +  PCIE_INFO ("Device Configuration space 0x%08x\n", pPrintAddr);
> +  PCIE_INFO ("===============================\n");
> +  for (PrintIndex = 0; PrintIndex < 16; ++PrintIndex) {
> +    PCIE_INFO ("PCI [%02x] 0x%08x 0x%08x 0x%08x 0x%08x\n", \
> +                PrintIndex * 16, \
> +                pPrintAddr[0], \
> +                pPrintAddr[1], \
> +                pPrintAddr[2], \
> +                pPrintAddr[3]);
> +
> +    pPrintAddr += 4;
> +  }
> +  PCIE_INFO ("===============================\n");
> +#endif
> +
> +Exit:
> +
> +  if (EFI_ERROR (Status)) {
> +    PCIE_ERROR ("Failed to initialize Pcie, disabling controller\n");
> +    PcieSetLinkStatus (FALSE);
> +    PcieSetPhyState (FALSE);
> +    PcieSetClockGate (IMX_CLOCK_GATE_STATE_OFF);
> +  }
> +
> +  // For debug printout the state of the PLL/PHY
> +#ifdef DEBUG
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogRegs;
> +  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxcRegs;
> +
> +  pCcmAnalogRegs = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
> +  pIoMuxcRegs = (IMX_IOMUXC_GPR_REGISTERS *)IMX_IOMUXC_BASE;
> +
> +  PCIE_INFO ( "IMX_CCM_PLL_ENET 0x%08X\n",
> +              MmioRead32 ((UINTN) &pCcmAnalogRegs->PLL_ENET));
> +  PCIE_INFO ( "IOMUXC_GPR1 0x%08X\n", MmioRead32 ((UINTN) &pIoMuxcRegs->GPR1));
> +#endif
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
> new file mode 100644
> index 000000000000..029e93b277cf
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
> @@ -0,0 +1,145 @@
> +/** @file
> +*
> +*  Copyright (c) Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#pragma once

Please use include guards instead.

> +
> +#ifndef ARRAYSIZE
> +#define ARRAYSIZE(__array__) (sizeof((__array__))/sizeof((__array__[0])))
> +#endif

Again, use the one from Base.h

> +
> +// Print macro
> +#define PCIE_INIT(PRINT_OUT, ...) \
> +    DEBUG((DEBUG_INIT, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
> +#define PCIE_INFO(PRINT_OUT, ...) \
> +    DEBUG((DEBUG_INFO, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
> +#define PCIE_WARNING(PRINT_OUT, ...) \
> +    DEBUG((DEBUG_WARN, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
> +#define PCIE_ERROR(PRINT_OUT, ...) \
> +    DEBUG((DEBUG_ERROR, "iMX6PCIe:" PRINT_OUT, ##__VA_ARGS__))
> +
> +// PCIe related base address
> +#define PCIE_HOST_CONFIG_BASE_REG       FixedPcdGet32(PcdPcieHostConfigBase)
> +#define PCIE_CTRL_PORT_LOGIG_BASE_REG   0x01FFC700
> +#define PCIE_DEVICE_CONFIG_BASE_REG     FixedPcdGet32(PcdPcieDeviceConfigBase)
> +#define PCIE_DEVICE_CONFIG_SIZE         FixedPcdGet32(PcdPcieDeviceConfigSize)
> +#define PCIE_IO_SPACE_BASE              FixedPcdGet32(PcdPcieIOBase)
> +#define PCIE_IO_SPACE_SIZE              FixedPcdGet32(PcdPcieIOSize)
> +#define PCIE_MEMORY_SPACE_BASE          FixedPcdGet32(PcdPciMemoryBase)
> +#define PCIE_MEMORY_SPACE_SIZE          FixedPcdGet32(PcdPciMemorySize)
> +#define PCIE_PREFETCH_MEMORY_SPACE_BASE FixedPcdGet32(PcdPciPrefetchMemoryBase)
> +#define PCIE_PREFETCH_MEMORY_SPACE_SIZE FixedPcdGet32(PcdPciPrefetchMemorySize)
> +
> +#pragma pack(push, 1)
> +
> +typedef struct {
> +  UINT64 Base;
> +  UINT64 Size;
> +  UINT64 Curr;
> +} PCI_RESOURCE;
> +
> +// Debug register related bits
> +#define PCIE_PL_DEBUG1_PHY_LINK_UP          (1 << 4)
> +#define PCIE_PL_DEBUG1_LINK_IN_TRAINING     (1 << 29)

I realise this is not an exported header file, but please still add an
iMX_ prefix to all PCI* macros, to make it clear which ones (if any)
come from common include headers.

> +
> +// Address Translation Unit related definition
> +#define MAX_iATU_REGION          4
> +
> +typedef enum _REGION_DIRECTION {
> +  OUTBOUND,
> +  INBOUND,
> +} REGION_DIRECTION;
> +
> +typedef enum _TLP_TYPE {
> +  MEMORY_TYPE,
> +  MEMORY_LOCK_TYPE,
> +  IO_TYPE,
> +  CFG0_TYPE = 4,
> +  CFG1_TYPE = 5,
> +} TLP_TYPE;
> +
> +typedef enum _REGION_STATE {
> +  REGION_DISABLE = 0,
> +  REGION_ENABLE = 0x80000000,
> +} REGION_STATE;
> +
> +typedef struct {
> +  UINT32 PCIE_PL_ALTRTR;          // ACK latency timer and replay timer
> +  UINT32 PCIE_PL_VSDR;            // Vendor specific DLLP
> +  UINT32 PCIE_PL_PFLR;            // Port force link
> +  UINT32 PCIE_PL_AFLACR;          // ACK frequency and L0-L1 ASPM control
> +  UINT32 PCIE_PL_PLCR;            // Port link control
> +  UINT32 PCIE_PL_LSR;             // Lane skew
> +  UINT32 PCIE_PL_SNR;             // Symbol number
> +  UINT32 PCIE_PL_STRFM1;          // Symbol timer and filter mask 1
> +  UINT32 PCIE_PL_STRFM2;          // Filter mask 2
> +  UINT32 PCIE_PL_AMODNPSR;        // AMBA Multiple Outbound Decomposed NP Sub-Requests
> +                                  //   Control
> +  UINT32 PCIE_PL_DEBUG0;          // Debug 0
> +  UINT32 PCIE_PL_DEBUG1;          // Debug 1
> +  UINT32 PCIE_PL_TPFCSR;          // Transmit Posted FC Credit Status
> +  UINT32 PCIE_PL_TNFCSR;          // Transmit Non-Posted FC Credit Status
> +  UINT32 PCIE_PL_TCFCSR;          // Transmit Completion FC Credit Status
> +  UINT32 PCIE_PL_QSR;             // Queue status
> +  UINT32 PCIE_PL_VCTAR1;          // Transmit Completion FC Status 1
> +  UINT32 PCIE_PL_VCTAR2;          // Transmit Completion FC Status 1
> +  UINT32 PCIE_PL_VC0PRQC;         // VC0 Posted Receive Queue Control
> +  UINT32 PCIE_PL_VC0NRQC;         // VC0 Non-Posted Receive Queue Control
> +  UINT32 PCIE_PL_VC0CRQC;         // VC0 Completion Receive Queue Control
> +  UINT32 PCIE_PL_VCnPRQC;         // VCn Posted Receive Queue Control
> +  UINT32 PCIE_PL_VCnNRQC;         // VCn Non-Posted Receive Queue Control
> +  UINT32 PCIE_PL_VCnCRQC;         // VCn Completion Receive Queue Control
> +  UINT32 PCIE_PL_RESERVED_0[18];
> +  UINT32 PCIE_PL_VC0PBD;          // VC0 Posted Buffer Depth
> +  UINT32 PCIE_PL_VC0NPBD;         // VC0 Non-Posted Buffer Depth
> +  UINT32 PCIE_PL_VC0CBD;          // VC0 Completion Buffer Depth
> +  UINT32 PCIE_PL_VC1PBD;          // VCn Posted Buffer Depth
> +  UINT32 PCIE_PL_VC1NPBD;         // VCn Non-Posted Buffer Depth
> +  UINT32 PCIE_PL_VC1CBD;          // VCn Completion Buffer Depth
> +  UINT32 PCIE_PL_RESERVED_1[19];
> +  UINT32 PCIE_PL_G2CR;            // Gen2 Control
> +  UINT32 PCIE_PL_PHY_STATUS;      // PHY status
> +  UINT32 PCIE_PL_PHY_CTRL;        // PHY control
> +  UINT32 PCIE_PL_MRCCR0;          // Master Response Composer Control 0
> +  UINT32 PCIE_PL_MRCCR1;          // Master Response Composer Control 1
> +  UINT32 PCIE_PL_MSICA;           // MSI Controller Address
> +  UINT32 PCIE_PL_MSICUA;          // MSI Controller Upper Address
> +  UINT32 PCIE_PL_MSICIn_ENB;      // MSI Controller Interrupt n Enable
> +  UINT32 PCIE_PL_MSICIn_MASK;     // MSI Controller Interrupt n Mask
> +  UINT32 PCIE_PL_MSICIn_STATUS;   // MSI Controller Interrupt n Status
> +  UINT32 PCIE_PL_RESERVED_2[21];
> +  UINT32 PCIE_PL_MSICGPIO;        // MSI Controller General Purpose IO
> +  UINT32 PCIE_PL_RESERVED_3[29];
> +  UINT32 PCIE_PL_iATUVR;          // iATU Viewport
> +  UINT32 PCIE_PL_iATURC1;         // iATU Control 1
> +  UINT32 PCIE_PL_iATURC2;         // iATU Control 2
> +  UINT32 PCIE_PL_iATURLBA;        // iATU Region Lower Base Address
> +  UINT32 PCIE_PL_iATURUBA;        // iATU Region Upper Base Address
> +  UINT32 PCIE_PL_iATURLA;         // iATU Region Limit Address
> +  UINT32 PCIE_PL_iATURLTA;        // iATU Region Lower Target Address
> +  UINT32 PCIE_PL_iATURUTA;        // iATU Region Upper Target Address

(Don't worry about struct members though, as long as the structs don't
start with PCI*.)

> +} CSP_PCIE_PL_REGS, *PCSP_PCIE_PL_REGS;
> +

Please drop all *-typedefs, throughout.

/
    Leif

> +typedef struct _IATU_SETTINGS {
> +  UINT32 RegionDirection;
> +  UINT32 RegionIndex;
> +  TLP_TYPE Type;
> +  UINT32 LowerBaseAddr;
> +  UINT32 UpperBaseAddr;
> +  UINT32 LimitAddr;
> +  UINT32 LowerTargetAddr;
> +  UINT32 UpperTargetAddr;
> +  UINT32 State;
> +} IATU_SETTINGS, *PIATU_SETTINGS;
> +
> +#pragma pack(pop)
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
> new file mode 100644
> index 000000000000..99dbe9a4344e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
> @@ -0,0 +1,66 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION       = 0x0001001A
> +  BASE_NAME         = iMX6PciExpress
> +  FILE_GUID         = 5A7FB871-8A19-48D5-A268-441E79AAFD9E
> +  MODULE_TYPE       = DXE_DRIVER
> +  VERSION_STRING    = 1.0
> +  ENTRY_POINT       = PcieInitialize
> +
> +[Sources.common]
> +  iMX6PciExpress.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  IntelFrameworkPkg/IntelFrameworkPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DxeServicesTableLib
> +  iMX6ClkPwrLib
> +  IoLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  UefiRuntimeServicesTableLib
> +
> +[Protocols]
> +
> +[Pcd]
> +  giMX6TokenSpaceGuid.PcdPcieDeviceConfigBase
> +  giMX6TokenSpaceGuid.PcdPcieDeviceConfigSize
> +  giMX6TokenSpaceGuid.PcdPcieHostConfigBase
> +  giMX6TokenSpaceGuid.PcdPcieIOBase
> +  giMX6TokenSpaceGuid.PcdPcieIOSize
> +  giMX6TokenSpaceGuid.PcdPciMemoryBase
> +  giMX6TokenSpaceGuid.PcdPciMemorySize
> +  giMX6TokenSpaceGuid.PcdPciPrefetchMemoryBase
> +  giMX6TokenSpaceGuid.PcdPciPrefetchMemorySize
> +  giMX6TokenSpaceGuid.PcdPcieResetGpio
> +  giMX6TokenSpaceGuid.PcdPcieResetGpioBankNumber
> +  giMX6TokenSpaceGuid.PcdPcieResetGpioIoNumber
> +
> +[FixedPcd]
> +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> +
> +[Depex]
> +  gEfiCpuArchProtocolGuid AND gEfiMetronomeArchProtocolGuid
> +
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver
  2018-09-21  8:26 ` [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver Chris Co
@ 2018-12-14 22:37   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 22:37 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:15AM +0000, Chris Co wrote:
> This adds GOP display support for NXP i.MX6 SoCs.  It has support for
> HDMI, LVDS, IPU, and parses EDID using I2C.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>

This patch is massive. I would be lying if I said I have given it a
proper review - but I do have some comments sprinkled below.

> ---
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c             | 423 +++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h             | 277 +++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c               |  69 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h               |  28 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c           | 455 ++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h           | 175 +++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c | 399 ++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h | 331 +++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c  | 458 ++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h  | 195 +++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c              |  96 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h              |  33 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c            | 475 ++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h            |  20 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf          |  70 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c              | 761 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h              | 529 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c             |  88 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h             |  32 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h               | 236 ++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c              |  93 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h              |  67 ++
>  22 files changed, 5310 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c
> new file mode 100644
> index 000000000000..a8ab78128719
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c

What does CP stand for? Worth adding to the file header.

> @@ -0,0 +1,423 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "CPMem.h"
> +#include "GopDxe.h"
> +#include "Ipu.h"
> +
> +CPMEM_PARAM *CpMemParamBasePtr = (CPMEM_PARAM *)(IPU1_BASE + CSP_IPUV3_CPMEM_REGS_OFFSET);

Is this meant to be externally visible, or could it be STATIC?
It needs a g- or m-prefix.

> +
> +STATIC CONST UINT8 ChannelMap[] = {

Please add m-prefix.

> +  5, 0,
> +  11, 2,
> +  12, 4,
> +  14, 6,
> +  15, 8,
> +  20, 10,
> +  21, 12,
> +  22, 14,
> +  23, 16,
> +  27, 18,
> +  28, 20,
> +  45, 0,
> +  46, 2,
> +  47, 4,
> +  48, 6,
> +  49, 8,
> +  50, 10,
> +};
> +
> +#ifdef DEBUG
> +VOID
> +DumpCpmemParamPack (
> +  IN  CPMEM_PARAM   *ParamPtr
> +  )
> +{
> +  DEBUG ((DEBUG_VERBOSE, "%a: --WORD0--\n", __FUNCTION__));
> +  DEBUG ((DEBUG_VERBOSE, "%a: XVVirtualCoordinate 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.XVVirtualCoordinate));
> +  DEBUG ((DEBUG_VERBOSE, "%a: YVVirtualCoordinate 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.YVVirtualCoordinate));
> +  DEBUG ((DEBUG_VERBOSE, "%a: XBinnerBlockCoordinate 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.XBinnerBlockCoordinate));
> +  DEBUG ((DEBUG_VERBOSE, "%a: YBinnerBlockCoordinate 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.YBinnerBlockCoordinate));
> +  DEBUG ((DEBUG_VERBOSE, "%a: NewSubBlock 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.NewSubBlock));
> +  DEBUG ((DEBUG_VERBOSE, "%a: CurrentField 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.CurrentField));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollXCounter 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollXCounter));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollYCounter 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollYCounter));
> +  DEBUG ((DEBUG_VERBOSE, "%a: NumberOfScroll 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.NumberOfScroll));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollDeltaX 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollDeltaX));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollMax 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollMax));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollingConfiguration 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollingConfiguration));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollingEnable 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollingEnable));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollDeltaY 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollDeltaY));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollHorizontalDirection 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollHorizontalDirection));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScrollVerticalDirection 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScrollVerticalDirection));
> +  DEBUG ((DEBUG_VERBOSE, "%a: BitsPerPixel 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.BitsPerPixel));
> +  DEBUG ((DEBUG_VERBOSE, "%a: DecodeAddressSelect 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.DecodeAddressSelect));
> +  DEBUG ((DEBUG_VERBOSE, "%a: AccessDimension 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.AccessDimension));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ScanOrder 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ScanOrder));
> +  DEBUG ((DEBUG_VERBOSE, "%a: BandMode 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.BandMode));
> +  DEBUG ((DEBUG_VERBOSE, "%a: BlockMode 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.BlockMode));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Rotation 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.Rotation));
> +  DEBUG ((DEBUG_VERBOSE, "%a: HorizontalFlip 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.HorizontalFlip));
> +  DEBUG ((DEBUG_VERBOSE, "%a: VerticalFlip 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.VerticalFlip));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ThresholdEnable 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ThresholdEnable));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ConditionalAccessPolarity 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ConditionalAccessPolarity));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ConditionalAccessEnable 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.ConditionalAccessEnable));
> +  DEBUG ((DEBUG_VERBOSE, "%a: FrameWidth 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.FrameWidth));
> +  DEBUG ((DEBUG_VERBOSE, "%a: FrameHeight 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.FrameHeight));
> +  DEBUG ((DEBUG_VERBOSE, "%a: EndOfLineInterrupt 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word0Pack.EndOfLineInterrupt));
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: --WORD1--\n", __FUNCTION__));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ExtMemBuffer0Address 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.ExtMemBuffer0Address));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ExtMemBuffer1Address 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.ExtMemBuffer1Address));
> +  DEBUG ((DEBUG_VERBOSE, "%a: InterlaceOffset 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.InterlaceOffset));
> +  DEBUG ((DEBUG_VERBOSE, "%a: NumberOfPixelsInWholeBurstAccess 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.NumberOfPixelsInWholeBurstAccess));
> +  DEBUG ((DEBUG_VERBOSE, "%a: PixelFormatSelect 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.PixelFormatSelect));
> +  DEBUG ((DEBUG_VERBOSE, "%a: AlphaUsed 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.AlphaUsed));
> +  DEBUG ((DEBUG_VERBOSE, "%a: AlphaChannelMapping 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.AlphaChannelMapping));
> +  DEBUG ((DEBUG_VERBOSE, "%a: AxiId 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.AxiId));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Threshold 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Threshold));
> +  DEBUG ((DEBUG_VERBOSE, "%a: StrideLine 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.StrideLine));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Width0 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Width0));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Width1 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Width1));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Width2 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Width2));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Width3 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Width3));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Offset0 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Offset0));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Offset1 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Offset1));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Offset2 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Offset2));
> +  DEBUG ((DEBUG_VERBOSE, "%a: Offset3 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.Offset3));
> +  DEBUG ((DEBUG_VERBOSE, "%a: SelectSXSYSet 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.SelectSXSYSet));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ConditionalReadEnable 0x%08x\n", __FUNCTION__,
> +    ParamPtr->Word1Pack.ConditionalReadEnable));
> +}
> +
> +VOID
> +DumpBasicCpmemReg (
> +  IN  CPMEM_PARAM   *pCpmemChannel
> +  )
> +{
> +  DEBUG ((DEBUG_VERBOSE, "%a: ---------- CPMEM Register Dump ----------\n",
> +    __FUNCTION__));
> +  DEBUG ((DEBUG_VERBOSE, "%a: CPMEM\n", __FUNCTION__));
> +  DEBUG ((DEBUG_VERBOSE, "%a: IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE\n",
> +    __FUNCTION__));
> +  DumpCpmemParamPack (pCpmemChannel);
> +  DEBUG ((DEBUG_VERBOSE, "%a: ------------------------------------\n",
> +    __FUNCTION__));
> +}
> +#endif /* DEBUG */
> +
> +// Enable IDMAC lock setting, which optimises memory accesses and reduces
> +// power consumption
> +VOID
> +SetIdmacLockEn (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  UINT32                      Channel,
> +  IN  UINT32                      Setting
> +  )
> +{
> +  UINT32 i;
> +  UINTN   LockReg;
> +  UINT32 Shift;
> +  UINT32 Value;
> +
> +  Shift = -1;
> +
> +  for (i = 0; i < ARRAYSIZE (ChannelMap); i += 2) {
> +    if (ChannelMap[i] == Channel) {
> +      Shift = ChannelMap[i + 1];
> +      break;
> +    }
> +  }
> +
> +  if (Shift == -1) {
> +    DEBUG ((DEBUG_WARN, "%a: Channel %d does not have lock bits\n",
> +      __FUNCTION__, Channel));
> +    return;
> +  }
> +
> +  if (Channel < 29) {
> +    LockReg = (UINTN)DisplayInterfaceContextPtr->IpuMmioBasePtr + IPU_IDMAC_LOCK_EN_1;
> +  } else {
> +    LockReg = (UINTN)DisplayInterfaceContextPtr->IpuMmioBasePtr + IPU_IDMAC_LOCK_EN_2;
> +  }
> +
> +  Value = MmioRead32 ((UINT32)LockReg);
> +  Value &= ~(0x3 << Shift);
> +  Value |= (Setting & 0x3) << Shift;
> +  MmioWrite32 ((UINT32)LockReg, Value);
> +}
> +
> +EFI_STATUS
> +ConfigureCpmemFrameBuffer (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  UINT32                      Channel,
> +  IN  SURFACE_INFO                *FrameBufferPtr
> +  )
> +{
> +  CPMEM_PARAM *pCpmemChannel;
> +  EFI_STATUS Status;
> +  CPMEM_WORD0_PACKED_REG CpmemWord0PackedReg;
> +  CPMEM_WORD1_PACKED_REG CpmemWord1PackedReg;
> +  CPMEM_DEC_SEL DecodeAddressSelect;
> +  UINT32 PixelBurst;
> +  CPMEM_PFS_PACKED PixelFormatSelector;
> +  UINT32 Width0;
> +  UINT32 Width1;
> +  UINT32 Width2;
> +  UINT32 Width3;
> +  UINT32 Offset0;
> +  UINT32 Offset1;
> +  UINT32 Offset2;
> +  UINT32 Offset3;
> +  UINT32 BytesPerPixel;
> +
> +  pCpmemChannel = DisplayInterfaceContextPtr->CpMemParamBasePtr;
> +  Status = EFI_SUCCESS;
> +  PixelBurst = 1;
> +  DecodeAddressSelect = CPMEM_DEC_SEL_0_15; // Only applicable for 4 bpp
> +  ZeroMem (&CpmemWord0PackedReg, sizeof (CpmemWord0PackedReg));
> +  ZeroMem (&CpmemWord1PackedReg, sizeof (CpmemWord1PackedReg));
> +
> +  switch (FrameBufferPtr->PixelFormat) {
> +  case PIXEL_FORMAT_BGRA32:
> +    PixelBurst = 15; // 16 Pixel. Valid range is 1 - 64 pixel
> +    PixelFormatSelector = CPMEM_PFS_RGB;
> +    Offset0 = 8;
> +    Offset1 = 16;
> +    Offset2 = 24;
> +    Offset3 = 0;
> +    BytesPerPixel = 4;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    Status = EFI_UNSUPPORTED;
> +    break;
> +  }
> +  if (EFI_ERROR (Status)) {
> +    goto Exit;
> +  }
> +
> +  switch (FrameBufferPtr->Bpp) {
> +  case 8:
> +    Width0 = 0;
> +    Width1 = 0;
> +    Width2 = 0;
> +    Width3 = 0;
> +    break;
> +  case 32:
> +    if (PixelFormatSelector == CPMEM_PFS_RGB) {
> +      Width0 = 7;
> +      Width1 = 7;
> +      Width2 = 7;
> +      Width3 = 7;
> +    } else {
> +      Width0 = 0;
> +      Width1 = 0;
> +      Width2 = 0;
> +      Width3 = 0;
> +    }
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    Status = EFI_UNSUPPORTED;
> +    break;
> +  }
> +  if (EFI_ERROR (Status)) {
> +    goto Exit;
> +  }
> +  // Setting up CPMEM word 0
> +  CpmemWord0PackedReg.XVVirtualCoordinate = 0;
> +  CpmemWord0PackedReg.YVVirtualCoordinate = 0;
> +
> +  // Subblock is unused although expect to have some Value after write
> +  CpmemWord0PackedReg.XBinnerBlockCoordinate = 0;
> +  CpmemWord0PackedReg.YBinnerBlockCoordinate = 0;
> +  CpmemWord0PackedReg.NewSubBlock = 0;
> +
> +  // Verify "current field" definition
> +  CpmemWord0PackedReg.CurrentField = 0;
> +
> +  // Disable scrolling
> +  CpmemWord0PackedReg.ScrollXCounter = 0;
> +  CpmemWord0PackedReg.ScrollYCounter = 0;
> +  CpmemWord0PackedReg.NumberOfScroll = 0;
> +  CpmemWord0PackedReg.ScrollDeltaX = 0;
> +  CpmemWord0PackedReg.ScrollMax = 0;
> +  CpmemWord0PackedReg.ScrollingConfiguration = 0;
> +  CpmemWord0PackedReg.ScrollingEnable = 0;
> +  CpmemWord0PackedReg.ScrollDeltaY = 0;
> +  CpmemWord0PackedReg.ScrollHorizontalDirection = 0;
> +  CpmemWord0PackedReg.ScrollVerticalDirection = 0;
> +
> +  // Bits per pixel
> +  CpmemWord0PackedReg.BitsPerPixel = FrameBufferPtr->Bpp;
> +
> +  // Decode Address Select
> +  CpmemWord0PackedReg.DecodeAddressSelect = DecodeAddressSelect;
> +
> +  // Scan order is progressive no support for interlace mode
> +  CpmemWord0PackedReg.ScanOrder = CPMEM_SO_PROGRESSIVE;
> +
> +  // Band mode is sub frame double buffering
> +  CpmemWord0PackedReg.BandMode = CPMEM_BNDM_DISABLE;
> +
> +  // Block mode used for post filtering and rotation
> +  CpmemWord0PackedReg.BlockMode = CPMEM_BM_DISABLE;
> +
> +  // No support for rotation and flipping for now
> +  CpmemWord0PackedReg.Rotation = CPMEM_ROT_NO_ROTATION;
> +  CpmemWord0PackedReg.HorizontalFlip = CPMEM_HF_NO_HFLIP;
> +  CpmemWord0PackedReg.VerticalFlip = CPMEM_HF_NO_VFLIP;
> +  CpmemWord0PackedReg.ThresholdEnable = CPMEM_THE_DISABLE;
> +
> +  // Disable conditional access
> +  CpmemWord0PackedReg.ConditionalAccessEnable = CPMEM_CAP_SKIP_LOW;
> +  CpmemWord0PackedReg.ConditionalAccessPolarity = CPMEM_CAE_DISABLE;
> +
> +  // Frame width and height, minus one as 0 == 1 pixel
> +  CpmemWord0PackedReg.FrameWidth = FrameBufferPtr->Width - 1;
> +  CpmemWord0PackedReg.FrameHeight = FrameBufferPtr->Height - 1;
> +
> +  // No interrupt required at the end of line
> +  CpmemWord0PackedReg.EndOfLineInterrupt = CPMEM_EOLI_DISABLE;
> +
> +  // Setting up CPMEM word 1
> +  // Buffer 0, use the [31:3] bit address
> +  CpmemWord1PackedReg.ExtMemBuffer0Address = FrameBufferPtr->PhyAddr >> 3;
> +
> +  // Buffer 1, use the same buffer for now
> +  CpmemWord1PackedReg.ExtMemBuffer1Address = FrameBufferPtr->PhyAddr >> 3;
> +
> +  // Currently do not support interlace mode
> +  CpmemWord1PackedReg.InterlaceOffset = 0;
> +
> +  // Pixel format and burst
> +  CpmemWord1PackedReg.NumberOfPixelsInWholeBurstAccess = PixelBurst;
> +  CpmemWord1PackedReg.PixelFormatSelect = PixelFormatSelector;
> +
> +  // Alpha config
> +  CpmemWord1PackedReg.AlphaUsed = CPMEM_ALU_SAME_BUFFER;
> +
> +  // AXI ID 0 should be okay, we don't have anything else contending for it
> +  CpmemWord1PackedReg.AxiId = CPMEM_ID_ID_0;
> +
> +  CpmemWord1PackedReg.Threshold = CPMEM_THE_DISABLE;
> +
> +  // Stride, width and offset
> +  CpmemWord1PackedReg.StrideLine = (FrameBufferPtr->Pitch * BytesPerPixel) - 1;
> +  CpmemWord1PackedReg.Width0 = Width0;
> +  CpmemWord1PackedReg.Width1 = Width1;
> +  CpmemWord1PackedReg.Width2 = Width2;
> +  CpmemWord1PackedReg.Width3 = Width3;
> +  CpmemWord1PackedReg.Offset0 = Offset0;
> +  CpmemWord1PackedReg.Offset1 = Offset1;
> +  CpmemWord1PackedReg.Offset2 = Offset2;
> +  CpmemWord1PackedReg.Offset3 = Offset3;
> +
> +  // SX SY is ignored since scrolling is disabled
> +  CpmemWord1PackedReg.SelectSXSYSet = 0;
> +
> +  // Conditional read is always enabled so fully transperant pixel are
> +  // not read.
> +  CpmemWord1PackedReg.ConditionalReadEnable = CPMEM_CRE_ENABLE;
> +
> +  // Finally write into cpmem IDMAC channel
> +  pCpmemChannel = (pCpmemChannel + Channel);
> +
> +  CopyMem (
> +    &pCpmemChannel->Word0Pack,
> +    &CpmemWord0PackedReg,
> +    sizeof (pCpmemChannel->Word0Pack)
> +  );
> +
> +  CopyMem (
> +    &pCpmemChannel->Word1Pack,
> +    &CpmemWord1PackedReg,
> +    sizeof (pCpmemChannel->Word1Pack)
> +  );
> +
> +  // IDMAC will generate 8 AXI bursts upon assertion of the DMA request
> +  // This significantly reduces memory activity and power consumption
> +  SetIdmacLockEn (DisplayInterfaceContextPtr, Channel, 0x3);
> +
> +#ifdef DEBUG
> +  DumpBasicCpmemReg (pCpmemChannel);
> +#endif /* DEBUG */
> +
> +Exit:
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
> new file mode 100644
> index 000000000000..06e96538f2d1
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
> @@ -0,0 +1,277 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _CPMEM_H_
> +#define _CPMEM_H_

Please add an IMX6 prefix.

> +
> +// IDMAC channel definition
> +#define IDMAC_CHANNEL_CSI_0                                 0
> +#define IDMAC_CHANNEL_CSI_1                                 1
> +#define IDMAC_CHANNEL_CSI_2                                 2
> +#define IDMAC_CHANNEL_CSI_3                                 3
> +#define IDMAC_CHANNEL_VDIC_VF1_VF2                          5
> +#define IDMAC_CHANNEL_VDIC_PREVIOUS_FIELD                   8
> +#define IDMAC_CHANNEL_VDIC_CURRENT_FIELD                    9
> +#define IDMAC_CHANNEL_VDIC_NEXT_FIELD                       10
> +#define IDMAC_CHANNEL_IC_VIDEO_POST_PROCESSSING             11
> +#define IDMAC_CHANNEL_IC_VIDEO_PRP_TASK                     12
> +
> +#define IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE            23
> +
> +typedef enum {
> +  CPMEM_SO_PROGRESSIVE,
> +  CPMEM_SO_INTERLACE,
> +} CPMEM_SO;
> +
> +typedef enum {
> +  CPMEM_BNDM_DISABLE,
> +  CPMEM_BNDM_BAND_HEIGHT_4,
> +  CPMEM_BNDM_BAND_HEIGHT_8,
> +  CPMEM_BNDM_BAND_HEIGHT_16,
> +  CPMEM_BNDM_BAND_HEIGHT_32,
> +  CPMEM_BNDM_BAND_HEIGHT_64,
> +  CPMEM_BNDM_BAND_HEIGHT_128,
> +  CPMEM_BNDM_BAND_HEIGHT_256,
> +} CPMEM_BNDM;
> +
> +typedef enum {
> +  CPMEM_BM_DISABLE,
> +  CPMEM_BM_BW_BH_8,
> +  CPMEM_BM_BW_BH_16,
> +  CPMEM_BM_UNUSED,
> +} CPMEM_BM;
> +
> +typedef enum {
> +  CPMEM_ROT_NO_ROTATION,
> +  CPMEM_ROT_90_ROTATION,
> +} CPMEM_ROT;
> +
> +typedef enum {
> +  CPMEM_HF_NO_HFLIP,
> +  CPMEM_HF_HFLIP_ENABLE,
> +} CPMEM_HF;
> +
> +typedef enum {
> +  CPMEM_HF_NO_VFLIP,
> +  CPMEM_HF_VFLIP_ENABLE,
> +} CPMEM_VF;
> +
> +typedef enum {
> +  CPMEM_THE_DISABLE,
> +  CPMEM_THE_ENABLE,
> +} CPMEM_THE;
> +
> +typedef enum {
> +  CPMEM_CAP_SKIP_LOW,
> +  CPMEM_CAP_SKIP_HIGH,
> +} CPMEM_CAP;
> +
> +typedef enum {
> +  CPMEM_CAE_DISABLE,
> +  CPMEM_CAE_ENABLE,
> +} CPMEM_CAE;
> +
> +typedef enum {
> +  CPMEM_EOLI_DISABLE,
> +  CPMEM_EOLI_ENABLE,
> +} CPMEM_EOLI;
> +
> +typedef enum {
> +  CPMEM_PFS_NON_INT_444,
> +  CPMEM_PFS_NON_INT_422,
> +  CPMEM_PFS_NON_INT_420,
> +  CPMEM_PFS_PAR_INT_422,
> +  CPMEM_PFS_PAR_INT_420,
> +} CPMEM_PFS_PLANAR;
> +
> +typedef enum {
> +  CPMEM_DEC_SEL_0_15,
> +  CPMEM_DEC_SEL_64_79,
> +  CPMEM_DEC_SEL_128_143,
> +  CPMEM_DEC_SEL_192_207,
> +} CPMEM_DEC_SEL;
> +
> +typedef enum {
> +  CPMEM_PFS_CODE = 5,
> +  CPMEM_PFS_GENERIC_DATA,
> +  CPMEM_PFS_RGB,
> +  CPMEM_PFS_INT_422_Y1U1Y2V1,
> +  CPMEM_PFS_INT_422_Y2U1Y1V1,
> +  CPMEM_PFS_INT_422_U1Y1V1Y2,
> +  CPMEM_PFS_INT_422_U1Y2V1Y1,
> +} CPMEM_PFS_PACKED;
> +
> +typedef enum {
> +  CPMEM_ALU_SAME_BUFFER,
> +  CPMEM_ALU_SEPERATE_BUFFER,
> +} CPMEM_ALU;
> +
> +typedef enum {
> +  CPMEM_ID_ID_0,
> +  CPMEM_ID_ID_1,
> +  CPMEM_ID_ID_2,
> +  CPMEM_ID_ID_3,
> +} CPMEM_ID;
> +
> +typedef enum {
> +  CPMEM_CRE_DISABLE,
> +  CPMEM_CRE_ENABLE,
> +} CPMEM_CRE;
> +
> +#pragma pack(push, 1)
> +
> +// CPMEM_WORD0_PLANAR - Non interlaved
> +typedef union {
> +  struct {
> +    UINT32 XVVirtualCoordinate : 10;
> +    UINT32 YVVirtualCoordinate : 9;
> +    UINT32 XBinnerBlockCoordinate : 13;
> +    UINT32 YBinnerBlockCoordinate : 12;
> +    UINT32 NewSubBlock : 1;
> +    UINT32 CurrentField : 1;
> +    UINT32 MemUBufferOffset : 22;
> +    UINT32 MemVBufferOffset : 22;
> +    UINT32 InitialOffsetX : 4;
> +    UINT32 ReduceDoubleReadOrWrites : 1;
> +    UINT32 Reserved1 : 18;
> +    UINT32 ScanOrder : 1;
> +    UINT32 BandMode : 3;
> +    UINT32 BlockMode : 2;
> +    UINT32 Rotation : 1;
> +    UINT32 HorizontalFlip : 1;
> +    UINT32 VerticalFlip : 1;
> +    UINT32 ThresholdEnable : 1;
> +    UINT32 ConditionalAccessPolarity : 1;
> +    UINT32 ConditionalAccessEnable : 1;
> +    UINT32 FrameWidth : 13; // Max 8192 Pixel
> +    UINT32 FrameHeight : 12; // Max 4096 Pixel
> +    UINT32 EndOfLineInterrupt : 1;
> +    UINT32 Reserved2 : 9;
> +  };
> +  UINT32 Word0[5];
> +} CPMEM_WORD0_PLANAR_REG;
> +
> +// CPMEM_WORD1_PLANAR - Non interleaved
> +typedef union {
> +  struct {
> +    UINT32 ExtMemBuffer0Address : 29;
> +    UINT32 ExtMemBuffer1Address : 29;
> +    UINT32 InterlaceOffset : 20;
> +    UINT32 NumberOfPixelsInWholeBurstAccess : 7;
> +    UINT32 PixelFormatSelect : 4;
> +    UINT32 AlphaUsed : 1;
> +    UINT32 AlphaChannelMapping : 3;
> +    UINT32 AxiId : 2;
> +    UINT32 Threshold : 7;
> +    UINT32 StrideLine : 14;
> +    UINT32 Reserved1 : 9;
> +    UINT32 Width3 : 3;
> +    UINT32 StrideLineUV : 14;
> +    UINT32 Reserved2 : 7;
> +    UINT32 ConditionalReadEnable : 1;
> +    UINT32 Reserved3 : 10;
> +  };
> +  UINT32 Word1[5];
> +} CPMEM_WORD1_PLANAR_REG;
> +
> +// CPMEM_WORD0_PACKED - Interlaved
> +typedef union {
> +  struct {
> +    UINT32 XVVirtualCoordinate : 10;
> +    UINT32 YVVirtualCoordinate : 9;
> +    UINT32 XBinnerBlockCoordinate : 13;
> +    UINT32 YBinnerBlockCoordinate : 12;
> +    UINT32 NewSubBlock : 1;
> +    UINT32 CurrentField : 1;
> +    UINT32 ScrollXCounter : 12;
> +    UINT32 ScrollYCounter : 11;
> +    UINT32 NumberOfScroll : 10;
> +    UINT32 ScrollDeltaX : 7;
> +    UINT32 ScrollMax : 10;
> +    UINT32 ScrollingConfiguration : 1;
> +    UINT32 ScrollingEnable : 1;
> +    UINT32 ScrollDeltaY : 7;
> +    UINT32 ScrollHorizontalDirection : 1;
> +    UINT32 ScrollVerticalDirection : 1;
> +    UINT32 BitsPerPixel : 3;
> +    UINT32 DecodeAddressSelect : 2;
> +    UINT32 AccessDimension : 1;
> +    UINT32 ScanOrder : 1;
> +    UINT32 BandMode : 3;
> +    UINT32 BlockMode : 2;
> +    UINT32 Rotation : 1;
> +    UINT32 HorizontalFlip : 1;
> +    UINT32 VerticalFlip : 1;
> +    UINT32 ThresholdEnable : 1;
> +    UINT32 ConditionalAccessPolarity : 1;
> +    UINT32 ConditionalAccessEnable : 1;
> +    UINT32 FrameWidth : 13; // Max 8192 Pixel
> +    UINT32 FrameHeight : 12; // Max 4096 Pixel
> +    UINT32 EndOfLineInterrupt : 1;
> +    UINT32 Reserved2 : 9;
> +  };
> +  UINT32 Word0[5];
> +} CPMEM_WORD0_PACKED_REG;
> +
> +// CPMEM_WORD1_PACKED - Non interleaved
> +typedef union {
> +  struct {
> +    UINT32 ExtMemBuffer0Address : 29;
> +    UINT32 ExtMemBuffer1Address : 29;
> +    UINT32 InterlaceOffset : 20;
> +    UINT32 NumberOfPixelsInWholeBurstAccess : 7;
> +    UINT32 PixelFormatSelect : 4;
> +    UINT32 AlphaUsed : 1;
> +    UINT32 AlphaChannelMapping : 3;
> +    UINT32 AxiId : 2;
> +    UINT32 Threshold : 7;
> +    UINT32 StrideLine : 14;
> +    UINT32 Width0 : 3;
> +    UINT32 Width1 : 3;
> +    UINT32 Width2 : 3;
> +    UINT32 Width3 : 3;
> +    UINT32 Offset0 : 5;
> +    UINT32 Offset1 : 5;
> +    UINT32 Offset2 : 5;
> +    UINT32 Offset3 : 5;
> +    UINT32 SelectSXSYSet : 1;
> +    UINT32 ConditionalReadEnable : 1;
> +    UINT32 Reserved1 : 10;
> +  };
> +  UINT32 Word1[5];
> +} CPMEM_WORD1_PACKED_REG;
> +
> +typedef struct _CPMEM_PARAM {
> +  union {
> +    CPMEM_WORD0_PLANAR_REG Word0Planar;
> +    CPMEM_WORD0_PACKED_REG Word0Pack;
> +  };
> +  UINT32 Reserved1[3];
> +  union {
> +    CPMEM_WORD1_PLANAR_REG Word1Planar;
> +    CPMEM_WORD1_PACKED_REG Word1Pack;
> +  };
> +  UINT32 Reserved2[3];
> +} CPMEM_PARAM, *PCPMEM_PARAM;
> +
> +#pragma pack(pop)
> +
> +EFI_STATUS
> +ConfigureCpmemFrameBuffer (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  UINT32                      Channel,
> +  IN  SURFACE_INFO                *FrameBufferPtr
> +  );
> +
> +#endif  /* _CPMEM_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
> new file mode 100644
> index 000000000000..30b737b2f4f5
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
> @@ -0,0 +1,69 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "Edid.h"
> +#include "Ddc.h"
> +#include "Hdmi.h"
> +#include "Lvds.h"
> +
> +EFI_STATUS
> +Imx6DdcRead (
> +  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
> +  IN  UINT8               SlaveAddress,
> +  IN  UINT8               RegisterAddress,
> +  IN  UINT32              ReadSize,
> +  IN  UINT8               *DataReadPtr
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  switch (DisplayInterface) {
> +  case HdmiDisplay:
> +    Status = HdmiDdcRead (
> +               &DisplayContextPtr->DiContext[HdmiDisplay],
> +               SlaveAddress,
> +               RegisterAddress,
> +               ReadSize,
> +               HDMI_DDC_STANDARD_MODE,
> +               DataReadPtr
> +             );
> +    if (Status != EFI_SUCCESS) {
> +      DEBUG ((DEBUG_ERROR, "%a: HdmiDdcRead failed\n", __FUNCTION__));
> +    }
> +    break;
> +  case MipiDisplay:
> +  case Lvds0Display:
> +  case Lvds1Display:
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +    break;
> +  }
> +
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
> new file mode 100644
> index 000000000000..5a10f3d0c26c
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
> @@ -0,0 +1,28 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _DDC_H_
> +#define _DDC_H_

IMX_ prefix please.

> +
> +EFI_STATUS
> +Imx6DdcRead (
> +  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
> +  IN  UINT8               SlaveAddress,
> +  IN  UINT8               RegisterAddress,
> +  IN  UINT32              ReadSize,
> +  IN  UINT8               *DataReadPtr
> +  );
> +
> +#endif  /* _DDC_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
> new file mode 100644
> index 000000000000..334e7362d3b8
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
> @@ -0,0 +1,455 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +// Display muxing register
> +#include "iMX6.h"

Is this not the same iMX6.h as 5 lines up?

> +
> +#include "Display.h"
> +#include "Edid.h"
> +#include "Hdmi.h"
> +#include "Lvds.h"
> +#include "DisplayInterface.h"
> +#include "DisplayController.h"
> +#include "CPMem.h"
> +#include "Ipu.h"
> +#include "IoMux.h"
> +
> +DISPLAY_TIMING DefaultTiming = {
> +  65000000,   // PixelClock
> +  1024,       // HActive
> +  320,        // HBlank
> +  768,        // VActive
> +  38,         // VBlank
> +  136,        // HSync
> +  6,          // VSync
> +  24,         // HSyncOffset;
> +  3,          // VSyncOffset;
> +  1024,       // HImageSize
> +  768,        // VImageSize
> +  0,          // HBorder
> +  0,          // VBorder
> +  0,          // EdidFlags
> +  0,          // Flags
> +  1,          // PixelRepetition
> +  32,          // Bpp
> +  PIXEL_FORMAT_BGRA32,       // PixelFormat
> +};
> +
> +DISPLAY_TIMING Hannstar_XGA = {
> +  65000000,   // PixelClock
> +  1024,       // HActive
> +  320,        // HBlank
> +  768,        // VActive
> +  38,         // VBlank
> +  60,         // HSync
> +  10,         // VSync
> +  24,         // HSyncOffset;
> +  3,          // VSyncOffset;
> +  1024,       // HImageSize
> +  768,        // VImageSize
> +  0,          // HBorder
> +  0,          // VBorder
> +  0,          // EdidFlags
> +  0,          // Flags
> +  1,          // PixelRepetition
> +  32,         // Bpp
> +  PIXEL_FORMAT_BGRA32,       // PixelFormat
> +};
> +
> +EFI_STATUS
> +GetPreferredTiming (
> +  IN  UINT8           *EdidDataPtr,
> +  IN  UINT32          EdidDataSize,
> +  IN  DISPLAY_TIMING  *PreferredTimingPtr
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    *PreferredTimingPtr = Hannstar_XGA;
> +    Status = EFI_SUCCESS;
> +  } else {
> +    Status = GetEdidPreferredTiming (EdidDataPtr, EdidDataSize, PreferredTimingPtr);
> +    if (Status != EFI_SUCCESS) {
> +      // If EDID is unavailable use the default timing
> +      Status = EFI_SUCCESS;
> +      *PreferredTimingPtr = DefaultTiming;
> +      DEBUG ((DEBUG_WARN,
> +        "%a: EDID data not available, falling back to default timing\n",
> +        __FUNCTION__));
> +    }
> +  }
> +
> +  // Only support 8 bit per pixel and no pixel repetition for now
> +  PreferredTimingPtr->PixelRepetition = 1;
> +  PreferredTimingPtr->PixelFormat = PIXEL_FORMAT_BGRA32;
> +  PreferredTimingPtr->Bpp = 32;
> +
> +#ifdef DEBUG
> +  PrintDisplayTiming ("Preferred Timing", PreferredTimingPtr);
> +#endif /* DEBUG */
> +  DEBUG ((DEBUG_WARN, "%a: --GetPreferredTiming\n", __FUNCTION__));
> +  return Status;
> +}
> +
> +EFI_STATUS
> +InitDisplay (
> +  IN  DISPLAY_CONTEXT   **DisplayConfigPPtr
> +  )
> +{
> +  DISPLAY_CONTEXT     *pTempDisplayContext;
> +  DISPLAY_INTERFACE_TYPE   DisplayCounter;
> +  EFI_STATUS          Status;
> +
> +  pTempDisplayContext = AllocateRuntimePool (sizeof (*pTempDisplayContext));
> +  if (pTempDisplayContext == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate display context\n", __FUNCTION__));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +
> +  ZeroMem (pTempDisplayContext, sizeof (*pTempDisplayContext));
> +
> +  pTempDisplayContext->IoMuxMmioBasePtr = (VOID *)IOMUXC_GPR_BASE_ADDRESS;
> +  if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to map IO Mux register\n", __FUNCTION__));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +
> +  pTempDisplayContext->IpuMmioBasePtr[IPU1] = (VOID *)IPU1_BASE;
> +  if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to map IPU1 IO Mux register\n", __FUNCTION__));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +#if !defined(CPU_IMX6SDL)
> +  pTempDisplayContext->IpuMmioBasePtr[IPU2] = (VOID *)IPU2_BASE;
> +  if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to map IPU2 IO Mux register\n", __FUNCTION__));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +#endif
> +  for (DisplayCounter = HdmiDisplay; DisplayCounter < DisplayTypeMax; ++DisplayCounter) {
> +    pTempDisplayContext->DiContext[DisplayCounter].displayInterface =
> +      DisplayCounter;
> +  }
> +
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    Status = InitLvds (pTempDisplayContext);
> +    if (Status != EFI_SUCCESS) {
> +      DEBUG ((DEBUG_ERROR, "%a: Fail to intialize LVDS\n", __FUNCTION__));
> +      goto Exit;
> +    }
> +  } else {
> +    Status = InitHdmi (pTempDisplayContext);
> +    if (Status != EFI_SUCCESS) {
> +      DEBUG ((DEBUG_ERROR, "%a: Fail to intialize HDMI\n", __FUNCTION__));
> +      goto Exit;
> +    }
> +  }
> +
> +  *DisplayConfigPPtr = pTempDisplayContext;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +ValidateDisplayConfig (
> +  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN  DISPLAY_MODE        DisplayMode,
> +  IN  DISPLAY_INTERFACE_TYPE   *DiOrder
> +  )
> +{
> +  DISPLAY_INTERFACE_TYPE   DisplayDevice;
> +  EFI_STATUS          Status;
> +
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    DisplayDevice = Lvds0Display;
> +  } else {
> +    DisplayDevice = HdmiDisplay;
> +  }
> +
> +  // Currently only support single display mode on HDMI/LVDS
> +  if (DisplayMode != SINGLE_MODE && DiOrder[0] != DisplayDevice) {
> +    Status = EFI_UNSUPPORTED;
> +    goto Exit;
> +  }
> +
> +  // Currently going to a very simplistic approach of enabling HDMI/LVDS single
> +  // display on HDMI/LVDS port. This configuration is applied regardless if
> +  // there is a monitor connected. No hot plug, monitor detection support.
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +SetDisplayConfig (
> +  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN      DISPLAY_MODE        DisplayMode,
> +  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
> +  )
> +{
> +  DISPLAY_INTERFACE_CONTEXT   *pDisplayInterfaceContext;
> +  DISPLAY_INTERFACE_INDEX     DisplayInterfaceIndex;
> +  UINT32                      DisplayInterfaceOffset[DisplayInterfaceMax];
> +  UINT32                      DisplayModeIndex;
> +  IPU_INDEX                   IpuIndex;
> +  EFI_STATUS                  Status;
> +
> +  DisplayInterfaceOffset[0] = IPU_DISPLAY_INTERFACE_0_OFFSET;
> +  DisplayInterfaceOffset[1] = IPU_DISPLAY_INTERFACE_1_OFFSET;
> +  Status = ValidateDisplayConfig (DisplayContextPtr, DisplayMode, DiOrder);
> +  if (Status != EFI_SUCCESS) {
> +    DisplayContextPtr->DisplayConfig.DisplayMode = UNKNOWN_MODE;
> +    ZeroMem (
> +      DisplayContextPtr->DisplayConfig.DiOrder,
> +      sizeof (DisplayContextPtr->DisplayConfig.DiOrder)
> +    );
> +    DEBUG ((DEBUG_ERROR, "%a: Unsupported display configuration\n", __FUNCTION__));
> +    Status = EFI_UNSUPPORTED;
> +    goto Exit;
> +  }
> +
> +  DisplayContextPtr->DisplayConfig.DisplayMode = DisplayMode;
> +  ZeroMem (
> +    DisplayContextPtr->DisplayConfig.DiOrder,
> +    sizeof (DisplayContextPtr->DisplayConfig.DiOrder)
> +  );
> +
> +  // Assigning display interface in order. Require mode information on IPU
> +  // and Display Interface valid combination
> +  DisplayModeIndex = 0;
> +  for (IpuIndex = IPU1; IpuIndex < IPU_TOTAL; IpuIndex++) {
> +    for (DisplayInterfaceIndex = DisplayInterface0;
> +         DisplayInterfaceIndex < DisplayInterfaceMax;
> +         DisplayInterfaceIndex++)
> +    {
> +      if (DisplayModeIndex >= (UINT32)DisplayMode) {
> +        break;
> +      }
> +      DisplayModeIndex++;
> +
> +      DisplayContextPtr->DisplayConfig.DiOrder[DisplayInterfaceIndex] =
> +        DiOrder[DisplayInterfaceIndex];
> +      pDisplayInterfaceContext =
> +        &DisplayContextPtr->DiContext[DiOrder[DisplayInterfaceIndex]];
> +      pDisplayInterfaceContext->IpuMmioBasePtr =
> +        DisplayContextPtr->IpuMmioBasePtr[IpuIndex];
> +      pDisplayInterfaceContext->IpuDiRegsPtr =
> +        (IPU_DIx_REGS *)(((UINTN)DisplayContextPtr->IpuMmioBasePtr[IpuIndex]) +
> +                                 DisplayInterfaceOffset[DisplayInterfaceIndex]);
> +      pDisplayInterfaceContext->CpMemParamBasePtr =
> +        (VOID *)(((UINTN)pDisplayInterfaceContext->IpuMmioBasePtr) +
> +                         CSP_IPUV3_CPMEM_REGS_OFFSET);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +ApplyDisplayConfig (
> +  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN      DISPLAY_MODE        DisplayMode,
> +  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
> +  )
> +{
> +  DISPLAY_TIMING              *pCurrentDisplayTiming;
> +  DISPLAY_CONFIG              *pDisplayConfig;
> +  DISPLAY_INTERFACE_CONTEXT   *pDisplayInterfaceContext;

No Hungarian notation please, throughout.

> +  UINT32                      CurrentDisplayInterface;
> +  UINT32                      DisplayModeIndex;
> +  EFI_STATUS                  Status;
> +
> +  Status = EFI_SUCCESS;
> +  pDisplayConfig = &DisplayContextPtr->DisplayConfig;
> +  Status = SetDisplayConfig (DisplayContextPtr, DisplayMode, DiOrder);
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to set display configuration %d\n",
> +      __FUNCTION__, DisplayMode));
> +    Status = EFI_UNSUPPORTED;
> +    goto Exit;
> +  }
> +
> +  // Setup muxing first before configuring DI and DC
> +  Status = SetupDisplayMux (DisplayContextPtr);
> +  if (Status != EFI_SUCCESS) {

if (EFI_ERROR (Status)) {

is more idiomatic. Could you replace throughout?

> +    DEBUG ((DEBUG_ERROR, "%a: SetDisplayMux failed \n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +  for (DisplayModeIndex = 0;
> +       DisplayModeIndex < (UINT32)pDisplayConfig->DisplayMode;
> +       ++DisplayModeIndex)
> +  {
> +    CurrentDisplayInterface = pDisplayConfig->DiOrder[DisplayModeIndex];
> +    pDisplayInterfaceContext = &DisplayContextPtr->DiContext[CurrentDisplayInterface];
> +    pCurrentDisplayTiming = &pDisplayConfig->DisplayTiming[DisplayModeIndex];
> +
> +    Status = ConfigureDisplayControllerChannel (
> +               pDisplayInterfaceContext,
> +               CurrentDisplayInterface,
> +               DisplayModeIndex,
> +               pCurrentDisplayTiming
> +             );
> +    if (Status != EFI_SUCCESS) {
> +      DEBUG ((DEBUG_ERROR,
> +        "%a:ConfigureDisplayControllerChannel fail display %d index %d\n",
> +        __FUNCTION__, CurrentDisplayInterface, DisplayModeIndex));
> +      goto Exit;
> +    }
> +
> +    Status = ConfigureDisplayInterface (
> +               pDisplayInterfaceContext,
> +               DisplayModeIndex,
> +               pCurrentDisplayTiming
> +             );
> +    if (Status != EFI_SUCCESS) {
> +      DEBUG ((DEBUG_ERROR, "%a: Fail to configure DI\n", __FUNCTION__));
> +      goto Exit;
> +    }
> +
> +    switch (CurrentDisplayInterface) {
> +    case HdmiDisplay:
> +      Status = SetHdmiDisplay (pDisplayInterfaceContext, pCurrentDisplayTiming);
> +      if (Status != EFI_SUCCESS) {
> +        DEBUG ((DEBUG_ERROR, "%a: Fail to set HDMI timing\n", __FUNCTION__));
> +        goto Exit;
> +      }
> +      break;
> +    case Lvds0Display:
> +    case Lvds1Display:
> +      break;
> +    default:
> +      Status = EFI_UNSUPPORTED;
> +      break;
> +    }
> +    if (EFI_ERROR (Status)) {
> +      goto Exit;
> +    }
> +
> +    Status = ConfigureFrameBuffer (
> +               pDisplayInterfaceContext,
> +               &pDisplayConfig->DisplaySurface[DisplayModeIndex]
> +             );
> +    if (Status != EFI_SUCCESS) {
> +      DEBUG ((DEBUG_ERROR,
> +        "%a: Fail to configure frame buffer (%d)\n",
> +        __FUNCTION__, DisplayModeIndex));
> +      goto Exit;
> +    }
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +AllocateFrameBuffer (
> +  IN OUT  SURFACE_INFO  *SurfaceInfoPtr
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  DEBUG ((DEBUG_INFO, "%a: Enter\n", __FUNCTION__));
> +  if ((SurfaceInfoPtr->Width == 0) || (SurfaceInfoPtr->Height == 0)) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: Frame Buffer AddrP=%Xh\n",
> +    __FUNCTION__, FixedPcdGet32 (PcdFrameBufferBase)));
> +  DEBUG ((DEBUG_INFO, "%a: Frame Buffer Size=%Xh\n",
> +    __FUNCTION__, FixedPcdGet32 (PcdFrameBufferSize)));
> +
> +  SurfaceInfoPtr->VirtAddrPtr = (VOID *)(UINTN)FixedPcdGet32 (PcdFrameBufferBase);
> +  SurfaceInfoPtr->PhyAddr = (UINT32)(SurfaceInfoPtr->VirtAddrPtr);
> +  SurfaceInfoPtr->Pitch = SurfaceInfoPtr->Width;
> +
> +  DEBUG ((DEBUG_INFO,
> +    "%a: Allocate FB PhyAddr %x VirtAddr %x\n",
> +    __FUNCTION__, SurfaceInfoPtr->PhyAddr, SurfaceInfoPtr->VirtAddrPtr));
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  DEBUG ((DEBUG_INFO, "%a: Exit = %Xh\n",
> +    __FUNCTION__, Status));
> +  return Status;
> +}
> +
> +EFI_STATUS
> +ConfigureFrameBuffer (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  SURFACE_INFO                *FrameBufferPtr
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  // Only support single display for now
> +  Status = ConfigureCpmemFrameBuffer (
> +             DisplayInterfaceContextPtr,
> +             IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE,
> +             FrameBufferPtr
> +           );
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to configure CPMEM\n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +UINT32
> +GetColorDepth (
> +  IN  PIXEL_FORMAT  PixelFormat
> +  )
> +{
> +  UINT32  BitDepth;
> +
> +  switch (PixelFormat) {
> +  case PIXEL_FORMAT_ARGB32:
> +  case PIXEL_FORMAT_BGRA32:
> +    BitDepth = 8;
> +    break;
> +  default:
> +    BitDepth = 0;
> +    break;
> +  }
> +
> +  return BitDepth;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
> new file mode 100644
> index 000000000000..cbcea1219743
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
> @@ -0,0 +1,175 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _DISPLAY_H_
> +#define _DISPLAY_H_

IMX_ prefix.

> +
> +typedef enum {
> +  UNKNOWN_MODE,
> +  SINGLE_MODE,
> +  DUAL_MODE,
> +} DISPLAY_MODE;
> +
> +typedef enum {
> +  IPU1,
> +#if !defined(CPU_IMX6SDL)
> +  IPU2,
> +#endif
> +  IPU_TOTAL,
> +} IPU_INDEX;
> +
> +typedef enum {
> +  DisplayInterface0,
> +  DisplayInterface1,
> +  DisplayInterfaceMax,
> +} DISPLAY_INTERFACE_INDEX;
> +
> +typedef enum {
> +  HdmiDisplay,
> +  MipiDisplay,
> +  Lvds0Display,
> +  Lvds1Display,
> +  DisplayTypeMax, // Only 4 display types supported by IPU
> +  NoDisplayType = DisplayTypeMax,
> +} DISPLAY_INTERFACE_TYPE;
> +
> +typedef struct _SURFACE_INFO {
> +  UINT32 PhyAddr;
> +  UINT32 *VirtAddrPtr;
> +  UINT32 Width;
> +  UINT32 Height;
> +  UINT32 Pitch;
> +  UINT32 Bpp;
> +  PIXEL_FORMAT PixelFormat;
> +} SURFACE_INFO, *PSURFACE_INFO;
> +
> +typedef struct _IPU_DIx_REGS {
> +  UINT32 DIxGENERAL;
> +  UINT32 DIxBS_CLKGEN0;
> +  UINT32 DIxBS_CLKGEN1;
> +  UINT32 DIxSW_GEN0_1;
> +  UINT32 DIxSW_GEN0_2;
> +  UINT32 DIxSW_GEN0_3;
> +  UINT32 DIxSW_GEN0_4;
> +  UINT32 DIxSW_GEN0_5;
> +  UINT32 DIxSW_GEN0_6;
> +  UINT32 DIxSW_GEN0_7;
> +  UINT32 DIxSW_GEN0_8;
> +  UINT32 DIxSW_GEN0_9;
> +  UINT32 DIxSW_GEN1_1;
> +  UINT32 DIxSW_GEN1_2;
> +  UINT32 DIxSW_GEN1_3;
> +  UINT32 DIxSW_GEN1_4;
> +  UINT32 DIxSW_GEN1_5;
> +  UINT32 DIxSW_GEN1_6;
> +  UINT32 DIxSW_GEN1_7;
> +  UINT32 DIxSW_GEN1_8;
> +  UINT32 DIxSW_GEN1_9;
> +  UINT32 DIxSYNC_AS_GEN;
> +  UINT32 DIxDW_GEN[12];
> +  UINT32 DIxDW_SET0[12];
> +  UINT32 DIxDW_SET1[12];
> +  UINT32 DIxDW_SET2[12];
> +  UINT32 DIxDW_SET3[12];
> +  UINT32 DIxSTP_REP[4];
> +  UINT32 DIxSTP_REP_9;
> +  UINT32 DIxSER_CONF;
> +  UINT32 DIxSSC;
> +  UINT32 DIxPOL;
> +  UINT32 DIxAW0;
> +  UINT32 DIxAW1;
> +  UINT32 DIxSCR_CONF;
> +  UINT32 DIxSTAT;
> +} IPU_DIx_REGS, *PIPU_DIx_REGS;
> +
> +typedef struct _DISPLAY_INTERFACE_CONTEXT {
> +  DISPLAY_INTERFACE_TYPE displayInterface;
> +
> +  VOID *MmioBasePtr;
> +  VOID *IpuMmioBasePtr;
> +  VOID *CpMemParamBasePtr;
> +  IPU_DIx_REGS *IpuDiRegsPtr;
> +  UINT32 EdidDataSize;
> +  UINT8 EdidData[256];
> +  DISPLAY_TIMING PreferredTiming;
> +} DISPLAY_INTERFACE_CONTEXT, *PDISPLAY_INTERFACE_CONTEXT;
> +
> +typedef struct _DISPLAY_CONFIG {
> +  DISPLAY_MODE DisplayMode;
> +  DISPLAY_INTERFACE_TYPE DiOrder[DisplayTypeMax];
> +  SURFACE_INFO DisplaySurface[DisplayTypeMax];
> +  DISPLAY_TIMING DisplayTiming[DisplayTypeMax];
> +  UINT32 OsHandle[DisplayTypeMax];
> +} DISPLAY_CONFIG, *PDISPLAY_CONFIG;
> +
> +typedef struct _DISPLAY_CONTEXT {
> +  DISPLAY_CONFIG DisplayConfig;
> +  VOID *IoMuxMmioBasePtr;
> +  VOID *IpuMmioBasePtr[IPU_TOTAL];
> +  DISPLAY_INTERFACE_CONTEXT DiContext[DisplayTypeMax];
> +} DISPLAY_CONTEXT, *PDISPLAY_CONTEXT;
> +
> +extern DISPLAY_TIMING DefaultTiming;

g- or m- prefix for an exported variable.

> +
> +EFI_STATUS
> +GetPreferredTiming (
> +  IN  UINT8           *EdidDataPtr,
> +  IN  UINT32          EdidDataSize,
> +  IN  DISPLAY_TIMING  *PreferredTimingPtr
> +  );
> +
> +EFI_STATUS
> +InitDisplay (
> +  IN  DISPLAY_CONTEXT   **DisplayConfigPPtr
> +  );
> +
> +EFI_STATUS
> +ValidateDisplayConfig (
> +  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN  DISPLAY_MODE        DisplayMode,
> +  IN  DISPLAY_INTERFACE_TYPE   *DiOrder
> +  );
> +
> +EFI_STATUS
> +SetDisplayConfig (
> +  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN      DISPLAY_MODE        DisplayMode,
> +  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
> +  );
> +
> +EFI_STATUS
> +ApplyDisplayConfig (
> +  IN OUT  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN      DISPLAY_MODE        DisplayMode,
> +  IN      DISPLAY_INTERFACE_TYPE   *DiOrder
> +  );
> +
> +EFI_STATUS
> +AllocateFrameBuffer (
> +  IN OUT  SURFACE_INFO  *SurfaceInfoPtr
> +  );
> +
> +EFI_STATUS
> +ConfigureFrameBuffer (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  SURFACE_INFO                *FrameBufferPtr
> +  );
> +
> +UINT32
> +GetColorDepth (
> +  IN  PIXEL_FORMAT  PixelFormat
> +  );
> +
> +#endif  /* _DISPLAY_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
> new file mode 100644
> index 000000000000..7a5fc7e3d6c3
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
> @@ -0,0 +1,399 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Ipu.h"
> +#include "Display.h"
> +#include "DisplayController.h"
> +#include "DisplayInterface.h"
> +
> +#ifdef DEBUG
> +VOID
> +DumpBasicDisplayControllerReg (
> +  IN  VOID  *IpuMmioBasePtr
> +  )
> +{
> +  UINT32 Counter;
> +  UINT32 Index;
> +  UINT32 RegVal;
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ------- DC Register Dump -------\n", __FUNCTION__));
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ## Configuration\n\n", __FUNCTION__));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_WR_CH_CONF_5_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_1_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_WR_CH_CONF_1_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_0_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_0_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_1_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_1_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_2_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_2_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_3_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_3_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF2_0_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF2_0_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_GEN_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_GEN_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ## Bus MAPPING\n\n", __FUNCTION__));
> +  {

Please move the { to the end of the preceding line.

> +    for (Counter = 0, Index = 0; Index < 26; Counter += 4, ++Index) {

++ suffix rather than prefix, please.

> +      RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_MAP_CONF_0_OFFSET + Counter);
> +      DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_MAP_CONF_%d %x\n",
> +        __FUNCTION__, Index, RegVal));
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ## Channel MicroCode setup\n\n", __FUNCTION__));
> +  // Only print out channel 5 as we only support single mode for now
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL0_CH_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL0_CH_5_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL1_CH_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL1_CH_5_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL2_CH_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL2_CH_5_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL3_CH_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL3_CH_5_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +  RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL4_CH_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL4_CH_5_OFFSET %x\n",
> +    __FUNCTION__, RegVal));
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ## MicroCode\n\n", __FUNCTION__));
> +  // There are 256 template, only print out the first 10
> +  for (Counter = 0, Index = 0; Index < 10; Counter += 8, ++Index) {
> +    DEBUG ((DEBUG_VERBOSE, "%a: (%d)\n", __FUNCTION__, Index));
> +    RegVal = IpuRead32 (
> +                IpuMmioBasePtr,
> +                IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + Counter);
> +    DEBUG ((DEBUG_VERBOSE, "%a: - %8x\n", __FUNCTION__, RegVal));
> +    RegVal = IpuRead32 (
> +                IpuMmioBasePtr,
> +                IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + Counter + 4);
> +    DEBUG ((DEBUG_VERBOSE, "%a:  %8x -\n", __FUNCTION__, RegVal));
> +  }
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ---------------------------\n\n", __FUNCTION__));
> +}
> +#endif /* DEBUG */
> +
> +EFI_STATUS
> +WriteWrodCommand (
> +  IN  VOID    *IpuMmioBasePtr,
> +  IN  UINT32  MicroCodeAddr,
> +  IN  UINT32  Data,
> +  IN  UINT32  Mapping,
> +  IN  UINT32  WaveForm,
> +  IN  UINT32  GlueLogic,
> +  IN  UINT32  Sync
> +  )
> +{
> +  UINT32                            MicroCodeAddrOffset;
> +  DISPLAY_CONTROLLER_WROD_COMMAND   WrodCommand;
> +
> +
> +  MicroCodeAddrOffset = IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + (MicroCodeAddr * 8);
> +  ZeroMem ((VOID *)&WrodCommand, sizeof (WrodCommand));
> +  WrodCommand.STOP = 1;
> +  WrodCommand.OPCODE = 0x18;
> +  WrodCommand.DATA = Data;
> +  WrodCommand.MAPPING = Mapping;
> +  WrodCommand.WAVEFORM = WaveForm + 1;
> +  WrodCommand.GLUELOGIC = GlueLogic;
> +  WrodCommand.SYNC = Sync;
> +  IpuWrite32 (IpuMmioBasePtr, MicroCodeAddrOffset, WrodCommand.LowWord);
> +  IpuWrite32 (IpuMmioBasePtr, MicroCodeAddrOffset + 4, WrodCommand.HighWord);
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SetDisplayControllerChannelState (
> +  IN  VOID *IpuMmioBasePtr,
> +  IN  PROG_CHAN_TYP ChannelType
> +  )
> +{
> +  IPU_DC_WR_CH_CONF_5_REG   WrChConfigReg;
> +
> +  WrChConfigReg.Reg = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET);
> +  WrChConfigReg.PROG_CHAN_TYP = ChannelType;
> +  IpuWrite32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET, WrChConfigReg.Reg);
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ConfigureDisplayControllerChannel (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  DISPLAY_INTERFACE_TYPE           DisplayInterface,
> +  IN  UINT32                      DisplayIndex,
> +  IN  DISPLAY_TIMING              *DisplayTimingPtr
> +  )
> +{
> +  VOID                          *pIpuMmioBase;
> +  DC_MAP_CONF_OFFSET_MASK_REG   DcConfOffsetMaskReg;
> +  IPUx_DC_MAP_CONF_MAP_REG      DcMapConf0Reg;
> +  IPU_DC_RL0_CH_5_REG           DcRl0Ch5Reg;
> +  IPU_DC_RL2_CH_5_REG           DcRl2Ch5Reg;
> +  IPU_DC_RL4_CH_5_REG           DcRl4Ch5Reg;
> +  IPUx_DC_DISP_CONF1_REG        DisplayConfig1Reg;
> +  IPUx_IPU_DC_GEN_REG           DisplayControllerGenReg;
> +  UINT32                        Mask0;
> +  UINT32                        Mask1;
> +  UINT32                        Mask2;
> +  UINT32                        Offset0;
> +  UINT32                        Offset1;
> +  UINT32                        Offset2;
> +  EFI_STATUS                    Status;
> +  IPU_DC_WR_CH_CONF_5_REG       WrChConfigReg;
> +
> +  pIpuMmioBase = DisplayInterfaceContextPtr->IpuMmioBasePtr;
> +  Status = EFI_SUCCESS;
> +
> +  ZeroMem ((VOID *)&WrChConfigReg, sizeof (WrChConfigReg));
> +  WrChConfigReg.PROG_START_TIME = 0;
> +  WrChConfigReg.FILED_MODE = 0;
> +  WrChConfigReg.CHAN_MASK_DEFAULT = 0; // only used highest priority
> +  WrChConfigReg.PROG_CHAN_TYP = 0; // Begin as disable
> +  WrChConfigReg.PROG_DISP_ID = DisplayInterface;
> +  WrChConfigReg.PROG_DI_ID = DisplayIndex % 2;
> +  WrChConfigReg.W_SIZE = 0x02; // 24 Bits
> +  WrChConfigReg.Reserved1 = 0;
> +  WrChConfigReg.Reserved2 = 0;
> +  // Channel 5 is used main primary flow
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_CONF_5_OFFSET, WrChConfigReg.Reg);
> +  // Start address of memory always 0
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_ADDR_5_OFFSET, 0);
> +
> +  ZeroMem ((VOID *)&WrChConfigReg, sizeof (WrChConfigReg));
> +  WrChConfigReg.FILED_MODE = 0;
> +  WrChConfigReg.CHAN_MASK_DEFAULT = 0; // only used highest priority
> +  WrChConfigReg.PROG_CHAN_TYP = 4; // Enable
> +  WrChConfigReg.PROG_DISP_ID = DisplayInterface;
> +  WrChConfigReg.PROG_DI_ID = DisplayIndex % 2;
> +  WrChConfigReg.W_SIZE = 0x02; // 1 Bits
> +  WrChConfigReg.Reserved1 = 0;
> +  WrChConfigReg.Reserved2 = 0;
> +
> +  // Channel 1 is used as sync/async flow
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_CONF_1_OFFSET, WrChConfigReg.Reg);
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_ADDR_1_OFFSET, 0);
> +
> +  DisplayConfig1Reg.DISP_TYP = 0x02; // What is byte_enabled
> +  DisplayConfig1Reg.ADDR_INCREMENT = 0; // Increase by 1 byte
> +  DisplayConfig1Reg.ADDR_BE_L_INC = 0;
> +  DisplayConfig1Reg.MCU_ACC_LB_MASK_3 = 0;
> +  DisplayConfig1Reg.DISP_RD_VALUE_PTR = 0;
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_DISP_CONF1_0_OFFSET, DisplayConfig1Reg.Reg);
> +
> +  // Set stride
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_DISP_CONF2_0_OFFSET, DisplayTimingPtr->VActive);
> +
> +  // Setup general register. Channel 5 is the main channel.
> +  DisplayControllerGenReg.Sync_1_6 = 2; // Sync flow
> +  DisplayControllerGenReg.MASK_EN = 0; // Disable masking
> +  DisplayControllerGenReg.MASK4CHAN_5 = 0; // Ignore as mask is disabled
> +  DisplayControllerGenReg.SYNC_PRIORITY_5 = 1; // Higher sync priority for channel 5
> +  DisplayControllerGenReg.SYNC_PRIORITY_1 = 0; // Lower sync priority
> +  DisplayControllerGenReg.DC_CH5_TYPE = 0; // Normal mode, sync flow through channel 5
> +  DisplayControllerGenReg.DC_BK_EN = 0; // No cursor support
> +  DisplayControllerGenReg.DC_BKDIV = 0; // No cursor support
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_GEN_OFFSET, DisplayControllerGenReg.Reg);
> +
> +  // Do not use any user event
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE0_0_OFFSET, 0);
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE1_0_OFFSET, 0);
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE2_0_OFFSET, 0);
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE3_0_OFFSET, 0);
> +
> +  DcMapConf0Reg.MAPPING_PNTR_BYTE0_X = 0;
> +  DcMapConf0Reg.MAPPING_PNTR_BYTE1_X = 1;
> +  DcMapConf0Reg.MAPPING_PNTR_BYTE2_X = 2;
> +  DcMapConf0Reg.MAPPING_PNTR_BYTE0_Y = 3; // Unused
> +  DcMapConf0Reg.MAPPING_PNTR_BYTE1_Y = 4; // Unused
> +  DcMapConf0Reg.MAPPING_PNTR_BYTE2_Y = 5; // Unused
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_0_OFFSET, DcMapConf0Reg.Reg);
> +
> +  switch (DisplayInterface) {
> +  // PixelFormat RGB24
> +  case HdmiDisplay:
> +    Mask0 = 0xFF;
> +    Mask1 = 0xFF;
> +    Mask2 = 0xFF;
> +    Offset0 = 7;
> +    Offset1 = 15;
> +    Offset2 = 23;
> +    break;
> +  // PixelFormat RGB666
> +  case Lvds0Display:
> +  case Lvds1Display:
> +    Mask0 = 0xFC;
> +    Mask1 = 0xFC;
> +    Mask2 = 0xFC;
> +    Offset0 = 5;
> +    Offset1 = 11;
> +    Offset2 = 17;
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    Status = EFI_UNSUPPORTED;
> +    break;
> +  }
> +  if (EFI_ERROR (Status)) {
> +    goto Exit;
> +  }
> +
> +  DcConfOffsetMaskReg.MD_MASK_X = Mask0;
> +  DcConfOffsetMaskReg.MD_OFFSET_X = Offset0; // Blue
> +  DcConfOffsetMaskReg.MD_MASK_Y = Mask1;
> +  DcConfOffsetMaskReg.MD_OFFSET_Y = Offset1; // Green
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_15_OFFSET, DcConfOffsetMaskReg.Reg);
> +
> +  DcConfOffsetMaskReg.MD_MASK_X = Mask2;
> +  DcConfOffsetMaskReg.MD_OFFSET_X = Offset2; // Red
> +  DcConfOffsetMaskReg.MD_MASK_Y = 0x00;
> +  DcConfOffsetMaskReg.MD_OFFSET_Y = 0; // Unused
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_16_OFFSET, DcConfOffsetMaskReg.Reg);
> +
> +  // Setup microcode
> +  // New line event point to the first microcode (0)
> +  ZeroMem ((VOID *)&DcRl0Ch5Reg, sizeof (DcRl0Ch5Reg));
> +  DcRl0Ch5Reg.COD_NL_START_CHAN_5 = 0;
> +  DcRl0Ch5Reg.COD_NL_PRIORITY_CHAN_5 = 3;
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_RL0_CH_5_OFFSET, DcRl0Ch5Reg.Reg);
> +
> +  // End of line event point to the second microcode (1)
> +  ZeroMem ((VOID *)&DcRl2Ch5Reg, sizeof (DcRl2Ch5Reg));
> +  DcRl2Ch5Reg.COD_EOL_START_CHAN_5 = 1;
> +  DcRl2Ch5Reg.COD_EOL_PRIORITY_CHAN_5 = 2;
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_RL2_CH_5_OFFSET, DcRl2Ch5Reg.Reg);
> +
> +  // New data event point to the first microcode (2)
> +  ZeroMem ((VOID *)&DcRl4Ch5Reg, sizeof (DcRl4Ch5Reg));
> +  DcRl4Ch5Reg.COD_NEW_DATA_START_CHAN_5 = 2;
> +  DcRl4Ch5Reg.COD_NEW_DATA_PRIORITY_CHAN_5 = 1;
> +  IpuWrite32 (pIpuMmioBase, IPU_DC_RL4_CH_5_OFFSET, DcRl4Ch5Reg.Reg);
> +
> +  // MicroCodeAddr
> +  // - 0 set for new line event
> +  // Data
> +  // - Unsused
> +  // Map to mapping parameter 0
> +  // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0,
> +  //   MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field
> +  // WaveForm
> +  // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform
> +  //   register is used, default to first IPUx_DI0_DW_SET0_1)
> +  // GlueLogic
> +  // - Once the signal is asserted then it remains asserted (high or low
> +  //   according to the polarity)
> +  // Sync
> +  // - Sync with Counter 5
> +  WriteWrodCommand (
> +    pIpuMmioBase,
> +    0,
> +    0,
> +    1,
> +    DwGen0,
> +    8,
> +    DI_COUNTER_5_ACTIVE_CLOCK
> +  );
> +
> +  // MicroCodeAddr
> +  // - 1 set for end of line event
> +  // Data
> +  // - Unsused
> +  // Map to mapping parameter 0
> +  // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0,
> +  //   MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field
> +  // WaveForm
> +  // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform
> +  //   register is used, default to first IPUx_DI0_DW_SET0_1)
> +  // GlueLogic
> +  // - Once the signal is negated then it remains negated (high or low
> +  //   according to the polarity)
> +  // Sync
> +  // - Sync with Counter 5
> +  WriteWrodCommand (
> +    pIpuMmioBase,
> +    1,
> +    0,
> +    1,
> +    DwGen0,
> +    4,
> +    DI_COUNTER_5_ACTIVE_CLOCK
> +  );
> +
> +  // MicroCodeAddr
> +  // - 2 set for new data event
> +  // Data
> +  // - Unsused
> +  // Map to mapping parameter 0
> +  // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0,
> +  //   MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field
> +  // WaveForm
> +  // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform
> +  //   register is used, default to first IPUx_DI0_DW_SET0_1)
> +  // GlueLogic
> +  // - CS mode No impact on the waveform
> +  // Sync
> +  // - Sync with channel 5
> +  WriteWrodCommand (
> +    pIpuMmioBase,
> +    2,
> +    0,
> +    1,
> +    DwGen0,
> +    8,
> +    DI_COUNTER_5_ACTIVE_CLOCK
> +  );
> +
> +  // Turn on channel without anti tearing
> +  SetDisplayControllerChannelState (
> +    DisplayInterfaceContextPtr->IpuMmioBasePtr,
> +    PROG_CHAN_TYP_NORMAL
> +  );
> +
> +#ifdef DEBUG
> +  DumpBasicDisplayControllerReg (pIpuMmioBase);
> +#endif /* DEBUG */
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
> new file mode 100644
> index 000000000000..46f0fa66d674
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
> @@ -0,0 +1,331 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _DISPLAY_CONTROLLER_H_
> +#define _DISPLAY_CONTROLLER_H_

IMX_ prefix please.

> +
> +#define IPU_DC_OFFSET 0x00058000
> +
> +// DC Registers
> +#define IPU_DC_READ_CH_CONF_OFFSET              IPU_DC_OFFSET + 0x0000
> +#define IPU_DC_READ_CH_ADDR_OFFSET              IPU_DC_OFFSET + 0x0004
> +#define IPU_DC_RL0_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0008
> +#define IPU_DC_RL1_CH_0_OFFSET                  IPU_DC_OFFSET + 0x000C
> +#define IPU_DC_RL2_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0010
> +#define IPU_DC_RL3_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0014
> +#define IPU_DC_RL4_CH_0_OFFSET                  IPU_DC_OFFSET + 0x0018
> +#define IPU_DC_WR_CH_CONF_1_OFFSET              IPU_DC_OFFSET + 0x001C
> +#define IPU_DC_WR_CH_ADDR_1_OFFSET              IPU_DC_OFFSET + 0x0020
> +#define IPU_DC_RL0_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0024
> +#define IPU_DC_RL1_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0028
> +#define IPU_DC_RL2_CH_1_OFFSET                  IPU_DC_OFFSET + 0x002C
> +#define IPU_DC_RL3_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0030
> +#define IPU_DC_RL4_CH_1_OFFSET                  IPU_DC_OFFSET + 0x0034
> +#define IPU_DC_WR_CH_CONF_2_OFFSET              IPU_DC_OFFSET + 0x0038
> +#define IPU_DC_WR_CH_ADDR_2_OFFSET              IPU_DC_OFFSET + 0x003C
> +#define IPU_DC_RL0_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0040
> +#define IPU_DC_RL1_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0044
> +#define IPU_DC_RL2_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0048
> +#define IPU_DC_RL3_CH_2_OFFSET                  IPU_DC_OFFSET + 0x004C
> +#define IPU_DC_RL4_CH_2_OFFSET                  IPU_DC_OFFSET + 0x0050
> +#define IPU_DC_CMD_CH_CONF_3_OFFSET             IPU_DC_OFFSET + 0x0054
> +#define IPU_DC_CMD_CH_CONF_4_OFFSET             IPU_DC_OFFSET + 0x0058
> +#define IPU_DC_WR_CH_CONF_5_OFFSET              IPU_DC_OFFSET + 0x005C
> +#define IPU_DC_WR_CH_ADDR_5_OFFSET              IPU_DC_OFFSET + 0x0060
> +#define IPU_DC_RL0_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0064
> +#define IPU_DC_RL1_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0068
> +#define IPU_DC_RL2_CH_5_OFFSET                  IPU_DC_OFFSET + 0x006C
> +#define IPU_DC_RL3_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0070
> +#define IPU_DC_RL4_CH_5_OFFSET                  IPU_DC_OFFSET + 0x0074
> +#define IPU_DC_WR_CH_CONF_6_OFFSET              IPU_DC_OFFSET + 0x0078
> +#define IPU_DC_WR_CH_ADDR_6_OFFSET              IPU_DC_OFFSET + 0x007C
> +#define IPU_DC_RL0_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0080
> +#define IPU_DC_RL1_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0084
> +#define IPU_DC_RL2_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0088
> +#define IPU_DC_RL3_CH_6_OFFSET                  IPU_DC_OFFSET + 0x008C
> +#define IPU_DC_RL4_CH_6_OFFSET                  IPU_DC_OFFSET + 0x0090
> +#define IPU_DC_WR_CH_CONF1_8_OFFSET             IPU_DC_OFFSET + 0x0094
> +#define IPU_DC_WR_CH_CONF2_8_OFFSET             IPU_DC_OFFSET + 0x0098
> +#define IPU_DC_RL1_CH_8_OFFSET                  IPU_DC_OFFSET + 0x009C
> +#define IPU_DC_RL2_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00A0
> +#define IPU_DC_RL3_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00A4
> +#define IPU_DC_RL4_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00A8
> +#define IPU_DC_RL5_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00AC
> +#define IPU_DC_RL6_CH_8_OFFSET                  IPU_DC_OFFSET + 0x00B0
> +#define IPU_DC_WR_CH_CONF1_9_OFFSET             IPU_DC_OFFSET + 0x00B4
> +#define IPU_DC_WR_CH_CONF2_9_OFFSET             IPU_DC_OFFSET + 0x00B8
> +#define IPU_DC_RL1_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00BC
> +#define IPU_DC_RL2_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00C0
> +#define IPU_DC_RL3_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00C4
> +#define IPU_DC_RL4_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00C8
> +#define IPU_DC_RL5_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00CC
> +#define IPU_DC_RL6_CH_9_OFFSET                  IPU_DC_OFFSET + 0x00D0
> +#define IPU_DC_GEN_OFFSET                       IPU_DC_OFFSET + 0x00D4
> +#define IPU_DC_DISP_CONF1_0_OFFSET              IPU_DC_OFFSET + 0x00D8
> +#define IPU_DC_DISP_CONF1_1_OFFSET              IPU_DC_OFFSET + 0x00DC
> +#define IPU_DC_DISP_CONF1_2_OFFSET              IPU_DC_OFFSET + 0x00E0
> +#define IPU_DC_DISP_CONF1_3_OFFSET              IPU_DC_OFFSET + 0x00E4
> +#define IPU_DC_DISP_CONF2_0_OFFSET              IPU_DC_OFFSET + 0x00E8
> +#define IPU_DC_DISP_CONF2_1_OFFSET              IPU_DC_OFFSET + 0x00EC
> +#define IPU_DC_DISP_CONF2_2_OFFSET              IPU_DC_OFFSET + 0x00F0
> +#define IPU_DC_DISP_CONF2_3_OFFSET              IPU_DC_OFFSET + 0x00F4
> +#define IPU_DC_DI0_CONF1_OFFSET                 IPU_DC_OFFSET + 0x00F8
> +#define IPU_DC_DI0_CONF2_OFFSET                 IPU_DC_OFFSET + 0x00FC
> +#define IPU_DC_DI1_CONF1_OFFSET                 IPU_DC_OFFSET + 0x0100
> +#define IPU_DC_DI1_CONF2_OFFSET                 IPU_DC_OFFSET + 0x0104
> +#define IPU_DC_MAP_CONF_0_OFFSET                IPU_DC_OFFSET + 0x0108
> +#define IPU_DC_MAP_CONF_1_OFFSET                IPU_DC_OFFSET + 0x010C
> +#define IPU_DC_MAP_CONF_2_OFFSET                IPU_DC_OFFSET + 0x0110
> +#define IPU_DC_MAP_CONF_3_OFFSET                IPU_DC_OFFSET + 0x0114
> +#define IPU_DC_MAP_CONF_4_OFFSET                IPU_DC_OFFSET + 0x0118
> +#define IPU_DC_MAP_CONF_5_OFFSET                IPU_DC_OFFSET + 0x011C
> +#define IPU_DC_MAP_CONF_6_OFFSET                IPU_DC_OFFSET + 0x0120
> +#define IPU_DC_MAP_CONF_7_OFFSET                IPU_DC_OFFSET + 0x0124
> +#define IPU_DC_MAP_CONF_8_OFFSET                IPU_DC_OFFSET + 0x0128
> +#define IPU_DC_MAP_CONF_9_OFFSET                IPU_DC_OFFSET + 0x012C
> +#define IPU_DC_MAP_CONF_10_OFFSET               IPU_DC_OFFSET + 0x0130
> +#define IPU_DC_MAP_CONF_11_OFFSET               IPU_DC_OFFSET + 0x0134
> +#define IPU_DC_MAP_CONF_12_OFFSET               IPU_DC_OFFSET + 0x0138
> +#define IPU_DC_MAP_CONF_13_OFFSET               IPU_DC_OFFSET + 0x013C
> +#define IPU_DC_MAP_CONF_14_OFFSET               IPU_DC_OFFSET + 0x0140
> +#define IPU_DC_MAP_CONF_15_OFFSET               IPU_DC_OFFSET + 0x0144
> +#define IPU_DC_MAP_CONF_16_OFFSET               IPU_DC_OFFSET + 0x0148
> +#define IPU_DC_MAP_CONF_17_OFFSET               IPU_DC_OFFSET + 0x014C
> +#define IPU_DC_MAP_CONF_18_OFFSET               IPU_DC_OFFSET + 0x0150
> +#define IPU_DC_MAP_CONF_19_OFFSET               IPU_DC_OFFSET + 0x0154
> +#define IPU_DC_MAP_CONF_20_OFFSET               IPU_DC_OFFSET + 0x0158
> +#define IPU_DC_MAP_CONF_21_OFFSET               IPU_DC_OFFSET + 0x015C
> +#define IPU_DC_MAP_CONF_22_OFFSET               IPU_DC_OFFSET + 0x0160
> +#define IPU_DC_MAP_CONF_23_OFFSET               IPU_DC_OFFSET + 0x0164
> +#define IPU_DC_MAP_CONF_24_OFFSET               IPU_DC_OFFSET + 0x0168
> +#define IPU_DC_MAP_CONF_25_OFFSET               IPU_DC_OFFSET + 0x016C
> +#define IPU_DC_MAP_CONF_26_OFFSET               IPU_DC_OFFSET + 0x0170
> +#define IPU_DC_UGDE0_0_OFFSET                   IPU_DC_OFFSET + 0x0174
> +#define IPU_DC_UGDE0_1_OFFSET                   IPU_DC_OFFSET + 0x0178
> +#define IPU_DC_UGDE0_2_OFFSET                   IPU_DC_OFFSET + 0x017C
> +#define IPU_DC_UGDE0_3_OFFSET                   IPU_DC_OFFSET + 0x0180
> +#define IPU_DC_UGDE1_0_OFFSET                   IPU_DC_OFFSET + 0x0184
> +#define IPU_DC_UGDE1_1_OFFSET                   IPU_DC_OFFSET + 0x0188
> +#define IPU_DC_UGDE1_2_OFFSET                   IPU_DC_OFFSET + 0x018C
> +#define IPU_DC_UGDE1_3_OFFSET                   IPU_DC_OFFSET + 0x0190
> +#define IPU_DC_UGDE2_0_OFFSET                   IPU_DC_OFFSET + 0x0194
> +#define IPU_DC_UGDE2_1_OFFSET                   IPU_DC_OFFSET + 0x0198
> +#define IPU_DC_UGDE2_2_OFFSET                   IPU_DC_OFFSET + 0x019C
> +#define IPU_DC_UGDE2_3_OFFSET                   IPU_DC_OFFSET + 0x01A0
> +#define IPU_DC_UGDE3_0_OFFSET                   IPU_DC_OFFSET + 0x01A4
> +#define IPU_DC_UGDE3_1_OFFSET                   IPU_DC_OFFSET + 0x01A8
> +#define IPU_DC_UGDE3_2_OFFSET                   IPU_DC_OFFSET + 0x01AC
> +#define IPU_DC_UGDE3_3_OFFSET                   IPU_DC_OFFSET + 0x01B0
> +#define IPU_DC_LLA0_OFFSET                      IPU_DC_OFFSET + 0x01B4
> +#define IPU_DC_LLA1_OFFSET                      IPU_DC_OFFSET + 0x01B8
> +#define IPU_DC_R_LLA0_OFFSET                    IPU_DC_OFFSET + 0x01BC
> +#define IPU_DC_R_LLA1_OFFSET                    IPU_DC_OFFSET + 0x01C0
> +#define IPU_DC_WR_CH_ADDR_5_ALT_OFFSET          IPU_DC_OFFSET + 0x01C4
> +#define IPU_DC_STAT_OFFSET                      IPU_DC_OFFSET + 0x01C8
> +
> +// Microcode template
> +#define IPU_DC_TEMPLATE_REGS_ADDR_OFFSET        0x00180000
> +
> +typedef enum {
> +  DC_CHANNEL_READ = 0,
> +  DC_CHANNEL_DC_SYNC_ASYNC = 1,
> +  DC_CHANNEL_DC_ASYNC = 2,
> +  DC_CHANNEL_DP_MAIN = 5,
> +  DC_CHANNEL_DP_SECONDARY = 6,
> +} DC_CHANNEL;
> +
> +#pragma pack(push, 1)
> +
> +// IPU_DC_WR_CH_CONF_1 0x1C
> +// IPU_DC_WR_CH_CONF_5 0x5C
> +typedef union {
> +  struct {
> +    UINT32 W_SIZE : 2;
> +    UINT32 PROG_DI_ID : 1;
> +    UINT32 PROG_DISP_ID : 2;
> +    UINT32 PROG_CHAN_TYP : 3;
> +    UINT32 CHAN_MASK_DEFAULT : 1;
> +    UINT32 FILED_MODE : 1;
> +    UINT32 Reserved1 : 6;
> +    UINT32 PROG_START_TIME : 11;
> +    UINT32 Reserved2 : 5;
> +  };
> +  UINT32 Reg;
> +} IPU_DC_WR_CH_CONF_1_REG, IPU_DC_WR_CH_CONF_5_REG;
> +
> +typedef enum {
> +  PROG_CHAN_TYP_DISABLED,
> +  PROG_CHAN_TYP_RESERVED1,
> +  PROG_CHAN_TYP_NORMAL = 4,
> +  PROG_CHAN_TYP_NORMAL_ANTI_TEARING,
> +  PROG_CHAN_TYP_RESERVED2,
> +} PROG_CHAN_TYP;
> +
> +// IPU_DC_GEN 0xD4
> +typedef union {
> +  struct {
> +    UINT32 Reserved1 : 1;
> +    UINT32 Sync_1_6 : 2;
> +    UINT32 Reserved2 : 1;
> +    UINT32 MASK_EN : 1;
> +    UINT32 MASK4CHAN_5 : 1;
> +    UINT32 SYNC_PRIORITY_5 : 1;
> +    UINT32 SYNC_PRIORITY_1 : 1;
> +    UINT32 DC_CH5_TYPE : 1;
> +    UINT32 Reserved3 : 7;
> +    UINT32 DC_BKDIV : 8;
> +    UINT32 DC_BK_EN : 1;
> +    UINT32 Reserved4 : 7;
> +  };
> +  UINT32 Reg;
> +} IPUx_IPU_DC_GEN_REG;
> +
> +// IPU_DC_RL0_CH_5 0x0064
> +typedef union {
> +  struct {
> +    UINT32 COD_NF_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved1 : 4;
> +    UINT32 COD_NF_START_CHAN_5 : 8;
> +    UINT32 COD_NL_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved2 : 4;
> +    UINT32 COD_NL_START_CHAN_5 : 24;
> +  };
> +  UINT32 Reg;
> +} IPU_DC_RL0_CH_5_REG;
> +
> +// IPU_DC_RL1_CH_5 0x006C
> +typedef union {
> +  struct {
> +    UINT32 COD_EOF_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved1 : 4;
> +    UINT32 COD_EOF_START_CHAN_5 : 8;
> +    UINT32 COD_NFIELD_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved2 : 4;
> +    UINT32 COD_NFIELD_START_CHAN_5 : 24;
> +  };
> +  UINT32 Reg;
> +} IPU_DC_RL1_CH_5_REG;
> +
> +// IPU_DC_RL2_CH_5 0x0068
> +typedef union {
> +  struct {
> +    UINT32 COD_EOL_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved1 : 4;
> +    UINT32 COD_EOL_START_CHAN_5 : 8;
> +    UINT32 COD_EOFIELD_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved2 : 4;
> +    UINT32 COD_EOFIELD_START_CHAN_5 : 24;
> +  };
> +  UINT32 Reg;
> +} IPU_DC_RL2_CH_5_REG;
> +
> +// IPU_DC_RL3_CH_5 0x0070
> +typedef union {
> +  struct {
> +    UINT32 COD_NEW_ADDR_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved1 : 4;
> +    UINT32 COD_NEW_ADDR_START_CHAN_5 : 8;
> +    UINT32 COD_NEW_CHAN_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved2 : 4;
> +    UINT32 COD_NEW_CHAN_START_CHAN_5 : 24;
> +  };
> +  UINT32 Reg;
> +} IPU_DC_RL3_CH_5_REG;
> +
> +// IPU_DC_RL4_CH_5 0x0074
> +typedef union {
> +  struct {
> +    UINT32 COD_NEW_DATA_PRIORITY_CHAN_5 : 4;
> +    UINT32 Reserved1 : 4;
> +    UINT32 COD_NEW_DATA_START_CHAN_5 : 8;
> +    UINT32 Reserved2 : 16;
> +  };
> +  UINT32 Reg;
> +} IPU_DC_RL4_CH_5_REG;
> +
> +// DC_DISP_CONF1 0xD8 - 0xE4
> +typedef union {
> +  struct {
> +    UINT32 DISP_TYP : 2;
> +    UINT32 ADDR_INCREMENT : 2;
> +    UINT32 ADDR_BE_L_INC : 2;
> +    UINT32 MCU_ACC_LB_MASK_3 : 1;
> +    UINT32 DISP_RD_VALUE_PTR : 1;
> +    UINT32 Reserved : 24;
> +  };
> +  UINT32 Reg;
> +} IPUx_DC_DISP_CONF1_REG;
> +
> +// DC_MAP_CONF_MAP_OFFSET 0x0108 - 0x0140
> +typedef union {
> +  struct {
> +    UINT32 MAPPING_PNTR_BYTE0_X : 5;
> +    UINT32 MAPPING_PNTR_BYTE1_X : 5;
> +    UINT32 MAPPING_PNTR_BYTE2_X : 5;
> +    UINT32 Reserved1 : 1;
> +    UINT32 MAPPING_PNTR_BYTE0_Y : 5;
> +    UINT32 MAPPING_PNTR_BYTE1_Y : 5;
> +    UINT32 MAPPING_PNTR_BYTE2_Y : 5;
> +    UINT32 Reserved2 : 1;
> +  };
> +  UINT32 Reg;
> +} IPUx_DC_MAP_CONF_MAP_REG;
> +
> +// DC_MAP_CONF_OFFSET_MASK_OFFSET 0x0144 - 0x0170
> +typedef union {
> +  struct {
> +    UINT32 MD_MASK_X : 8;
> +    UINT32 MD_OFFSET_X : 5;
> +    UINT32 Reserved1 : 3;
> +    UINT32 MD_MASK_Y : 8;
> +    UINT32 MD_OFFSET_Y : 5;
> +    UINT32 Reserved2 : 3;
> +  };
> +  UINT32 Reg;
> +} DC_MAP_CONF_OFFSET_MASK_REG;
> +
> +typedef union {
> +  struct {
> +    UINT32 SYNC : 4;
> +    UINT32 GLUELOGIC : 7;
> +    UINT32 WAVEFORM : 4;
> +    UINT32 MAPPING : 5;
> +    UINT32 DATA : 16;
> +    UINT32 OPCODE : 5;
> +    UINT32 STOP : 1;
> +    UINT32 Unused : 22;
> +  };
> +  struct     {
> +    UINT32 LowWord;
> +    UINT32 HighWord;
> +  };
> +} DISPLAY_CONTROLLER_WROD_COMMAND;
> +
> +#pragma pack(pop)
> +
> +EFI_STATUS
> +SetDisplayControllerChannelState (
> +  IN  VOID *IpuMmioBasePtr,
> +  IN  PROG_CHAN_TYP ChannelType
> +  );
> +
> +EFI_STATUS
> +ConfigureDisplayControllerChannel (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  DISPLAY_INTERFACE_TYPE           DisplayInterface,
> +  IN  UINT32                      DisplayIndex,
> +  IN  DISPLAY_TIMING              *DisplayTimingPtr
> +  );
> +
> +#endif  /* _DISPLAY_CONTROLLER_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
> new file mode 100644
> index 000000000000..b36d03239652
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
> @@ -0,0 +1,458 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Ipu.h"
> +#include "Display.h"
> +#include "DisplayInterface.h"
> +
> +#ifdef DEBUG
> +VOID
> +DumpBasicDisplayInterfaceReg (
> +  IN  VOID          *IpuMmioBasePtr,
> +  IN  IPU_DIx_REGS  *IpuDiRegsPtr
> +  )
> +{
> +  UINT32 index, setNumber, regVal;
> +  UINT32 printTotalGen = 8; // Limit printing (max 12)
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: ------- DI Register Dump -------\n", __FUNCTION__));
> +  // Print out generator value for D0
> +  DEBUG ((DEBUG_VERBOSE, "%a: ## Wave Gen\n", __FUNCTION__));
> +  for (index = 0; index < printTotalGen; ++index) {
> +    regVal = READ_WAVE_GEN (IpuDiRegsPtr, index);
> +    DEBUG ((DEBUG_VERBOSE, "%a: DI0_DW_GEN_%d 0x%08x\n",
> +      __FUNCTION__, index, regVal));
> +  }
> +  // Print out generator value for D0
> +  DEBUG ((DEBUG_VERBOSE, "%a: ## Wave Set\n", __FUNCTION__));
> +  for (index = 0; index < printTotalGen; ++index) {
> +    for (setNumber = 0; setNumber < 4; ++setNumber) {
> +      regVal = READ_WAVE_SET (IpuDiRegsPtr, index, setNumber);
> +      DEBUG ((DEBUG_VERBOSE, "%a: DI0_DW_SET%d_%d 0x%08x\n",
> +        __FUNCTION__, setNumber, index, regVal));
> +    }
> +  }
> +
> +  regVal = IpuRead32 (IpuMmioBasePtr, IPU_IPU_PM_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_IPU_PM_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_BS_CLKGEN0_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_BS_CLKGEN0_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_BS_CLKGEN1_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_BS_CLKGEN1_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SCR_CONF_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SCR_CONF_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_1_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_1_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_1_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_1_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_2_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_2_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_2_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_2_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_3_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_3_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_3_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_3_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_4_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_4_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_4_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_4_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_5_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_5_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_5_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +
> +  for (index = 0; index < 5; ++index) {
> +    regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_STP_REP_OFFSET +  (index * 0x4));
> +    DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_STP_%d_REP_OFFSET %x\n",
> +      __FUNCTION__, index + 1, regVal));
> +  }
> +
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SYNC_AS_GEN_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SYNC_AS_GEN_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_GENERAL_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_GENERAL_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_POL_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_POL_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  regVal = DiRead32 (IpuDiRegsPtr, IPU_IPU_DISP_GEN_OFFSET);
> +  DEBUG ((DEBUG_VERBOSE, "%a: IPU_IPU_DISP_GEN_OFFSET %x\n",
> +    __FUNCTION__, regVal));
> +  DEBUG ((DEBUG_VERBOSE, "%a: ------------------------------\n\n", __FUNCTION__));
> +}
> +#endif /* DEBUG */
> +
> +VOID
> +ConfigureSyncWave (
> +  IN  VOID          *IpuMmioBasePtr,
> +  IN  IPU_DIx_REGS  *IpuDiRegsPtr,
> +  IN  UINT32        CounterIndex,
> +  IN  UINT32        RunValue,
> +  IN  UINT32        RunResolution,
> +  IN  UINT32        OffsetValue,
> +  IN  UINT32        OffsetResolution,
> +  IN  UINT32        CounterPolarityGenEn,
> +  IN  UINT32        CounterAutoReload,
> +  IN  UINT32        CounterClearSelect,
> +  IN  UINT32        CounterDown,
> +  IN  UINT32        CounterPolarityTriggerSelect,
> +  IN  UINT32        CounterPolarityClearSelect,
> +  IN  UINT32        CounterUp,
> +  IN  UINT32        StepRepeat
> +  )
> +{
> +  IPUx_DIx_SW_GEN0_x_REG  DiSwGen0Reg;
> +  IPUx_DIx_SW_GEN1_x_REG  DiSwGen1Reg;
> +  UINT32                  StepIndex;
> +  IPUx_DIx_STP_REP_REG    StepRepeatReg;
> +
> +  ZeroMem ((VOID *)&DiSwGen0Reg, sizeof (DiSwGen0Reg));
> +  DiSwGen0Reg.dix_offset_resolution = OffsetResolution;
> +  DiSwGen0Reg.dix_offset_value = OffsetValue;
> +  DiSwGen0Reg.dix_run_resolution = RunResolution;
> +  DiSwGen0Reg.dix_run_value_m1 = RunValue;
> +  DiWrite32 (
> +    IpuDiRegsPtr,
> +    IPU_DIx_SW_GEN0_1_OFFSET + ((CounterIndex - 1) * 0x04),
> +    DiSwGen0Reg.Reg
> +  );
> +
> +  ZeroMem ((VOID *)&DiSwGen1Reg, sizeof (DiSwGen1Reg));
> +  DiSwGen1Reg.dix_cnt_up = CounterUp;
> +  DiSwGen1Reg.dix_cnt_polarity_clr_sel = CounterPolarityClearSelect;
> +  DiSwGen1Reg.dix_cnt_polarity_trigger_sel = CounterPolarityTriggerSelect;
> +  DiSwGen1Reg.dix_cnt_down = CounterDown;
> +  DiSwGen1Reg.dix_cnt_clr_sel = CounterClearSelect;
> +  DiSwGen1Reg.dix_cnt_auto_reload = CounterAutoReload;
> +  DiSwGen1Reg.dix_cnt_polarity_gen_en = CounterPolarityGenEn;
> +  DiWrite32 (
> +    IpuDiRegsPtr,
> +    IPU_DIx_SW_GEN1_1_OFFSET + ((CounterIndex - 1) * 0x04),
> +    DiSwGen1Reg.Reg
> +  );
> +
> +  StepIndex = (CounterIndex - 1) / 2;
> +  StepRepeatReg.Reg = IpuRead32 (
> +                        IpuMmioBasePtr,
> +                        IPU_DI0_STP_REP_OFFSET + (StepIndex * 0x4)
> +                      );
> +
> +  if (CounterIndex % 2) {
> +    StepRepeatReg.dix_step_repeat_2i_minus_1 = StepRepeat;
> +  } else {
> +    StepRepeatReg.dix_step_repeat_2i = StepRepeat;
> +  }
> +  IpuWrite32 (
> +    IpuMmioBasePtr,
> +    IPU_DI0_STP_REP_OFFSET + (StepIndex * 0x4),
> +    StepRepeatReg.Reg
> +  );
> +}
> +
> +EFI_STATUS
> +ConfigureDisplayInterface (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  UINT32                      DisplayIndex,
> +  IN  DISPLAY_TIMING              *DisplayTimingPtr
> +  )
> +{
> +  IPU_DIx_REGS              *pIpuDiRegs;
> +  VOID                      *pIpuMmioBase;
> +  UINT32                    BaseDiv;
> +  UINT32                    DispGenReg;
> +  UINT64                    DisplayInterfaceFrequency;
> +  IPUx_DIx_DW_GEN_REG       DixDwGenReg;
> +  IPUx_DIx_DW_SET_REG       DixDwSetReg;
> +  IPUx_DIx_GENERAL_REG      DixGeneralReg;
> +  IPUx_DIx_POL_REG          DixPolReg;
> +  IPUx_DIx_SYNC_AS_GEN_REG  DixSyncAsGenReg;
> +  UINT32                    HorizontalLength;
> +  EFI_STATUS                Status;
> +  UINT32                    VerticalLength;
> +
> +  DisplayInterfaceFrequency = DisplayTimingPtr->PixelClock;
> +  HorizontalLength = DisplayTimingPtr->HActive + DisplayTimingPtr->HBlank;
> +  VerticalLength = DisplayTimingPtr->VActive + DisplayTimingPtr->VBlank;
> +  pIpuMmioBase = DisplayInterfaceContextPtr->IpuMmioBasePtr;
> +  pIpuDiRegs = DisplayInterfaceContextPtr->IpuDiRegsPtr;
> +  Status = EFI_SUCCESS;
> +
> +  Status = ImxSetPll5ReferenceRate (DisplayTimingPtr->PixelClock);
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to setup PLL5=%r\n", __FUNCTION__, Status));
> +    goto Exit;
> +  }
> +
> +  // Setup base timer (fundamental timer). The base timer should already
> +  // setup to match the pixel clock frequency.
> +  // Shift 4 as the bottom 4 bits are fractional
> +  BaseDiv = (UINT32) ((DisplayInterfaceFrequency << 4) / DisplayTimingPtr->PixelClock);
> +  DiWrite32 (pIpuDiRegs, IPU_DIx_BS_CLKGEN0_OFFSET, BaseDiv);
> +
> +  // Up is always set to 0. Down is half of the pixel clock period where
> +  // the first bit is fraction
> +  BaseDiv >>= 4;
> +
> +  DiWrite32 (pIpuDiRegs, IPU_DIx_BS_CLKGEN1_OFFSET, BaseDiv << 16);
> +  // Calculate divisor, again this would usually be 1.
> +  BaseDiv = (UINT32) (DisplayInterfaceFrequency / DisplayTimingPtr->PixelClock);
> +
> +  // Set up wave, there 12 wave quartet, for now default to the first.
> +  // Each wave quartet has 4 set register
> +  // Set 0 is just a blank signal where up and down is set to 0
> +  ZeroMem ((VOID *)&DixDwSetReg, sizeof (DixDwSetReg));
> +  DixDwSetReg.dix_data_cnt_upx_i = 0;
> +  DixDwSetReg.dix_data_cnt_downx_i = 0;
> +  WRITE_WAVE_SET (
> +    pIpuDiRegs,
> +    DwGen0,
> +    DwSet0,
> +    DixDwSetReg.Reg
> +  );
> +
> +  // Set 3 is setup to match pixel clock
> +  ZeroMem ((VOID *)&DixDwSetReg, sizeof (DixDwSetReg));
> +  DixDwSetReg.dix_data_cnt_upx_i = 0;
> +  DixDwSetReg.dix_data_cnt_downx_i = BaseDiv * 2;
> +  WRITE_WAVE_SET (
> +    pIpuDiRegs,
> +    DwGen0,
> +    DwSet3,
> +    DixDwSetReg.Reg
> +  );
> +
> +  // All pins blank signal except pin 15
> +  ZeroMem ((VOID *)&DixDwGenReg, sizeof (DixDwGenReg));
> +  DixDwGenReg.dix_pt_0_i = DwSet0;
> +  DixDwGenReg.dix_pt_1_i = DwSet0;
> +  DixDwGenReg.dix_pt_2_i = DwSet0;
> +  DixDwGenReg.dix_pt_3_i = DwSet0;
> +  DixDwGenReg.dix_pt_4_i = DwSet3;
> +  DixDwGenReg.dix_pt_5_i = DwSet0;
> +  DixDwGenReg.dix_pt_6_i = DwSet0;
> +  DixDwGenReg.dix_cst_i = DwSet0;
> +  // Reuse the base divisor to determine extra IPU cycles.
> +  DixDwGenReg.dix_componnent_size_i = BaseDiv - 1;
> +  DixDwGenReg.dix_access_size_i = BaseDiv - 1;
> +  WRITE_WAVE_GEN (pIpuDiRegs, DwGen0, DixDwGenReg.Reg);
> +
> +  // Spec mention this as number of display rows but display only works
> +  // properly if this is setup as vertical total
> +  DiWrite32 (pIpuDiRegs, IPU_DIx_SCR_CONF_OFFSET, VerticalLength - 1);
> +
> +  // Internal HSYNC
> +  ConfigureSyncWave (
> +    pIpuMmioBase,
> +    pIpuDiRegs,
> +    DI_COUNTER_1_INTERNAL_HSYNC, // CounterIndex
> +    HorizontalLength - 1,   // Runvalue
> +    DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution
> +    0,            // OffsetValue
> +    0,            // OffsetResolution
> +    0,            // CounterPolarityGenEn
> +    1,            // CounterAutoReload
> +    DI_COUNTER_DISABLED, // CounterClearSelect
> +    0,            // CountDown
> +    0,            // CounterPolarityTriggerSelect
> +    0,            // CounterPolarityClearSelect
> +    0,            // CounterUp
> +    0             // StepRepeat
> +  );
> +
> +  // Output HSYNC
> +  ConfigureSyncWave (
> +    pIpuMmioBase,
> +    pIpuDiRegs,
> +    DI_COUNTER_2_OUTPUT_HSYNC, // CounterIndex
> +    HorizontalLength - 1,   // Runvalue
> +    DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution
> +    0,            // OffsetValue
> +    DI_COUNTER_0_DISPLAY_CLOCK + 1, // OffsetResolution - Display clock
> +    1,            // CounterPolarityGenEn
> +    1,            // CounterAutoReload
> +    DI_COUNTER_DISABLED, // CounterClearSelect
> +    DisplayTimingPtr->HSync * 2,    // CountDown
> +    1,            // CounterPolarityTriggerSelect
> +    0,            // CounterPolarityClearSelect
> +    0,            // CounterUp
> +    0             // StepRepeat
> +  );
> +
> +  // Output VSYNC
> +  ConfigureSyncWave (
> +    pIpuMmioBase,
> +    pIpuDiRegs,
> +    DI_COUNTER_3_OUTPUT_VSYNC, // CounterIndex
> +    VerticalLength - 1,   // Runvalue
> +    DI_COUNTER_1_INTERNAL_HSYNC + 1, // RunResolution - Counter 1
> +    0,            // OffsetValue
> +    0,            // OffsetResolution
> +    1,            // CounterPolarityGenEn
> +    1,            // CounterAutoReload
> +    DI_COUNTER_DISABLED, // CounterClearSelect
> +    DisplayTimingPtr->VSync * 2,    // CountDown
> +    2,            // CounterPolarityTriggerSelect
> +    0,            // CounterPolarityClearSelect
> +    0,            // CounterUp
> +    0             // StepRepeat
> +  );
> +
> +  // Active lines
> +  ConfigureSyncWave (
> +    pIpuMmioBase,
> +    pIpuDiRegs,
> +    DI_COUNTER_4_ACTIVE_LINE,  // CounterIndex
> +    0,            // Runvalue
> +    DI_COUNTER_2_OUTPUT_HSYNC + 1, // RunResolution - Counter 2
> +    DisplayTimingPtr->VSync + DisplayTimingPtr->VSyncOffset, // Offset
> +    DI_COUNTER_2_OUTPUT_HSYNC + 1,// OffsetResolution - Counter 2
> +    0,            // CounterPolarityGenEn
> +    0,            // CounterAutoReload
> +    DI_COUNTER_3_OUTPUT_VSYNC + 1, // CounterClearSelect - Counter 3
> +    0,            // CountDown
> +    0,            // CounterPolarityTriggerSelect
> +    0,            // CounterPolarityClearSelect
> +    0,            // CounterUp
> +    DisplayTimingPtr->VActive // StepRepeat repeat for total VActive
> +  );
> +
> +  // Active clock
> +  ConfigureSyncWave (
> +    pIpuMmioBase,
> +    pIpuDiRegs,
> +    DI_COUNTER_5_ACTIVE_CLOCK, // CounterIndex
> +    0,            // Runvalue
> +    DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution - Display clock
> +    DisplayTimingPtr->HSync + DisplayTimingPtr->HSyncOffset, // Offset
> +    DI_COUNTER_0_DISPLAY_CLOCK + 1, // OffsetResolution - Display clock
> +    0,            // CounterPolarityGenEn
> +    0,            // CounterAutoReload
> +    DI_COUNTER_4_ACTIVE_LINE + 1, // CounterClearSelect - Counter 4
> +    0,            // CountDown
> +    0,            // CounterPolarityTriggerSelect
> +    0,            // CounterPolarityClearSelect
> +    0,            // CounterUp
> +    DisplayTimingPtr->HActive // StepRepeat
> +  );
> +
> +  ZeroMem ((VOID *)&DixSyncAsGenReg, sizeof (DixSyncAsGenReg));
> +  // VSYNC is setup as counter 3 above, 0 index based
> +  DixSyncAsGenReg.dix_vsync_sel = 3 - 1;
> +  // Number of row DI prepares next frame data.
> +  DixSyncAsGenReg.dix_sync_start = 2;
> +  DiWrite32 (pIpuDiRegs, IPU_DIx_SYNC_AS_GEN_OFFSET, DixSyncAsGenReg.Reg);
> +
> +  // Setup general register
> +  ZeroMem ((VOID *)&DixGeneralReg, sizeof (DixGeneralReg));
> +  // Counter 1 as display line
> +  DixGeneralReg.dix_disp_y_sel = DI_COUNTER_1_INTERNAL_HSYNC - 1;
> +  // Stop at the next edge of the display clock
> +  DixGeneralReg.DIx_CLOCK_STOP_MODE = 0;
> +  // The display's clock is stopped after the next VSYNC
> +  DixGeneralReg.DIx_DISP_CLOCK_INIT = 0;
> +  // IPP_PIN_2 is coming from counter #2
> +  DixGeneralReg.dix_mask_sel = 0;
> +  // External clock - for not the video PLL
> +  DixGeneralReg.dix_vsync_ext = 1;
> +  // External clock - for not the video PLL
> +  DixGeneralReg.dix_clk_ext = 1;
> +  // 4 cycle watch dog based on BSP
> +  DixGeneralReg.DIx_WATCHDOG_MODE = 0;
> +  // default sync to counter 0
> +  DixGeneralReg.dix_sync_count_sel = DI_COUNTER_1_INTERNAL_HSYNC - 1;
> +  // In the event of error drive the last component
> +  DixGeneralReg.dix_err_treatment = 0;
> +  // An internal VSYNC signal asserted 2 lines before the DI's VSYNC
> +  DixGeneralReg.dix_erm_vsync_sel = 0;
> +
> +  switch (DisplayInterfaceContextPtr->displayInterface) {
> +  case HdmiDisplay:
> +    // Zero for HDMI display
> +    DixGeneralReg.dix_polarity_disp_clk = 0;
> +    DixGeneralReg.dix_polarity_cs1 = 0;
> +    DixGeneralReg.dix_polarity_cs0 = 0;
> +    DixGeneralReg.dix_polarity_i_1 = 0;
> +    break;
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +    DEBUG ((DEBUG_ERROR, "%a: Unsupported display interface %d\n",
> +      __FUNCTION__, DisplayInterfaceContextPtr->displayInterface));
> +    break;
> +  }
> +  if (EFI_ERROR (Status)) {
> +    goto Exit;
> +  }
> +  DiWrite32 (pIpuDiRegs, IPU_DIx_GENERAL_OFFSET, DixGeneralReg.Reg);
> +
> +  ZeroMem ((VOID *)&DixPolReg, sizeof (DixPolReg));
> +  // CS0
> +  DixPolReg.DIx_CS0_DATA_POLARITY = 1;
> +  DixPolReg.dix_cs0_polarity = 0x7F;
> +  // CS1
> +  DixPolReg.DIx_CS1_DATA_POLARITY = 1;
> +  DixPolReg.dix_cs1_polarity = 0x7F;
> +  // DRDY
> +  DixPolReg.DIx_DRDY_DATA_POLARITY = 0;
> +  DixPolReg.dix_drdy_polarity = 0x7F;
> +  // Wait
> +  DixPolReg.DIx_WAIT_POLARITY = 0;
> +  // CS0 byte enable polarity
> +  DixPolReg.DIx_CS0_BYTE_EN_POLARITY = 0;
> +  // CS1 byte enable polarity
> +  DixPolReg.DIx_CS1_BYTE_EN_POLARITY = 0;
> +  DiWrite32 (pIpuDiRegs, IPU_DIx_POL_OFFSET, DixPolReg.Reg);
> +
> +  DispGenReg = IpuRead32 (pIpuMmioBase, IPU_IPU_DISP_GEN_OFFSET);
> +  DispGenReg &= ~(0x0F << 18);
> +  DispGenReg |= (2 << 18);
> +  IpuWrite32 (pIpuMmioBase, IPU_IPU_DISP_GEN_OFFSET, DispGenReg);
> +
> +#ifdef DEBUG
> +  DumpBasicDisplayInterfaceReg (pIpuMmioBase, pIpuDiRegs);
> +#endif /* DEBUG */
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
> new file mode 100644
> index 000000000000..786ef1fff5f0
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
> @@ -0,0 +1,195 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _DISPLAY_INTERFACE_H_
> +#define _DISPLAY_INTERFACE_H_

IMX_ prefix please.

> +
> +#define READ_WAVE_GEN(IPU_BASE, GEN_INDEX) \
> +    DiRead32(IPU_BASE, IPU_DIx_DW_GEN_OFFSET + (GEN_INDEX * 0x4))
> +
> +#define WRITE_WAVE_GEN(IPU_BASE, GEN_INDEX, VALUE) \
> +    DiWrite32(IPU_BASE, IPU_DIx_DW_GEN_OFFSET + (GEN_INDEX * 0x4), VALUE)
> +
> +#define READ_WAVE_SET(IPU_BASE, GEN_INDEX, SET_NUMBER) \
> +    DiRead32(IPU_BASE, IPU_DIx_DW_SET0_OFFSET + (SET_NUMBER * 0x30) + (GEN_INDEX * 0x4))
> +
> +#define WRITE_WAVE_SET(IPU_BASE, GEN_INDEX, SET_NUMBER, VALUE) \
> +    DiWrite32(IPU_BASE, IPU_DIx_DW_SET0_OFFSET + (SET_NUMBER * 0x30) + (GEN_INDEX * 0x4), VALUE)
> +
> +#define DI_COUNTER_DISABLED 0
> +#define DI_COUNTER_0_DISPLAY_CLOCK 0
> +#define DI_COUNTER_1_INTERNAL_HSYNC 1
> +#define DI_COUNTER_2_OUTPUT_HSYNC 2
> +#define DI_COUNTER_3_OUTPUT_VSYNC 3
> +#define DI_COUNTER_4_ACTIVE_LINE 4
> +#define DI_COUNTER_5_ACTIVE_CLOCK 5
> +
> +typedef enum {
> +  DwGen0,
> +  DwGen1,
> +  DwGen2,
> +  DwGen3,
> +  DwGen4,
> +  DwGen5,
> +  DwGen6,
> +  DwGen7,
> +  DwGen8,
> +  DwGen9,
> +  DwGen10,
> +  DwGen11,
> +  DwGenMax
> +} DW_GEN;
> +
> +typedef enum {
> +  DwSet0,
> +  DwSet1,
> +  DwSet2,
> +  DwSet3,
> +  DwSetMax
> +} DW_SET;
> +
> +#pragma pack(push, 1)
> +
> +// IPUx_DIx_GENERAL
> +typedef union {
> +  struct {
> +    UINT32 dix_polarity_i_1 : 8;
> +    UINT32 dix_polarity_cs0 : 1;
> +    UINT32 dix_polarity_cs1 : 1;
> +    UINT32 dix_erm_vsync_sel : 1;
> +    UINT32 dix_err_treatment : 1;
> +    UINT32 dix_sync_count_sel : 4;
> +    UINT32 Reserved : 1;
> +    UINT32 dix_polarity_disp_clk : 1;
> +    UINT32 DIx_WATCHDOG_MODE : 2;
> +    UINT32 dix_clk_ext : 1;
> +    UINT32 dix_vsync_ext : 1;
> +    UINT32 dix_mask_sel : 1;
> +    UINT32 DIx_DISP_CLOCK_INIT : 1;
> +    UINT32 DIx_CLOCK_STOP_MODE : 4;
> +    UINT32 dix_disp_y_sel : 3;
> +    UINT32 dix_pin8_pin15_sel : 1;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_GENERAL_REG;
> +
> +// IPUx_DIx_SYNC_AS_GEN
> +typedef union {
> +  struct {
> +    UINT32 dix_sync_start : 12;
> +    UINT32 Reserved1 : 1;
> +    UINT32 dix_vsync_sel : 3;
> +    UINT32 Reserved2 : 12;
> +    UINT32 di0_sync_start_en : 1;
> +    UINT32 Reserved3 : 3;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_SYNC_AS_GEN_REG;
> +
> +// IPUx_DIx_DW_SET
> +typedef union {
> +  struct {
> +    UINT32 dix_data_cnt_upx_i : 9;
> +    UINT32 Reserved1 : 7;
> +    UINT32 dix_data_cnt_downx_i : 9;
> +    UINT32 Reserved2 : 7;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_DW_SET_REG;
> +
> +// IPUx_DIx_DW_GEN
> +typedef union {
> +  struct {
> +    UINT32 dix_pt_0_i : 2;  // Pin 11
> +    UINT32 dix_pt_1_i : 2;  // Pin 12
> +    UINT32 dix_pt_2_i : 2;  // Pin 13
> +    UINT32 dix_pt_3_i : 2;  // Pin 14
> +    UINT32 dix_pt_4_i : 2;  // Pin 15
> +    UINT32 dix_pt_5_i : 2;  // Pin 16
> +    UINT32 dix_pt_6_i : 2;  // Pin 17
> +    UINT32 dix_cst_i : 2;   // Chip Select
> +    UINT32 dix_componnent_size_i : 8;
> +    UINT32 dix_access_size_i : 8;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_DW_GEN_REG;
> +
> +
> +// IPUx_DIx_SW_GEN0_x_REG
> +typedef union {
> +  struct {
> +    UINT32 dix_offset_resolution : 3;
> +    UINT32 dix_offset_value : 12;
> +    UINT32 Reserved1: 1;
> +    UINT32 dix_run_resolution : 3;
> +    UINT32 dix_run_value_m1 : 12;
> +    UINT32 Reserved2 : 1;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_SW_GEN0_x_REG;
> +
> +// IPUx_DIx_SW_GEN1_x_REG
> +typedef union {
> +  struct {
> +    UINT32 dix_cnt_up : 9;
> +    UINT32 dix_cnt_polarity_clr_sel : 3;
> +    UINT32 dix_cnt_polarity_trigger_sel : 3;
> +    UINT32 Reserved1 : 1;
> +    UINT32 dix_cnt_down: 9;
> +    UINT32 dix_cnt_clr_sel : 3;
> +    UINT32 dix_cnt_auto_reload : 1;
> +    UINT32 dix_cnt_polarity_gen_en : 2;
> +    UINT32 Reserved2 : 1;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_SW_GEN1_x_REG;
> +
> +// IPUx_DIx_STP_REP
> +typedef union {
> +  struct {
> +    UINT32 dix_step_repeat_2i_minus_1 : 12;
> +    UINT32 Reserved1 : 4;
> +    UINT32 dix_step_repeat_2i : 12;
> +    UINT32 Reserved2 : 4;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_STP_REP_REG;
> +
> +// IPUx_DIx_POL
> +typedef union {
> +  struct {
> +    UINT32 dix_drdy_polarity : 7;
> +    UINT32 DIx_DRDY_DATA_POLARITY : 1;
> +    UINT32 dix_cs0_polarity : 7;
> +    UINT32 DIx_CS0_DATA_POLARITY : 1;
> +    UINT32 dix_cs1_polarity : 7;
> +    UINT32 DIx_CS1_DATA_POLARITY : 1;
> +    UINT32 DIx_CS0_BYTE_EN_POLARITY : 1;
> +    UINT32 DIx_CS1_BYTE_EN_POLARITY : 1;
> +    UINT32 DIx_WAIT_POLARITY : 1;
> +    UINT32 Reserved : 5;
> +  };
> +  UINT32 Reg;
> +} IPUx_DIx_POL_REG;
> +
> +#pragma pack(pop)
> +
> +EFI_STATUS
> +ConfigureDisplayInterface (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *DisplayInterfaceContextPtr,
> +  IN  UINT32                      DisplayIndex,
> +  IN  DISPLAY_TIMING              *DisplayTimingPtr
> +  );
> +
> +#endif  /* _DISPLAY_INTERFACE_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
> new file mode 100644
> index 000000000000..cc6557a58138
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
> @@ -0,0 +1,96 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "Edid.h"
> +#include "Ddc.h"
> +
> +EFI_STATUS
> +ReadEdid (
> +  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
> +  IN  UINT8               *EdidDataPtr,
> +  OUT UINT32              *EdidDataSizePtr
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = Imx6DdcRead (
> +             DisplayContextPtr,
> +             DisplayInterface,
> +             EDID_I2C_ADDRESS,
> +             0,
> +             EDID_MIN_SIZE,
> +             EdidDataPtr
> +           );
> +  if (Status != EFI_SUCCESS) {
> +    goto Exit;
> +  }
> +
> +  Status = ValidateEdidData (
> +             EdidDataPtr
> +           );
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_WARN, "%a: Invalid EDID data\n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: EDID initialized\n", __FUNCTION__));
> +
> +  *EdidDataSizePtr = EDID_MIN_SIZE;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +GetEdidPreferredTiming (
> +  IN  UINT8           *EdidDataPtr,
> +  IN  UINT32          EdidDataSizePtr,
> +  OUT DISPLAY_TIMING  *PreferredTiming
> +  )
> +{
> +  DETAILED_TIMING_DESCRIPTOR  *pEdidPreferredTiming;
> +  EFI_STATUS                  Status;
> +
> +  if (EdidDataSizePtr < EDID_MIN_SIZE) {
> +    DEBUG ((DEBUG_WARN, "%a: Insufficient EDID data\n", __FUNCTION__));
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +  pEdidPreferredTiming = (DETAILED_TIMING_DESCRIPTOR *)&EdidDataPtr[EDID_DTD_1_OFFSET];
> +  Status = ConvertDTDToDisplayTiming (pEdidPreferredTiming, PreferredTiming);
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "%a: Conversion to display timing failed\n",
> +      __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +Exit:
> +
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
> new file mode 100644
> index 000000000000..df714f284deb
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
> @@ -0,0 +1,33 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _EDID_H_
> +#define _EDID_H_

IMX_ prefix please.

> +
> +EFI_STATUS
> +ReadEdid (
> +  IN  DISPLAY_CONTEXT     *DisplayContextPtr,
> +  IN  DISPLAY_INTERFACE_TYPE   DisplayInterface,
> +  IN  UINT8               *EdidDataPtr,
> +  OUT UINT32              *EdidDataSizePtr
> +  );
> +
> +EFI_STATUS
> +GetEdidPreferredTiming (
> +  IN  UINT8           *EdidDataPtr,
> +  IN  UINT32          EdidDataSizePtr,
> +  OUT DISPLAY_TIMING  *PreferredTiming
> +  );
> +
> +#endif  /* _EDID_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
> new file mode 100644
> index 000000000000..2e990a6b14fb
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
> @@ -0,0 +1,475 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/EmbeddedExternalDevice.h>
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/Cpu.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/EdidDiscovered.h>
> +#include <Protocol/EdidActive.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "GopDxe.h"
> +#include "Hdmi.h"
> +#include "Lvds.h"
> +
> +#define PIXEL_BYTES 4
> +
> +typedef struct {
> +  VENDOR_DEVICE_PATH Mmc;
> +  EFI_DEVICE_PATH End;
> +} VID_DEVICE_PATH;
> +
> +DISPLAY_TIMING CONST FullHDTiming = {
> +  148500000,  // Full 1080p HD PixelClock
> +  1920,       // HActive
> +  280,        // HBlank
> +  1080,       // VActive
> +  45,         // VBlank
> +  44,         // HSync
> +  5,          // VSync
> +  88,         // HSyncOffset;
> +  4,          // VSyncOffset;
> +  1920,       // HImageSize
> +  1080,       // VImageSize
> +  0,          // HBorder
> +  0,          // VBorder
> +  30,         // EdidFlags
> +  0,          // Flags
> +  1,          // PixelRepetition
> +  32,         // Bpp
> +  PIXEL_FORMAT_BGRA32,       // PixelFormat
> +};
> +
> +EFI_STATUS
> +EFIAPI
> +VidGopQueryMode (
> +  IN EFI_GRAPHICS_OUTPUT_PROTOCOL           *This,
> +  IN UINT32                                 ModeNumber,
> +  OUT UINTN                                 *SizeOfInfo,
> +  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
> +  );
> +
> +EFI_STATUS
> +VidGopSetMode (
> +  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
> +  IN UINT32                         ModeNumber
> +  );
> +
> +EFI_STATUS
> +VidGopBlt (
> +  IN EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,
> +  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer,
> +  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
> +  IN UINTN                              SourceX,
> +  IN UINTN                              SourceY,
> +  IN UINTN                              DestinationX,
> +  IN UINTN                              DestinationY,
> +  IN UINTN                              Width,
> +  IN UINTN                              Height,
> +  IN UINTN                              Delta
> +  );
> +
> +STATIC VID_DEVICE_PATH VidDevicePath = {

m-prefix for global variables, please. Throughout. (Where they're not
for edk2-global visibility and should have g.)

> +  {
> +    {
> +      HARDWARE_DEVICE_PATH,
> +      HW_VENDOR_DP,
> +      {
> +        (UINT8)sizeof (VENDOR_DEVICE_PATH),
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8),
> +      }
> +    },
> +    {
> +      0xa6b94ebe,
> +      0x5ba3,
> +      0x44b0,
> +      { 0x95, 0x92, 0xdc, 0x04, 0x5e, 0xb8, 0xf8, 0x9e }
> +    }
> +  },
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      sizeof (EFI_DEVICE_PATH_PROTOCOL),
> +      0
> +    }
> +  }
> +};
> +
> +STATIC EFI_GRAPHICS_OUTPUT_MODE_INFORMATION VidGopModeInfo;
> +STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE VidGopMode;
> +
> +STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL VidGop = {
> +  VidGopQueryMode, // QueryMode
> +  VidGopSetMode,   // SetMode
> +  VidGopBlt,       // Blt
> +  &VidGopMode    // Mode
> +};
> +
> +EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered = {
> +  0,
> +  NULL
> +};
> +
> +EFI_EDID_ACTIVE_PROTOCOL EdidActive = {
> +  0,
> +  NULL
> +};
> +
> +DISPLAY_CONTEXT *DisplayContextPtr;
> +
> +DISPLAY_INTERFACE_TYPE DisplayDevice;
> +
> +EFI_STATUS
> +GopDxeInitialize (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  )
> +{
> +  DISPLAY_INTERFACE_TYPE  DisplayInterfaceOrder[DisplayTypeMax];
> +  UINT32                  i;
> +  UINT32                  RequestedDisplayMemorySize;
> +  UINT32                  ReservedDisplayMemorySize;
> +  EFI_STATUS              Status;
> +
> +  DEBUG ((DEBUG_INFO, "%a: Enter \n", __FUNCTION__));
> +
> +  for (i = 0; i < DisplayTypeMax; i++) {
> +    DisplayInterfaceOrder[i] = NoDisplayType;
> +  }
> +  ReservedDisplayMemorySize = FixedPcdGet32 (PcdFrameBufferSize);
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    DisplayDevice = Lvds0Display;
> +  } else {
> +    DisplayDevice = HdmiDisplay;
> +  }
> +
> +  Status = InitDisplay (&DisplayContextPtr);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to init display, Status=%r\n", __FUNCTION__,
> +      Status));
> +    goto Exit;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: - Allocate frame buffer\n", __FUNCTION__));
> +  // To allocate frame buffer dynamically, there isn`t a built in graphic memory
> +  // manager for UEFI, so we are allocating frame buffer manually. Currently only
> +  // support single display, so allocate single(1) frame buffer
> +  // Allocate frame buffer
> +  DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width =
> +    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.HActive;
> +  DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height =
> +    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.VActive;
> +  DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp =
> +    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.Bpp;
> +  DisplayContextPtr->DisplayConfig.DisplaySurface[0].PixelFormat =
> +    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.PixelFormat;
> +
> +  // iMX6 UEFI reserves display memory for fullHD buffer size.
> +  // PcdFrameBufferSize=800000h or 8388608 bytes - 1920x1080x4 bytes
> +  // to prevent larger displays overrun our reserved memory size,
> +  // cap display resolution to fullHD
> +  // NOTE: Displays which do not have support for 1920x1080 mode may
> +  // have poor or missing picture
> +  RequestedDisplayMemorySize =
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width *
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height *
> +    (DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp / 8);
> +
> +  DEBUG ((DEBUG_INFO, "%a: Display Memory: Needed=%d, Available=%d\n",
> +    __FUNCTION__, RequestedDisplayMemorySize, ReservedDisplayMemorySize));
> +
> +  if (RequestedDisplayMemorySize > ReservedDisplayMemorySize) {
> +    DEBUG ((DEBUG_INFO,
> +      "%a: WARNING. Need more video memory than reserved by %d bytes\n",
> +      __FUNCTION__, RequestedDisplayMemorySize - ReservedDisplayMemorySize));
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: - display resolution too big. Cap to HD 1080p\n",
> +      __FUNCTION__));
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width = FullHDTiming.HActive;
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height =
> +      FullHDTiming.VActive;
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp = FullHDTiming.Bpp;
> +    CopyMem (
> +      &DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming,
> +      &FullHDTiming,
> +      sizeof (DISPLAY_TIMING)
> +    );
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: - allocating frame buffer... \n",
> +    __FUNCTION__));
> +  Status = AllocateFrameBuffer (&DisplayContextPtr->DisplayConfig.DisplaySurface[0]);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate fb, Status=%r\n",
> +      __FUNCTION__, Status));
> +    goto Exit;
> +  };
> +
> +  DEBUG ((DEBUG_INFO, "%a: - Initialize the frame buffer to black\n",
> +    __FUNCTION__));
> +  // Initialize the frame buffer to black
> +  SetMem32 (
> +    (VOID *)DisplayContextPtr->DisplayConfig.DisplaySurface[0].PhyAddr,
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width *
> +    DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height * 4,
> +    0xFF000000
> +  );
> +
> +  DEBUG ((DEBUG_INFO, "%a: - set display configuration to single HDMI\n",
> +    __FUNCTION__));
> +  // Set the display configuration to single HDMI/LVDS mode
> +  DisplayInterfaceOrder[0] = DisplayDevice;
> +  DisplayContextPtr->DisplayConfig.DisplayTiming[0] =
> +    DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming;
> +
> +  Status = ApplyDisplayConfig (
> +              DisplayContextPtr,
> +              SINGLE_MODE,
> +              DisplayInterfaceOrder
> +            );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to set display. Exit Status=%r\n",
> +      __FUNCTION__, Status));
> +    goto Exit;
> +  }
> +
> +  VidGopModeInfo.Version = 0;
> +  VidGopModeInfo.HorizontalResolution =
> +    DisplayContextPtr->DisplayConfig.DisplayTiming[0].HActive;
> +  VidGopModeInfo.VerticalResolution =
> +    DisplayContextPtr->DisplayConfig.DisplayTiming[0].VActive;
> +  VidGopModeInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
> +  ZeroMem (
> +    &VidGopModeInfo.PixelInformation,
> +    sizeof (VidGopModeInfo.PixelInformation)
> +  );
> +
> +  VidGopModeInfo.PixelsPerScanLine = VidGopModeInfo.HorizontalResolution;
> +  VidGopMode.MaxMode = 1;
> +  VidGopMode.Mode = 0;
> +  VidGopMode.Info = &VidGopModeInfo;
> +  VidGopMode.SizeOfInfo = sizeof (VidGopModeInfo);
> +  VidGopMode.FrameBufferBase =
> +    (EFI_PHYSICAL_ADDRESS) DisplayContextPtr->DisplayConfig.DisplaySurface[0].PhyAddr;
> +  VidGopMode.FrameBufferSize =
> +    VidGopModeInfo.HorizontalResolution *
> +    VidGopModeInfo.VerticalResolution *
> +    (DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp / 8);
> +  DisplayContextPtr->DisplayConfig.OsHandle[0] = (UINT32)&ImageHandle;
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &ImageHandle,
> +                  &gEfiGraphicsOutputProtocolGuid,
> +                  &VidGop,
> +                  &gEfiDevicePathProtocolGuid,
> +                  &VidDevicePath,
> +                  NULL
> +                );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to install protocol, Status=%x\n",
> +      __FUNCTION__, Status));
> +    goto Exit;
> +  }
> +
> +Exit:
> +  DEBUG ((DEBUG_INFO, "%a: Exit = %Xh\n",
> +    __FUNCTION__, Status));
> +  return Status;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +VidGopQueryMode (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> +  IN  UINT32 ModeNumber,
> +  OUT UINTN *SizeOfInfo,
> +  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *OutputMode;
> +  EFI_STATUS                            Status;
> +
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    DisplayDevice = Lvds0Display;
> +  } else {
> +    DisplayDevice = HdmiDisplay;
> +  }
> +
> +  EdidDiscovered.SizeOfEdid = DisplayContextPtr->DiContext[DisplayDevice].EdidDataSize;
> +  EdidDiscovered.Edid = DisplayContextPtr->DiContext[DisplayDevice].EdidData;
> +  EdidActive.SizeOfEdid = DisplayContextPtr->DiContext[DisplayDevice].EdidDataSize;
> +  EdidActive.Edid = DisplayContextPtr->DiContext[DisplayDevice].EdidData;
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  (EFI_HANDLE)DisplayContextPtr->DisplayConfig.OsHandle[0],
> +                  &gEfiEdidDiscoveredProtocolGuid,
> +                  &EdidDiscovered,
> +                  &gEfiEdidActiveProtocolGuid,
> +                  &EdidActive,
> +                  NULL
> +                );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to install EDID protocols Status=%r\n",
> +      __FUNCTION__, Status));
> +  }
> +
> +  if (ModeNumber != 0) {
> +    DEBUG ((DEBUG_ERROR, "%a: Saw request to query mode %d\n",
> +      __FUNCTION__, ModeNumber));
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +  OutputMode = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)
> +    AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
> +  if (OutputMode == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Exit;
> +  }
> +
> +  OutputMode->Version = 0;
> +  OutputMode->HorizontalResolution = VidGopModeInfo.HorizontalResolution;
> +  OutputMode->VerticalResolution = VidGopModeInfo.VerticalResolution;
> +  OutputMode->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
> +  OutputMode->PixelsPerScanLine = VidGopModeInfo.HorizontalResolution;
> +  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
> +  *Info = OutputMode;
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +VidGopSetMode (
> +  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
> +  IN UINT32                         ModeNumber
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if (ModeNumber != 0) {
> +    DEBUG ((DEBUG_ERROR, "%a: Saw request to set mode to %d\n",
> +      __FUNCTION__, ModeNumber));
> +    Status = EFI_UNSUPPORTED;
> +    goto Exit;
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +VidGopBlt (
> +  IN EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,
> +  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer, OPTIONAL
> +  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
> +  IN UINTN                              SourceX,
> +  IN UINTN                              SourceY,
> +  IN UINTN                              DestinationX,
> +  IN UINTN                              DestinationY,
> +  IN UINTN                              Width,
> +  IN UINTN                              Height,
> +  IN UINTN                              Delta OPTIONAL
> +  )
> +{
> +  UINT32  *FrameBuffer;
> +  UINT32  BufferOffset;
> +  UINT32  BufferWidth;
> +  UINT32  FrameOffset;
> +  UINT32  FrameWidth;
> +  UINT32  i;
> +
> +  FrameBuffer = (UINT32 *)((UINTN)VidGopMode.FrameBufferBase);
> +  FrameWidth = VidGopModeInfo.HorizontalResolution;
> +  if (Delta == 0) {
> +    BufferWidth = Width;
> +  } else {
> +    BufferWidth = Delta / PIXEL_BYTES;
> +  }
> +
> +  if (BltOperation == EfiBltVideoFill) {
> +    FrameOffset = FrameWidth * DestinationY + DestinationX;
> +    for (i = DestinationY; i < DestinationY + Height; i++) {
> +      SetMem32 (
> +        FrameBuffer + FrameOffset,
> +        Width * PIXEL_BYTES,
> +        *(UINT32 *)BltBuffer
> +      );
> +      FrameOffset += FrameWidth;
> +    }
> +  } else if (BltOperation == EfiBltVideoToBltBuffer) {
> +    FrameOffset = FrameWidth * SourceY + SourceX;
> +    BufferOffset = BufferWidth * DestinationY + DestinationX;
> +    for (i = SourceY; i < SourceY + Height; i++) {
> +      CopyMem (
> +        BltBuffer + BufferOffset,
> +        FrameBuffer + FrameOffset,
> +        Width * PIXEL_BYTES
> +      );
> +      FrameOffset += FrameWidth;
> +      BufferOffset += BufferWidth;
> +    }
> +  } else if (BltOperation == EfiBltBufferToVideo) {
> +    FrameOffset = FrameWidth * DestinationY + DestinationX;
> +    BufferOffset = BufferWidth * SourceY + SourceX;
> +    for (i = SourceY; i < SourceY + Height; i++) {
> +      CopyMem (
> +        FrameBuffer + FrameOffset,
> +        BltBuffer + BufferOffset,
> +        Width * PIXEL_BYTES
> +      );
> +      FrameOffset += FrameWidth;
> +      BufferOffset += BufferWidth;
> +    }
> +  } else if (BltOperation == EfiBltVideoToVideo) {
> +    FrameOffset = FrameWidth * DestinationY + DestinationX;
> +    BufferOffset = FrameWidth * SourceY + SourceX;
> +    for (i = SourceY; i < SourceY + Height; i++) {
> +      CopyMem (
> +        FrameBuffer + FrameOffset,
> +        FrameBuffer + BufferOffset,
> +        Width * PIXEL_BYTES
> +      );
> +      FrameOffset += FrameWidth;
> +      BufferOffset += FrameWidth;
> +    }
> +  } else {
> +    DEBUG ((DEBUG_ERROR, "%a: Not implemented %d\n",
> +      __FUNCTION__, BltOperation));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
> new file mode 100644
> index 000000000000..b8622283238f
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
> @@ -0,0 +1,20 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _GOP_DXE_H_
> +#define _GOP_DXE_H_
> +
> +#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
> +
> +#endif  /* _GOP_DXE_H_ */

Use ARRAY_SIZE from Base.h, then this file can be deleted.

> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
> new file mode 100644
> index 000000000000..9dbe00ae1ab1
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
> @@ -0,0 +1,70 @@
> +#/** @file
> +#
> +#  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = GopDxe
> +  FILE_GUID                      = E68088EF-D1A4-4336-C1DB-4D3A204730A6
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = GopDxeInitialize
> +
> +[Sources.common]
> +  CPMem.c
> +  Ddc.c
> +  Display.c
> +  DisplayController.c
> +  DisplayInterface.c
> +  Edid.c
> +  GopDxe.c
> +  Hdmi.c
> +  IoMux.c
> +  Lvds.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +
> +[LibraryClasses]
> +  ArmLib
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  iMX6ClkPwrLib
> +  iMXDisplayLib
> +  IoLib
> +  TimerLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +
> +[Protocols]
> +  gEfiDevicePathProtocolGuid                    # Produced
> +  gEfiDevicePathToTextProtocolGuid
> +  gEfiEdidActiveProtocolGuid                    # Produced
> +  gEfiEdidDiscoveredProtocolGuid                # Produced
> +  gEfiGraphicsOutputProtocolGuid                # Produced
> +
> +[Pcd]
> +  giMX6TokenSpaceGuid.PcdFrameBufferBase
> +  giMX6TokenSpaceGuid.PcdFrameBufferSize
> +  giMX6TokenSpaceGuid.PcdLvdsEnable
> +
> +[Depex]
> +  gEfiCpuArchProtocolGuid AND gEfiTimerArchProtocolGuid
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
> new file mode 100644
> index 000000000000..fa8fb3ed4aea
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
> @@ -0,0 +1,761 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "GopDxe.h"
> +#include "Hdmi.h"
> +#include "Edid.h"
> +
> +PLL_MPLL_CONFIG PllMpllGenericConfigSetting[] = {

Can this be static?
m-prefix, please.

> +  {  13500000, 2,  8, {{3, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  13500000, 2, 10, {{1, 4, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  13500000, 2, 12, {{2, 4, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, },
> +  {  13500000, 2, 16, {{3, 1, 3, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
> +  {  13500000, 4,  8, {{3, 1, 3, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
> +  {  13500000, 4, 10, {{1, 5, 3, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
> +  {  13500000, 4, 12, {{2, 5, 3, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 0, 0,}}, },
> +  {  13500000, 4, 16, {{3, 2, 3, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, },
> +  {  18000000, 3,  8, {{2, 1, 3, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
> +  {  18000000, 3, 16, {{2, 2, 3, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, },
> +  {  24175000, 1,  8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  24175000, 1, 10, {{1, 0, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  24175000, 1, 12, {{2, 0, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, },
> +  {  24175000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  27000000, 1,  8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  27000000, 1, 10, {{1, 0, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  27000000, 1, 12, {{2, 0, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, },
> +  {  27000000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 5, 4, 0,}}, {{1, 0, 0,}}, },
> +  {  27000000, 2,  8, {{3, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  27000000, 2, 10, {{1, 1, 3, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, },
> +  {  27000000, 2, 12, {{2, 1, 3, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 0, 0,}}, },
> +  {  27000000, 2, 16, {{3, 1, 2, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
> +  {  27000000, 4,  8, {{3, 1, 2, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
> +  {  27000000, 4, 10, {{1, 2, 3, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, },
> +  {  27000000, 4, 12, {{2, 2, 3, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 0, 0,}}, },
> +  {  27000000, 4, 16, {{3, 2, 2, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 1, 0,}}, },
> +  {  36000000, 1,  8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, },
> +  {  36000000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  50350000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  50350000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  50350000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  50350000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  50350000, 2,  8, {{3, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  50350000, 2, 10, {{1, 1, 2, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
> +  {  50350000, 2, 12, {{2, 1, 2, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 1, 0,}}, },
> +  {  50350000, 2, 16, {{3, 1, 1, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 2, 0,}}, },
> +  {  54000000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  54000000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  54000000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  54000000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  54000000, 2,  8, {{3, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  54000000, 2, 10, {{1, 1, 2, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, },
> +  {  54000000, 2, 12, {{2, 1, 2, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 1, 0,}}, },
> +  {  54000000, 2, 16, {{3, 1, 1, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 2, 0,}}, },
> +  {  58400000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, },
> +  {  58400000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  58400000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  58400000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  72000000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  72000000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  72000000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  72000000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  {  74250000, 1,  8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, },
> +  {  74250000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{2, 2, 0,}}, },
> +  {  74250000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  {  74250000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  { 108000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  { 108000000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  { 108000000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  { 108000000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
> +  { 118800000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  { 118800000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, },
> +  { 118800000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  { 118800000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
> +  { 144000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  { 144000000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, },
> +  { 144000000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
> +  { 144000000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{3, 3, 0,}}, },
> +  { 148500000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  { 148500000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, },
> +  { 148500000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
> +  { 148500000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{3, 3, 0,}}, },
> +  { 216000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +  { 216000000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, },
> +  { 216000000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, },
> +  // Fallback
> +  {  65000000, 1,  8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, },
> +};
> +
> +BOOLEAN
> +HdmiPhyPollI2cDone (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  UINT32                      Timeout
> +  )
> +{
> +  HDMI_IH_I2CMPHY_STAT0_REG   I2cmphyStat0Reg;
> +  BOOLEAN                     WaitResult;
> +
> +  WaitResult = FALSE;
> +  for (; Timeout > 0; Timeout--) {
> +    I2cmphyStat0Reg.Reg = MmioRead8 (
> +                            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +

UINTN for addresses, please. Throughout.

> +                            HDMI_IH_I2CMPHY_STAT0
> +                          );
> +    if (I2cmphyStat0Reg.i2cmphydone) {
> +      WaitResult = TRUE;
> +      break;
> +    }
> +    gBS->Stall (1);
> +  }
> +
> +#if DEBUG
> +  if ((Timeout == 0) || (I2cmphyStat0Reg.i2cmphyerror == 1)) {
> +    DEBUG ((DEBUG_ERROR, "%a: HDMI I2C failed value %x time out %d\n",
> +      __FUNCTION__, I2cmphyStat0Reg.Reg, Timeout));
> +  }
> +#endif
> +
> +  return WaitResult;
> +}
> +
> +BOOLEAN
> +HdmiPhyI2cRead (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  UINT8                       Addr,
> +  OUT UINT16                      *DataPtr
> +  )
> +{
> +  UINT16                            Data0;
> +  UINT16                            Data1;
> +  HDMI_PHY_I2CM_OPERATION_ADDR_REG  I2cmOperationReg;
> +  HDMI_IH_I2CMPHY_STAT0_REG         I2cmphyStat0Reg;
> +  BOOLEAN                           ReadStatus;
> +
> +  I2cmphyStat0Reg.i2cmphyerror = 1;
> +  I2cmphyStat0Reg.i2cmphydone = 1;
> +  I2cmphyStat0Reg.reserved = 0;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CMPHY_STAT0,
> +    I2cmphyStat0Reg.Reg
> +  );
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_ADDRESS_ADDR,
> +    Addr
> +  );
> +
> +  I2cmOperationReg.Reg = MmioRead8 (
> +                           (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                           HDMI_PHY_I2CM_OPERATION_ADDR
> +                         );
> +  I2cmOperationReg.read = 1;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_OPERATION_ADDR,
> +    I2cmOperationReg.Reg
> +  );
> +
> +  ReadStatus = HdmiPhyPollI2cDone (HdmiDisplayContextPtr, 1000);
> +  if (!ReadStatus) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to read I2c HDMI Phy\n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +  Data0 = MmioRead8 (
> +            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +            HDMI_PHY_I2CM_DATAI_0_ADDR
> +          );
> +  Data1 = MmioRead8 (
> +            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +            HDMI_PHY_I2CM_DATAI_1_ADDR
> +          );
> +  *DataPtr = Data0 | (Data1 <<  8);
> +
> +Exit:
> +  return ReadStatus;
> +}
> +
> +BOOLEAN
> +HdmiPhyI2cWrite (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  UINT8                       Addr,
> +  IN  UINT16                      Data
> +  )
> +{
> +  UINT8                             Data0;
> +  UINT8                             Data1;
> +  HDMI_PHY_I2CM_OPERATION_ADDR_REG  I2cmOperationReg;
> +  HDMI_IH_I2CMPHY_STAT0_REG         I2cmphyStat0Reg;
> +
> +  Data0 = (Data & 0x00FF);
> +  Data1 = (Data >>  8);
> +  I2cmphyStat0Reg.i2cmphyerror = 1;
> +  I2cmphyStat0Reg.i2cmphydone = 1;
> +  I2cmphyStat0Reg.reserved = 1;
> +  I2cmOperationReg.read = 0;
> +  I2cmOperationReg.reserved0 = 0;
> +  I2cmOperationReg.write = 0;
> +  I2cmOperationReg.reserved1 = 0;
> +
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CMPHY_STAT0,
> +    I2cmphyStat0Reg.Reg
> +  );
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_ADDRESS_ADDR,
> +    Addr
> +  );
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_DATAO_0_ADDR,
> +    Data0
> +  );
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_DATAO_1_ADDR,
> +    Data1
> +  );
> +
> +  I2cmOperationReg.read = 0;
> +  I2cmOperationReg.write = 1;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_OPERATION_ADDR,
> +    I2cmOperationReg.Reg
> +  );
> +  return HdmiPhyPollI2cDone (HdmiDisplayContextPtr, 1000);
> +}
> +
> +BOOLEAN
> +GetGenericConfigSetting (
> +  IN  DISPLAY_TIMING    *DisplayTimingPtr,
> +  OUT PLL_MPLL_CONFIG   **ConfigGenericSettingPPtr
> +  )
> +{
> +  UINT32    ColorDepth;
> +  BOOLEAN   FoundConfig;
> +  UINT32    SettingIndex;
> +
> +  FoundConfig = FALSE;
> +  ColorDepth = GetColorDepth (DisplayTimingPtr->PixelFormat);
> +
> +  for (SettingIndex = 0;
> +       SettingIndex < ARRAYSIZE (PllMpllGenericConfigSetting);
> +       ++SettingIndex)
> +  {
> +    if ((DisplayTimingPtr->PixelClock ==
> +         PllMpllGenericConfigSetting[SettingIndex].PixelClock) &&
> +        (DisplayTimingPtr->PixelRepetition ==
> +         PllMpllGenericConfigSetting[SettingIndex].PixelRepetition) &&
> +        (ColorDepth == PllMpllGenericConfigSetting[SettingIndex].ColorDepth))
> +    {
> +      FoundConfig = TRUE;
> +      *ConfigGenericSettingPPtr = &PllMpllGenericConfigSetting[SettingIndex];
> +      break;
> +    }
> +  }
> +
> +  // Use the fallback value the last index if no configuration is found
> +  if (FoundConfig == FALSE) {
> +    *ConfigGenericSettingPPtr =
> +      &PllMpllGenericConfigSetting[ARRAYSIZE (PllMpllGenericConfigSetting)];
> +    FoundConfig = TRUE;
> +  }
> +
> +  return FoundConfig;
> +}
> +
> +EFI_STATUS
> +InitHdmi (
> +  IN  DISPLAY_CONTEXT   *DisplayContextPtr
> +  )
> +{
> +  DISPLAY_INTERFACE_CONTEXT   *pHdmiDisplayContext;
> +  EFI_STATUS                  Status;
> +
> +  pHdmiDisplayContext = &DisplayContextPtr->DiContext[HdmiDisplay];
> +  Status = EFI_SUCCESS;
> +  ZeroMem (pHdmiDisplayContext, sizeof (*pHdmiDisplayContext));
> +
> +  pHdmiDisplayContext->MmioBasePtr = (VOID *)HDMI_BASE;
> +  if (pHdmiDisplayContext->MmioBasePtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to map HDMI register\n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +  // Setup HDMI DDC muxing
> +  MmioWrite32 ((UINT32)IOMUXC_SW_MUX_CTL_PAD_KEY_COL3, 0x00000012);
> +  MmioWrite32 ((UINT32)IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3, 0x00000012);
> +  MmioWrite32 ((UINT32)IOMUXC_HDMI_II2C_CLKIN_SELECT_INPUT, 0x00000001);
> +  MmioWrite32 ((UINT32)IOMUXC_HDMI_II2C_DATAIN_SELECT_INPUT, 0x00000001);
> +  SetHdmiPower (pHdmiDisplayContext, TRUE);
> +
> +  // Mask all HDMI PHY interrupt
> +  MmioWrite8 (
> +    (UINT32)pHdmiDisplayContext->MmioBasePtr + HDMI_PHY_MASK0,
> +    0xFF
> +  );
> +
> +  Status = ReadEdid (
> +             DisplayContextPtr,
> +             HdmiDisplay,
> +             pHdmiDisplayContext->EdidData,
> +             &pHdmiDisplayContext->EdidDataSize
> +           );
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_WARN, "%a: Fail to read HDMI EDID data\n", __FUNCTION__));
> +    Status = EFI_SUCCESS;
> +  }
> +
> +  Status = GetPreferredTiming (
> +             pHdmiDisplayContext->EdidData,
> +             pHdmiDisplayContext->EdidDataSize,
> +             &pHdmiDisplayContext->PreferredTiming
> +           );
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to retrieve HDMI preferred timing\n",
> +      __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +  if ((pHdmiDisplayContext->PreferredTiming.HActive == 1920) &&
> +      (pHdmiDisplayContext->PreferredTiming.VActive == 1080))
> +  {
> +    pHdmiDisplayContext->PreferredTiming.HBlank -= 6;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +SetHdmiPower (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  BOOLEAN                     PowerState
> +  )
> +{
> +  HDMI_PHY_CONF0_REG  CurrentHdmiPhyConf0Reg;
> +
> +  CurrentHdmiPhyConf0Reg.Reg = MmioRead8 (
> +                                 (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                                 HDMI_PHY_CONF0
> +                               );
> +  if (PowerState) {
> +    // Setup PHY
> +    CurrentHdmiPhyConf0Reg.PDZ = 1;
> +    CurrentHdmiPhyConf0Reg.ENTMDS = 1;
> +    CurrentHdmiPhyConf0Reg.gen2_pddq = 1;
> +    CurrentHdmiPhyConf0Reg.gen2_txpwron = 1;
> +    CurrentHdmiPhyConf0Reg.seldataenpol = 1;
> +    CurrentHdmiPhyConf0Reg.seldipif = 0;
> +  } else {
> +    // Just power down PHY for shutdown
> +    CurrentHdmiPhyConf0Reg.PDZ = 0;
> +  }
> +
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0,
> +    CurrentHdmiPhyConf0Reg.Reg
> +  );
> +  gBS->Stall (3);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +SetHdmiPhy (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  DISPLAY_TIMING              *Timings
> +  )
> +{
> +  PLL_MPLL_CONFIG           *pPllMpllConfig;
> +  HDMI_PHY_CONF0_REG        CurrentHdmiPhyConf0Reg;
> +  HDMI_FC_AUDSCONF_REG      FcAudsconfReg;
> +  HDMI_MC_HEACPHY_RST_REG   HeacphyRstReg;
> +  HDMI_MC_CLKDIS_REG        McClkdisReg;
> +  HDMI_MC_PHYRSTZ_REG       PhyRstzReg;
> +  HDMI_PHY_STAT0_REG        PhyStat0Reg;
> +  BOOLEAN                   PhyStatus;
> +  UINT32                    RetryCount;
> +  EFI_STATUS                Status;
> +
> +  // Disable Audio
> +  FcAudsconfReg.Reg = MmioRead8 (
> +                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                        HDMI_FC_AUDSCONF
> +                      );
> +  FcAudsconfReg.aud_packet_layout = 0;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_FC_AUDSCONF,
> +    FcAudsconfReg.Reg
> +  );
> +
> +  // Minimum PCLK period / frequency (pixel repetition) : 74 ns / 13.5 MHz
> +  // Minimum PCLK period / frequency (no pixel repetition) : 39.7 ns / 24.175 MHz
> +  if (Timings->PixelClock < 13500000) {
> +    DEBUG ((DEBUG_ERROR, "%a: Unsupported pixel clock %d\n",
> +      __FUNCTION__, Timings->PixelClock));
> +    Status = EFI_INVALID_PARAMETER;
> +    goto Exit;
> +  }
> +
> +  if (GetGenericConfigSetting (Timings, &pPllMpllConfig) == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: No compatible generic config found\n",
> +      __FUNCTION__));
> +    Status = EFI_UNSUPPORTED;
> +    goto Exit;
> +  }
> +
> +  // Color Space Converter : Not used in UEFI
> +  McClkdisReg.Reg = MmioRead8 (
> +                      (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                      HDMI_MC_CLKDIS
> +                    );
> +  // Disable CEC, color converter, audio & pixel repitition
> +  McClkdisReg.cecclk_disable = 1;
> +  McClkdisReg.cscclk_disable = 1;
> +  McClkdisReg.audclk_disable = 1;
> +  McClkdisReg.prepclk_disable = 1;
> +  McClkdisReg.hdcpclk_disable = 1;
> +  McClkdisReg.tmdsclk_disable = 0;
> +  McClkdisReg.pixelclk_disable = 0;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_CLKDIS,
> +    McClkdisReg.Reg
> +  );
> +
> +  // Power down the PHY
> +  // To set the HDMI_PHY in Power-down mode, set the TX_PWRON signal to 1'b0
> +  // and the PDDQ signal to 1'b1. To power up the HDMI 3D Tx PHY and place it
> +  // in Active mode, set TX_PWRON to 1'b1 and PDDQ to 1'b0. Any configuration
> +  // programmed on the HDMI_PHY must be done in Power-down mode.
> +  CurrentHdmiPhyConf0Reg.Reg = MmioRead8 (
> +                                 (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                                 HDMI_PHY_CONF0
> +                               );
> +  CurrentHdmiPhyConf0Reg.gen2_txpwron = 0;
> +  CurrentHdmiPhyConf0Reg.gen2_pddq = 1;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0,
> +    CurrentHdmiPhyConf0Reg.Reg
> +  );
> +
> +  // Let's reset the PHY to a well defined state based on spec.
> +  // The PHY_RESET signal is used to place the digital section of the IP in
> +  // a well - defined state
> +  PhyRstzReg.Reg = MmioRead8 (
> +                     (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                     HDMI_MC_PHYRSTZ
> +                   );
> +  PhyRstzReg.phyrstz = 1;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_PHYRSTZ,
> +    PhyRstzReg.Reg
> +  );
> +  PhyRstzReg.phyrstz = 0;
> +  gBS->Stall (10);
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_PHYRSTZ,
> +    PhyRstzReg.Reg
> +  );
> +
> +  HeacphyRstReg.Reg = MmioRead8 (
> +                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                        HDMI_MC_HEACPHY_RST
> +                      );
> +  HeacphyRstReg.heacphyrst = 1;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_HEACPHY_RST,
> +    HeacphyRstReg.Reg
> +  );
> +
> +  // Program clock
> +  // PLL / MPLL Operation
> +  // The PLL / MPLL can be configured in Coherent mode or NonCoherent mode (default).
> +  //  In Coherent mode, the TMDS clock is the MPLL feedback clock, which is
> +  //  coherent with the MPLL's high-speed output clock, because both clocks are
> +  //  shaped by the MPLL response.
> +  //  In NonCoherent mode, the TMDS clock is the MPLL reference clock, which is
> +  //  not coherent with the MPLL's high-speed output clock.
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_CPCE_CTRL,
> +                pPllMpllConfig->HdmiPhyCpceCtrl.Reg
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CPCE_CTRL %x\n",
> +      __FUNCTION__, pPllMpllConfig->HdmiPhyCpceCtrl.Reg));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_CURRCTRL,
> +                pPllMpllConfig->HdmiPhyCurrctrl.Reg
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CURRCTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  };
> +
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_GMPCTRL,
> +                pPllMpllConfig->HdmiPhyGmpctrl.Reg
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_GMPCTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Maintaining the order of phy register writes
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_PLLPHBYCTRL,
> +                0x0000
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_PLLPHBYCTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Coherent mode
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_MSM_CTRL,
> +                0x0006
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_MSM_CTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Resistance value 133.33 ohm
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_TXTERM,
> +                0x0005
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_TXTERM\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Enable clock symbol
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_CKSYMTXCTRL,
> +                0x8009
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CKSYMTXCTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_VLEVCTRL,
> +                0x0210
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_VLEVCTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  // Enable override
> +  PhyStatus = HdmiPhyI2cWrite (
> +                HdmiDisplayContextPtr,
> +                HDMI_PHY_CKCALCTRL,
> +                0x8000
> +              );
> +  if (PhyStatus == FALSE) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CKCALCTRL\n",
> +      __FUNCTION__));
> +    Status = EFI_DEVICE_ERROR;
> +    goto Exit;
> +  }
> +
> +  CurrentHdmiPhyConf0Reg.gen2_txpwron = 1;
> +  CurrentHdmiPhyConf0Reg.gen2_pddq = 0;
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0,
> +    CurrentHdmiPhyConf0Reg.Reg
> +  );
> +
> +  Status = EFI_DEVICE_ERROR;
> +  for (RetryCount = 5; RetryCount > 0; RetryCount--) {
> +    PhyStat0Reg.Reg = MmioRead8 (
> +                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                        HDMI_PHY_STAT0
> +                      );
> +    if (!PhyStat0Reg.TX_PHY_LOCK) {
> +      Status = EFI_SUCCESS;
> +      break;
> +    }
> +    gBS->Stall (1000);
> +  }
> +
> +  if (RetryCount == 0) {
> +    DEBUG ((DEBUG_ERROR, "%a: TX PHY remain unlock\n", __FUNCTION__));
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +SetHdmiDisplay (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  DISPLAY_TIMING              *Timings
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = SetHdmiPhy (HdmiDisplayContextPtr, Timings);
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "%a: SetHdmiPhy failed\n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +VOID
> +SetDdcSpeed (
> +  IN  DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr,
> +  IN  DDC_MODE                  Mode
> +  )
> +{
> +  MmioWrite8 ((UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_DIV, Mode);
> +}
> +
> +EFI_STATUS
> +HdmiDdcRead (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  UINT8                       SlaveAddress,
> +  IN  UINT8                       RegisterAddress,
> +  IN  UINT32                      ReadSize,
> +  IN  DDC_MODE                    DDCMode,
> +  IN  UINT8                       *DataReadPtr
> +  )
> +{
> +  UINT8       *pCurrentDataRead;
> +  UINT32      AddrCount;
> +  UINT8       I2cmIntStatus;
> +  UINT32      I2cRetryCount;
> +  EFI_STATUS  Status;
> +
> +  pCurrentDataRead = DataReadPtr;
> +  Status = EFI_SUCCESS;
> +
> +  // Setup EDID transaction and loop through all byte request
> +  SetDdcSpeed (HdmiDisplayContextPtr, DDCMode);
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0,
> +    I2C_MASTER_ERROR | I2C_MASTER_DONE
> +  );
> +  MmioWrite8 (
> +    (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_SLAVE,
> +    SlaveAddress
> +  );
> +
> +  for (AddrCount = 0; AddrCount < ReadSize; ++AddrCount) {
> +    I2cRetryCount = 1000;
> +
> +    MmioWrite8 (
> +      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_ADDRESS,
> +      (UINT8) ( RegisterAddress + AddrCount)
> +    );
> +    MmioWrite8 (
> +      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_SEGADDR,
> +      0x00
> +    );
> +    MmioWrite8 (
> +      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_OPERATION,
> +      DDC_READ_OPERATION
> +    );
> +
> +    // Poll for completion
> +    I2cmIntStatus = MmioRead8 (
> +                      (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                      HDMI_IH_I2CM_STAT0
> +                    );
> +    for (I2cRetryCount = 1000; I2cRetryCount > 0; I2cRetryCount--) {
> +      I2cmIntStatus = MmioRead8 (
> +                        (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                        HDMI_IH_I2CM_STAT0
> +                      );
> +      if (I2cmIntStatus != 0) {
> +        break;
> +      }
> +    }
> +
> +    if (I2cRetryCount == 0) {
> +      Status = EFI_DEVICE_ERROR;
> +      DEBUG ((DEBUG_ERROR, "%a: Timeout waiting for interrupt 0x%02x\n",
> +        __FUNCTION__, I2cmIntStatus));
> +      goto Exit;
> +    }
> +
> +    if ((I2cmIntStatus & I2C_MASTER_DONE) &&
> +        !(I2cmIntStatus & I2C_MASTER_ERROR))
> +    {
> +      *pCurrentDataRead = MmioRead8 (
> +                            (UINT32)HdmiDisplayContextPtr->MmioBasePtr +
> +                            HDMI_I2CM_DATAI
> +                          );
> +      pCurrentDataRead++;
> +      MmioWrite8 (
> +        (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0,
> +        I2C_MASTER_ERROR | I2C_MASTER_DONE
> +      );
> +    } else {
> +      Status = EFI_DEVICE_ERROR;
> +      DEBUG ((DEBUG_ERROR, "%a: Failed to read with DDC 0x%02x\n",
> +        __FUNCTION__, I2cmIntStatus));
> +      goto Exit;
> +    }
> +
> +    MmioWrite8 (
> +      (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0,
> +      I2C_MASTER_ERROR | I2C_MASTER_DONE
> +    );
> +  }
> +
> +Exit:
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
> new file mode 100644
> index 000000000000..e1b7372bc2e9
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
> @@ -0,0 +1,529 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _HDMI_H_
> +#define _HDMI_H_

IMX_ prefix, please.

> +
> +// HDMI Register Base Address
> +#define HDMI_BASE 0x00120000
> +
> +// Interrupt Register Offset
> +#define HDMI_IH_FC_STAT0                0x0100
> +#define HDMI_IH_FC_STAT1                0x0101
> +#define HDMI_IH_FC_STAT2                0x0102
> +#define HDMI_IH_AS_STAT0                0x0103
> +#define HDMI_IH_PHY_STAT0               0x0104
> +#define HDMI_IH_I2CM_STAT0              0x0105
> +#define HDMI_IH_CEC_STAT0               0x0106
> +#define HDMI_IH_VP_STAT0                0x0107
> +#define HDMI_IH_I2CMPHY_STAT0           0x0108
> +#define HDMI_IH_AHBDMAAUD_STAT0         0x0180
> +#define HDMI_IH_MUTE_FC_STAT1           0x0181
> +#define HDMI_IH_MUTE_FC_STAT2           0x0182
> +#define HDMI_IH_MUTE_AS_STAT0           0x0183
> +#define HDMI_IH_MUTE_PHY_STAT0          0x0184
> +#define HDMI_IH_MUTE_I2CM_STAT0         0x0185
> +#define HDMI_IH_MUTE_CEC_STAT0          0x0186
> +#define HDMI_IH_MUTE_VP_STAT0           0x0187
> +#define HDMI_IH_MUTE_I2CMPHY_STAT0      0x0188
> +#define HDMI_IH_MUTE_AHBDMAAUD_STAT0    0x0189
> +#define HDMI_IH_MUTE                    0x01FF
> +#define HDMI_FC_INVIDCONF               0x1000
> +#define HDMI_FC_INHACTV0                0x1001
> +#define HDMI_FC_INHACTV1                0x1002
> +#define HDMI_FC_INHBLANK0               0x1003
> +#define HDMI_FC_INHBLANK1               0x1004
> +#define HDMI_FC_INVACTV0                0x1005
> +#define HDMI_FC_INVACTV1                0x1006
> +#define HDMI_FC_INVBLANK                0x1007
> +#define HDMI_FC_HSYNCINDELAY0           0x1008
> +#define HDMI_FC_HSYNCINDELAY1           0x1009
> +#define HDMI_FC_HSYNCINWIDTH0           0x100A
> +#define HDMI_FC_HSYNCINWIDTH1           0x100B
> +#define HDMI_FC_VSYNCINDELAY            0x100C
> +#define HDMI_FC_VSYNCINWIDTH            0x100D
> +#define HDMI_FC_INFREQ0                 0x100E
> +#define HDMI_FC_INFREQ1                 0x100F
> +#define HDMI_FC_INFREQ2                 0x1010
> +#define HDMI_FC_CTRLDUR                 0x1011
> +#define HDMI_FC_EXCTRLDUR               0x1012
> +#define HDMI_FC_EXCTRLSPAC              0x1013
> +#define HDMI_FC_CH0PREAM                0x1014
> +#define HDMI_FC_CH1PREAM                0x1015
> +#define HDMI_FC_CH2PREAM                0x1016
> +#define HDMI_FC_AVICONF3                0x1017
> +#define HDMI_FC_GCP                     0x1018
> +#define HDMI_FC_AVICONF0                0x1019
> +#define HDMI_FC_AVICONF1                0x101A
> +#define HDMI_FC_AVICONF2                0x101B
> +#define HDMI_FC_AVIVID                  0x101C
> +#define HDMI_FC_AVIETB0                 0x101D
> +#define HDMI_FC_AVIETB1                 0x101E
> +#define HDMI_FC_AVISBB0                 0x101F
> +#define HDMI_FC_AVISBB1                 0x1020
> +#define HDMI_FC_AVIELB0                 0x1021
> +#define HDMI_FC_AVIELB1                 0x1022
> +#define HDMI_FC_AVISRB0                 0x1023
> +#define HDMI_FC_AVISRB1                 0x1024
> +#define HDMI_FC_AUDICONF0               0x1025
> +#define HDMI_FC_AUDICONF1               0x1026
> +#define HDMI_FC_AUDICONF2               0x1027
> +#define HDMI_FC_AUDICONF3               0x1028
> +#define HDMI_FC_VSDIEEEID0              0x1029
> +#define HDMI_FC_VSDSIZE                 0x102A
> +#define HDMI_FC_VSDIEEEID1              0x1030
> +#define HDMI_FC_VSDIEEEID2              0x1031
> +#define HDMI_FC_VSDPAYLOAD0             0x1032
> +#define HDMI_FC_VSDPAYLOAD1             0x1033
> +#define HDMI_FC_VSDPAYLOAD2             0x1034
> +#define HDMI_FC_VSDPAYLOAD3             0x1035
> +#define HDMI_FC_VSDPAYLOAD4             0x1036
> +#define HDMI_FC_VSDPAYLOAD5             0x1037
> +#define HDMI_FC_VSDPAYLOAD6             0x1038
> +#define HDMI_FC_VSDPAYLOAD7             0x1039
> +#define HDMI_FC_VSDPAYLOAD8             0x103A
> +#define HDMI_FC_VSDPAYLOAD9             0x103B
> +#define HDMI_FC_VSDPAYLOAD10            0x103C
> +#define HDMI_FC_VSDPAYLOAD11            0x103D
> +#define HDMI_FC_VSDPAYLOAD12            0x103E
> +#define HDMI_FC_VSDPAYLOAD13            0x103F
> +#define HDMI_FC_VSDPAYLOAD14            0x1040
> +#define HDMI_FC_VSDPAYLOAD15            0x1041
> +#define HDMI_FC_VSDPAYLOAD16            0x1042
> +#define HDMI_FC_VSDPAYLOAD17            0x1043
> +#define HDMI_FC_VSDPAYLOAD18            0x1044
> +#define HDMI_FC_VSDPAYLOAD19            0x1045
> +#define HDMI_FC_VSDPAYLOAD20            0x1046
> +#define HDMI_FC_VSDPAYLOAD21            0x1047
> +#define HDMI_FC_VSDPAYLOAD22            0x1048
> +#define HDMI_FC_VSDPAYLOAD23            0x1049
> +#define HDMI_FC_SPDVENDORNAME0          0x104A
> +#define HDMI_FC_SPDVENDORNAME1          0x104B
> +#define HDMI_FC_SPDVENDORNAME2          0x104C
> +#define HDMI_FC_SPDVENDORNAME3          0x104D
> +#define HDMI_FC_SPDVENDORNAME4          0x104E
> +#define HDMI_FC_SPDVENDORNAME5          0x104F
> +#define HDMI_FC_SPDVENDORNAME6          0x1050
> +#define HDMI_FC_SPDVENDORNAME7          0x1051
> +#define HDMI_FC_SDPPRODUCTNAME0         0x1052
> +#define HDMI_FC_SDPPRODUCTNAME1         0x1053
> +#define HDMI_FC_SDPPRODUCTNAME2         0x1054
> +#define HDMI_FC_SDPPRODUCTNAME3         0x1055
> +#define HDMI_FC_SDPPRODUCTNAME4         0x1056
> +#define HDMI_FC_SDPPRODUCTNAME5         0x1057
> +#define HDMI_FC_SDPPRODUCTNAME6         0x1058
> +#define HDMI_FC_SDPPRODUCTNAME7         0x1059
> +#define HDMI_FC_SDPPRODUCTNAME8         0x105A
> +#define HDMI_FC_SDPPRODUCTNAME9         0x105B
> +#define HDMI_FC_SDPPRODUCTNAME10        0x105C
> +#define HDMI_FC_SDPPRODUCTNAME11        0x105D
> +#define HDMI_FC_SDPPRODUCTNAME12        0x105E
> +#define HDMI_FC_SDPPRODUCTNAME13        0x105F
> +#define HDMI_FC_SDPPRODUCTNAME14        0x1060
> +#define HDMI_FC_SPDPRODUCTNAME15        0x1061
> +#define HDMI_FC_SPDDEVICEINF            0x1062
> +#define HDMI_FC_AUDSCONF                0x1063
> +#define HDMI_FC_AUDSSTAT                0x1064
> +#define HDMI_FC_AUDSV                   0x1065
> +#define HDMI_FC_AUDSU                   0x1066
> +#define HDMI_FC_AUDSCHNLS0              0x1067
> +#define HDMI_FC_AUDSCHNLS1              0x1068
> +#define HDMI_FC_AUDSCHNLS2              0x1069
> +#define HDMI_FC_AUDSCHNLS3              0x106A
> +#define HDMI_FC_AUDSCHNLS4              0x106B
> +#define HDMI_FC_AUDSCHNLS5              0x106C
> +#define HDMI_FC_AUDSCHNLS6              0x106D
> +#define HDMI_FC_AUDSCHNLS7              0x106E
> +#define HDMI_FC_AUDSCHNLS8              0x106F
> +#define HDMI_FC_DATACH0FILL             0x1070
> +#define HDMI_FC_DATACH1FILL             0x1071
> +#define HDMI_FC_DATACH2FILL             0x1072
> +#define HDMI_FC_CTRLQHIGH               0x1073
> +#define HDMI_FC_CTRLQLOW                0x1074
> +#define HDMI_FC_ACP0                    0x1075
> +#define HDMI_FC_ACP28                   0x1076
> +#define HDMI_FC_ACP27                   0x1077
> +#define HDMI_FC_ACP26                   0x1078
> +#define HDMI_FC_ACP25                   0x1079
> +#define HDMI_FC_ACP24                   0x107A
> +#define HDMI_FC_ACP23                   0x107B
> +#define HDMI_FC_ACP22                   0x107C
> +#define HDMI_FC_ACP21                   0x107D
> +#define HDMI_FC_ACP20                   0x107E
> +#define HDMI_FC_ACP19                   0x107F
> +#define HDMI_FC_ACP18                   0x1080
> +#define HDMI_FC_ACP17                   0x1081
> +#define HDMI_FC_ACP16                   0x1082
> +#define HDMI_FC_ACP15                   0x1083
> +#define HDMI_FC_ACP14                   0x1084
> +#define HDMI_FC_ACP13                   0x1085
> +#define HDMI_FC_ACP12                   0x1086
> +#define HDMI_FC_ACP11                   0x1087
> +#define HDMI_FC_ACP10                   0x1088
> +#define HDMI_FC_ACP9                    0x1089
> +#define HDMI_FC_ACP8                    0x108A
> +#define HDMI_FC_ACP7                    0x108B
> +#define HDMI_FC_ACP6                    0x108C
> +#define HDMI_FC_ACP5                    0x108D
> +#define HDMI_FC_ACP4                    0x108E
> +#define HDMI_FC_ACP3                    0x108F
> +#define HDMI_FC_ACP2                    0x1090
> +#define HDMI_FC_ACP1                    0x1091
> +#define HDMI_FC_ISCR1_0                 0x1092
> +#define HDMI_FC_ISCR1_16                0x1093
> +#define HDMI_FC_ISCR1_15                0x1094
> +#define HDMI_FC_ISCR1_14                0x1095
> +#define HDMI_FC_ISCR1_13                0x1096
> +#define HDMI_FC_ISCR1_12                0x1097
> +#define HDMI_FC_ISCR1_11                0x1098
> +#define HDMI_FC_ISCR1_10                0x1099
> +#define HDMI_FC_ISCR1_9                 0x109A
> +#define HDMI_FC_ISCR1_8                 0x109B
> +#define HDMI_FC_ISCR1_7                 0x109C
> +#define HDMI_FC_ISCR1_6                 0x109D
> +#define HDMI_FC_ISCR1_5                 0x109E
> +#define HDMI_FC_ISCR1_4                 0x109F
> +#define HDMI_FC_ISCR1_3                 0x10A0
> +#define HDMI_FC_ISCR1_2                 0x10A1
> +#define HDMI_FC_ISCR1_1                 0x10A2
> +#define HDMI_FC_ISCR2_15                0x10A3
> +#define HDMI_FC_ISCR2_14                0x10A4
> +#define HDMI_FC_ISCR2_13                0x10A5
> +#define HDMI_FC_ISCR2_12                0x10A6
> +#define HDMI_FC_ISCR2_11                0x10A7
> +#define HDMI_FC_ISCR2_10                0x10A8
> +#define HDMI_FC_ISCR2_9                 0x10A9
> +#define HDMI_FC_ISCR2_8                 0x10AA
> +#define HDMI_FC_ISCR2_7                 0x10AB
> +#define HDMI_FC_ISCR2_6                 0x10AC
> +#define HDMI_FC_ISCR2_5                 0x10AD
> +#define HDMI_FC_ISCR2_4                 0x10AE
> +#define HDMI_FC_ISCR2_3                 0x10AF
> +#define HDMI_FC_ISCR2_2                 0x10B0
> +#define HDMI_FC_ISCR2_1                 0x10B1
> +#define HDMI_FC_ISCR2_0                 0x10B2
> +#define HDMI_FC_DATAUTO0                0x10B3
> +#define HDMI_FC_DATAUTO1                0x10B4
> +#define HDMI_FC_DATAUTO2                0x10B5
> +#define HDMI_FC_DATMAN                  0x10B6
> +#define HDMI_FC_DATAUTO3                0x10B7
> +#define HDMI_FC_RDRB0                   0x10B8
> +#define HDMI_FC_RDRB1                   0x10B9
> +#define HDMI_FC_RDRB2                   0x10BA
> +#define HDMI_FC_RDRB3                   0x10BB
> +#define HDMI_FC_RDRB4                   0x10BC
> +#define HDMI_FC_RDRB5                   0x10BD
> +#define HDMI_FC_RDRB6                   0x10BE
> +#define HDMI_FC_RDRB7                   0x10BF
> +#define HDMI_FC_STAT0                   0x10D0
> +#define HDMI_FC_INT0                    0x10D1
> +#define HDMI_FC_MASK0                   0x10D2
> +#define HDMI_FC_POL0                    0x10D3
> +#define HDMI_FC_STAT1                   0x10D4
> +#define HDMI_FC_INT1                    0x10D5
> +#define HDMI_FC_MASK1                   0x10D6
> +#define HDMI_FC_POL1                    0x10D7
> +#define HDMI_FC_STAT2                   0x10D8
> +#define HDMI_FC_INT2                    0x10D9
> +#define HDMI_FC_MASK2                   0x10DA
> +#define HDMI_FC_POL2                    0x10DB
> +#define HDMI_FC_PRCONF                  0x10E0
> +
> +// HDMI PHY Register Offset
> +#define HDMI_PHY_CONF0                      0x3000
> +#define HDMI_PHY_TST0                       0x3001
> +#define HDMI_PHY_TST1                       0x3002
> +#define HDMI_PHY_TST2                       0x3003
> +#define HDMI_PHY_STAT0                      0x3004
> +#define HDMI_PHY_INT0                       0x3005
> +#define HDMI_PHY_MASK0                      0x3006
> +#define HDMI_PHY_POL0                       0x3007
> +#define HDMI_PHY_I2CM_SLAVE_ADDR            0x3020
> +#define HDMI_PHY_I2CM_ADDRESS_ADDR          0x3021
> +#define HDMI_PHY_I2CM_DATAO_1_ADDR          0x3022
> +#define HDMI_PHY_I2CM_DATAO_0_ADDR          0x3023
> +#define HDMI_PHY_I2CM_DATAI_1_ADDR          0x3024
> +#define HDMI_PHY_I2CM_DATAI_0_ADDR          0x3025
> +#define HDMI_PHY_I2CM_OPERATION_ADDR        0x3026
> +#define HDMI_PHY_I2CM_INT_ADDR              0x3027
> +#define HDMI_PHY_I2CM_CTLINT_ADDR           0x3028
> +#define HDMI_PHY_I2CM_DIV_ADDR              0x3029
> +#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR         0x302a
> +#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR    0x302b
> +#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR    0x302c
> +#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR    0x302d
> +#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR    0x302e
> +#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR    0x302f
> +#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR    0x3030
> +#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR    0x3031
> +#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR    0x3032
> +
> +// Main Controller Registers
> +#define HDMI_MC_CLKDIS          0x4001
> +#define HDMI_MC_SWRSTZ          0x4002
> +#define HDMI_MC_OPCTRL          0x4003
> +#define HDMI_MC_FLOWCTRL        0x4004
> +#define HDMI_MC_PHYRSTZ         0x4005
> +#define HDMI_MC_LOCKONCLOCK     0x4006
> +#define HDMI_MC_HEACPHY_RST     0x4007
> +
> +// HDMI_PHY absolute address
> +#define HDMI_PHY_PWRCTRL        0x00
> +#define HDMI_PHY_SERDIVCTRL     0x01
> +#define HDMI_PHY_SERCKCTRL      0x02
> +#define HDMI_PHY_SERCKKILLCTRL  0x03
> +#define HDMI_PHY_TXRESCTRL      0x04
> +#define HDMI_PHY_CKCALCTRL      0x05
> +#define HDMI_PHY_CPCE_CTRL      0x06
> +#define HDMI_PHY_TXCLKMEASCTRL  0x07
> +#define HDMI_PHY_TXMEASCTRL     0x08
> +#define HDMI_PHY_CKSYMTXCTRL    0x09
> +#define HDMI_PHY_CMPSEQCTRL     0x0A
> +#define HDMI_PHY_CMPPWRCTRL     0x0B
> +#define HDMI_PHY_CMPMODECTRL    0x0C
> +#define HDMI_PHY_MEASCTRL       0x0D
> +#define HDMI_PHY_VLEVCTRL       0x0E
> +#define HDMI_PHY_D2ACTRL        0x0F
> +#define HDMI_PHY_CURRCTRL       0x10
> +#define HDMI_PHY_DRVANACTRL     0x11
> +#define HDMI_PHY_PLLMEASCTRL    0x12
> +#define HDMI_PHY_PLLPHBYCTRL    0x13
> +#define HDMI_PHY_GRP_CTRL       0x14
> +#define HDMI_PHY_GMPCTRL        0x15
> +#define HDMI_PHY_MPLLMEASCTRL   0x16
> +#define HDMI_PHY_MSM_CTRL       0x17
> +#define HDMI_PHY_SCRPB_STATUS   0x18
> +#define HDMI_PHY_TXTERM         0x19
> +#define HDMI_PHY_PTRPT_ENBL     0x1A
> +#define HDMI_PHY_PATTERNGEN     0x1B
> +#define HDMI_PHY_SDCAP_MODE     0x1C
> +#define HDMI_PHY_SCOPEMODE      0x1D
> +#define HDMI_PHY_DIGTXMODE      0x1E
> +#define HDMI_PHY_STR_STATUS     0x1F
> +#define HDMI_PHY_SCOPECNT0      0x20
> +#define HDMI_PHY_SCOPECNT1      0x21
> +#define HDMI_PHY_SCOPECNT2      0x22
> +#define HDMI_PHY_SCOPECNTCLK    0x23
> +#define HDMI_PHY_SCOPESAMPLE    0x24
> +#define HDMI_PHY_SCOPECNTMSB01  0x25
> +#define HDMI_PHY_SCOPECNTMSB2CK 0x26
> +
> +// HDMI DDC offset
> +#define HDMI_I2CM_SLAVE                 0x7E00
> +#define HDMI_I2CM_ADDRESS               0x7E01
> +#define HDMI_I2CM_DATAO                 0x7E02
> +#define HDMI_I2CM_DATAI                 0x7E03
> +#define HDMI_I2CM_OPERATION             0x7E04
> +#define HDMI_I2CM_INT                   0x7E05
> +#define HDMI_I2CM_CTLINT                0x7E06
> +#define HDMI_I2CM_DIV                   0x7E07
> +#define HDMI_I2CM_SEGADDR               0x7E08
> +#define HDMI_I2CM_SOFTRSTZ              0x7E09
> +#define HDMI_I2CM_SEGPTR                0x7E0A
> +#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR    0x7E0B
> +#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR    0x7E0C
> +#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR    0x7E0D
> +#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR    0x7E0E
> +#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR    0x7E0F
> +#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR    0x7E10
> +#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR    0x7E11
> +#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR    0x7E12
> +
> +// DDC Interrupt status
> +#define I2C_MASTER_ERROR                0x01
> +#define I2C_MASTER_DONE                 0x02
> +
> +// HDMI bit configuration
> +typedef enum {
> +  DDC_READ_OPERATION = 0x01,
> +  DDC_READ_EXT_OPERATION = 0x02,
> +  DDC_WRITE_OPERATION = 0x10,
> +} DDC_OPERATION;
> +
> +typedef enum {
> +  HDMI_DDC_STANDARD_MODE = 0x00,
> +  HDMI_DDC_FAST_MODE = 0x04,
> +} DDC_MODE;
> +
> +#pragma pack(push, 1)
> +
> +// HDMI_PHY_CONF0 0x0100
> +typedef union {
> +  struct {
> +    UINT8 seldipif : 1;
> +    UINT8 seldataenpol : 1;
> +    UINT8 gen2_enhpdrxsense : 1;
> +    UINT8 gen2_txpwron : 1;
> +    UINT8 gen2_pddq : 1;
> +    UINT8 sparectrl : 1;
> +    UINT8 ENTMDS : 1;
> +    UINT8 PDZ : 1;
> +  };
> +  UINT8 Reg;
> +}  HDMI_PHY_CONF0_REG;
> +
> +// HDMI_IH_I2CMPHY_STAT0 0x0108
> +typedef union {
> +  struct {
> +    UINT8 i2cmphyerror : 1;
> +    UINT8 i2cmphydone : 1;
> +    UINT8 reserved : 6;
> +  };
> +  UINT8 Reg;
> +}  HDMI_IH_I2CMPHY_STAT0_REG;
> +
> +// HDMI_FC_AUDSCONF 0x01063
> +typedef union {
> +  struct {
> +    UINT8 aud_packet_layout : 1;
> +    UINT8 reserved : 4;
> +    UINT8 aud_packet_sampfit : 4;
> +  };
> +  UINT8 Reg;
> +}  HDMI_FC_AUDSCONF_REG;
> +
> +// HDMI_PHY_STAT0 0x3004
> +typedef union {
> +  struct {
> +    UINT8 TX_PHY_LOCK : 1;
> +    UINT8 HPD : 1;
> +    UINT8 reserved : 2;
> +    UINT8 RX_SENSE0 : 1;
> +    UINT8 RX_SENSE1 : 1;
> +    UINT8 RX_SENSE2 : 1;
> +    UINT8 RX_SENSE3 : 1;
> +  };
> +  UINT8 Reg;
> +}  HDMI_PHY_STAT0_REG;
> +
> +// HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
> +typedef union {
> +  struct {
> +    UINT8 read : 1;
> +    UINT8 reserved0 : 3;
> +    UINT8 write : 1;
> +    UINT8 reserved1 : 3;
> +  };
> +  UINT8 Reg;
> +}  HDMI_PHY_I2CM_OPERATION_ADDR_REG;
> +
> +// HDMI_MC_CLKDIS 0x4001
> +typedef union {
> +  struct {
> +    UINT8 pixelclk_disable : 1;
> +    UINT8 tmdsclk_disable : 1;
> +    UINT8 prepclk_disable : 1;
> +    UINT8 audclk_disable : 1;
> +    UINT8 cscclk_disable : 1;
> +    UINT8 cecclk_disable : 1;
> +    UINT8 hdcpclk_disable : 1;
> +    UINT8 reserved : 1;
> +  };
> +  UINT8 Reg;
> +} HDMI_MC_CLKDIS_REG;
> +
> +// HDMI_MC_PHYRSTZ 0x4005
> +typedef union {
> +  struct {
> +    UINT8 phyrstz : 1;
> +    UINT8 reserved : 7;
> +  };
> +  UINT8 Reg;
> +}  HDMI_MC_PHYRSTZ_REG;
> +
> +// HDMI_MC_HEACPHY_RST 0x4007
> +typedef union {
> +  struct {
> +    UINT8 heacphyrst : 1;
> +    UINT8 reserved : 7;
> +  };
> +  UINT8 Reg;
> +}  HDMI_MC_HEACPHY_RST_REG;
> +
> +// HDMI PHY : HDMI_PHY_CPCE_CTRL 0x06
> +typedef union {
> +  struct {
> +    UINT16 clr_dpth : 2;
> +    UINT16 pixel_rep : 3;
> +    UINT16 pll_n_cntrl : 2;
> +    UINT16 mpll_n_cntrl : 2;
> +    UINT16 ck_edgerate : 2;
> +    UINT16 tx_edgerate : 2;
> +    UINT16 prep_div : 2;
> +    UINT16 reserved : 1;
> +  };
> +  UINT16 Reg;
> +}  HDMI_PHY_CPCE_CTRL_REG;
> +
> +// HDMI PHY : HDMI_PHY_CURRCTRL 0x10
> +typedef union {
> +  struct {
> +    UINT16 pll_int_cntrl : 3;
> +    UINT16 pll_prop_cntrl : 3;
> +    UINT16 mpll_int_cntrl : 3;
> +    UINT16 mpll_prop_cntrl : 3;
> +    UINT16 reserved : 4;
> +  };
> +  UINT16 Reg;
> +}  HDMI_PHY_CURRCTRL_REG;
> +
> +// HDMI PHY : HDMI_PHY_GMPCTRL 0x15
> +typedef union {
> +  struct {
> +    UINT16 mpll_gmp_cntrl : 2;
> +    UINT16 pll_gmp_cntrl : 2;
> +    UINT16 reserved : 12;
> +  };
> +  UINT16 Reg;
> +}  HDMI_PHY_GMPCTRL_REG;
> +
> +#pragma pack(pop)
> +
> +typedef struct _PLL_MPLL_CONFIG {
> +  UINT32 PixelClock;
> +  UINT8 PixelRepetition;
> +  UINT8 ColorDepth;
> +  HDMI_PHY_CPCE_CTRL_REG HdmiPhyCpceCtrl;
> +  HDMI_PHY_CURRCTRL_REG HdmiPhyCurrctrl;
> +  HDMI_PHY_GMPCTRL_REG HdmiPhyGmpctrl;
> +} PLL_MPLL_CONFIG, *PPLL_MPLL_CONFIG;
> +
> +EFI_STATUS
> +InitHdmi (
> +  IN  DISPLAY_CONTEXT   *DisplayContextPtr
> +  );
> +
> +EFI_STATUS
> +SetHdmiPower (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  BOOLEAN                     PowerState
> +  );
> +
> +EFI_STATUS
> +SetHdmiDisplay (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  DISPLAY_TIMING              *Timings
> +  );
> +
> +EFI_STATUS
> +HdmiDdcRead (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  UINT8                       SlaveAddress,
> +  IN  UINT8                       RegisterAddress,
> +  IN  UINT32                      ReadSize,
> +  IN  DDC_MODE                    DDCMode,
> +  IN  UINT8                       *DataReadPtr
> +  );
> +
> +#endif  /* _HDMI_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
> new file mode 100644
> index 000000000000..b82fbd2125f5
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
> @@ -0,0 +1,88 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "IoMux.h"
> +
> +EFI_STATUS
> +SetupDisplayMux (
> +  IN  DISPLAY_CONTEXT   *DisplayContextPtr
> +  )
> +{
> +  DISPLAY_INTERFACE_TYPE              *pDisplayInterfaceType;
> +  volatile IMX_IOMUXC_GPR_REGISTERS   *pIomuxcGprReg;
> +  UINT32                              DisplayInterfaceIndex;
> +  DISPLAY_MODE                        DisplayMode;
> +  UINT32                              Gpr3Reg;
> +  UINT32                              SourceMask;
> +  UINT32                              SourceValue;
> +  EFI_STATUS                          Status;
> +
> +  pIomuxcGprReg = DisplayContextPtr->IoMuxMmioBasePtr;
> +  DisplayMode = DisplayContextPtr->DisplayConfig.DisplayMode;
> +  pDisplayInterfaceType = DisplayContextPtr->DisplayConfig.DiOrder;
> +  Status = EFI_SUCCESS;
> +
> +  Gpr3Reg = MmioRead32 ((UINT32)&pIomuxcGprReg->GPR3);
> +  Gpr3Reg &= ~(HDMI_MUX_CTL_MASK | MIPI_MUX_CTL_MASK |
> +               LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
> +  MmioWrite32 ((UINT32)&pIomuxcGprReg->GPR3, Gpr3Reg);
> +
> +  for (DisplayInterfaceIndex = 0; DisplayInterfaceIndex < (UINT32)DisplayMode; ++DisplayInterfaceIndex) {
> +    Gpr3Reg = MmioRead32 ((UINT32)&pIomuxcGprReg->GPR3);
> +    switch (pDisplayInterfaceType[DisplayInterfaceIndex]) {
> +    case HdmiDisplay:
> +      SourceMask = HDMI_MUX_CTL_MASK;
> +      SourceValue = DisplayInterfaceIndex << HDMI_MUX_CTL_OFFSET;
> +      break;
> +    case MipiDisplay:
> +      SourceMask = MIPI_MUX_CTL_MASK;
> +      SourceValue = DisplayInterfaceIndex << MIPI_MUX_CTL_OFFSET;
> +      break;
> +    case Lvds0Display:
> +      SourceMask = LVDS0_MUX_CTL_MASK;
> +      SourceValue = DisplayInterfaceIndex << LVDS0_MUX_CTL_OFFSET;
> +      break;
> +    case Lvds1Display:
> +      SourceMask = LVDS1_MUX_CTL_MASK;
> +      SourceValue = DisplayInterfaceIndex << LVDS1_MUX_CTL_OFFSET;
> +      break;
> +    default:
> +      Status = EFI_UNSUPPORTED;
> +      break;
> +    }
> +    if (EFI_ERROR (Status)) {
> +      break;
> +    }
> +
> +    Gpr3Reg &= ~SourceMask;
> +    Gpr3Reg |= SourceValue;
> +    MmioWrite32 ((UINT32)&pIomuxcGprReg->GPR3, Gpr3Reg);
> +  }
> +
> +  return Status;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
> new file mode 100644
> index 000000000000..4946ab293ae5
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
> @@ -0,0 +1,32 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IO_MUX_H_
> +#define _IO_MUX_H_

IMX_ prefix, please.

> +
> +#define HDMI_MUX_CTL_OFFSET         2
> +#define HDMI_MUX_CTL_MASK           0x000C
> +#define MIPI_MUX_CTL_OFFSET         4
> +#define MIPI_MUX_CTL_MASK           0x0030
> +#define LVDS0_MUX_CTL_OFFSET        6
> +#define LVDS0_MUX_CTL_MASK          0x00C0
> +#define LVDS1_MUX_CTL_OFFSET        8
> +#define LVDS1_MUX_CTL_MASK          0x0300
> +
> +EFI_STATUS
> +SetupDisplayMux (
> +  IN  DISPLAY_CONTEXT   *DisplayContextPtr
> +  );
> +
> +#endif  /* _IO_MUX_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
> new file mode 100644
> index 000000000000..00d20c881b67
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
> @@ -0,0 +1,236 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IPU_H_
> +#define _IPU_H_
> +
> +#define IPU1_BASE      0x02600000
> +#define IPU2_BASE      0x02A00000
> +
> +#define IpuRead32(IPU_BASE, OFFSET) \
> +            MmioRead32((UINT32)((UINT8 *)IPU_BASE + OFFSET))
> +
> +#define IpuWrite32(IPU_BASE, OFFSET, VALUE) \
> +            MmioWrite32((UINT32)((UINT8 *)IPU_BASE + OFFSET), VALUE)
> +
> +#define DiRead32(DI_BASE, OFFSET) \
> +            MmioRead32((UINT32)((UINT8 *)DI_BASE + OFFSET))
> +
> +#define DiWrite32(DI_BASE, OFFSET, VALUE) \
> +            MmioWrite32((UINT32)((UINT8 *)DI_BASE + OFFSET), VALUE)
> +
> +// IPU Registers
> +#define IPU_IPU_CONF_OFFSET                     0x00000000
> +#define IPU_SISG_CTRL0_OFFSET                   0x00000004
> +#define IPU_SISG_CTRL1_OFFSET                   0x00000008
> +#define IPU_SISG_SET_OFFSET                     0x0000000C
> +#define IPU_SISG_CLR_OFFSET                     0x00000024
> +#define IPU_IPU_INT_CTRL_1_OFFSET               0x0000003C
> +#define IPU_IPU_INT_CTRL_2_OFFSET               0x00000040
> +#define IPU_IPU_INT_CTRL_3_OFFSET               0x00000044
> +#define IPU_IPU_INT_CTRL_4_OFFSET               0x00000048
> +#define IPU_IPU_INT_CTRL_5_OFFSET               0x0000004C
> +#define IPU_IPU_INT_CTRL_6_OFFSET               0x00000050
> +#define IPU_IPU_INT_CTRL_7_OFFSET               0x00000054
> +#define IPU_IPU_INT_CTRL_8_OFFSET               0x00000058
> +#define IPU_IPU_INT_CTRL_9_OFFSET               0x0000005C
> +#define IPU_IPU_INT_CTRL_10_OFFSET              0x00000060
> +#define IPU_IPU_INT_CTRL_11_OFFSET              0x00000064
> +#define IPU_IPU_INT_CTRL_12_OFFSET              0x00000068
> +#define IPU_IPU_INT_CTRL_13_OFFSET              0x0000006C
> +#define IPU_IPU_INT_CTRL_14_OFFSET              0x00000070
> +#define IPU_IPU_INT_CTRL_15_OFFSET              0x00000074
> +#define IPU_IPU_SDMA_EVENT_1_OFFSET             0x00000078
> +#define IPU_IPU_SDMA_EVENT_2_OFFSET             0x0000007C
> +#define IPU_IPU_SDMA_EVENT_3_OFFSET             0x00000080
> +#define IPU_IPU_SDMA_EVENT_4_OFFSET             0x00000084
> +#define IPU_IPU_SDMA_EVENT_7_OFFSET             0x00000088
> +#define IPU_IPU_SDMA_EVENT_8_OFFSET             0x0000008C
> +#define IPU_IPU_SDMA_EVENT_11_OFFSET            0x00000090
> +#define IPU_IPU_SDMA_EVENT_12_OFFSET            0x00000094
> +#define IPU_IPU_SDMA_EVENT_13_OFFSET            0x00000098
> +#define IPU_IPU_SDMA_EVENT_14_OFFSET            0x0000009C
> +#define IPU_IPU_SRM_PRI1_OFFSET                 0x000000A0
> +#define IPU_IPU_SRM_PRI2_OFFSET                 0x000000A4
> +#define IPU_IPU_FS_PROC_FLOW1_OFFSET            0x000000A8
> +#define IPU_IPU_FS_PROC_FLOW2_OFFSET            0x000000AC
> +#define IPU_IPU_FS_PROC_FLOW3_OFFSET            0x000000B0
> +#define IPU_IPU_FS_DISP_FLOW1_OFFSET            0x000000B4
> +#define IPU_IPU_FS_DISP_FLOW2_OFFSET            0x000000B8
> +#define IPU_IPU_SKIP_OFFSET                     0x000000BC
> +#define IPU_IPU_DISP_ALT_CONF_OFFSET            0x000000C0
> +#define IPU_IPU_DISP_GEN_OFFSET                 0x000000C4
> +#define IPU_IPU_DISP_ALT1_OFFSET                0x000000C8
> +#define IPU_IPU_DISP_ALT2_OFFSET                0x000000CC
> +#define IPU_IPU_DISP_ALT3_OFFSET                0x000000D0
> +#define IPU_IPU_DISP_ALT4_OFFSET                0x000000D4
> +#define IPU_IPU_SNOOP_OFFSET                    0x000000D8
> +#define IPU_IPU_MEM_RST_OFFSET                  0x000000DC
> +#define IPU_IPU_PM_OFFSET                       0x000000E0
> +#define IPU_IPU_GPR_OFFSET                      0x000000E4
> +#define IPU_IPU_INT_STAT_1_OFFSET               0x000000E8
> +#define IPU_IPU_INT_STAT_2_OFFSET               0x000000EC
> +#define IPU_IPU_INT_STAT_3_OFFSET               0x000000F0
> +#define IPU_IPU_INT_STAT_4_OFFSET               0x000000F4
> +#define IPU_IPU_INT_STAT_5_OFFSET               0x000000F8
> +#define IPU_IPU_INT_STAT_6_OFFSET               0x000000FC
> +#define IPU_IPU_INT_STAT_7_OFFSET               0x00000100
> +#define IPU_IPU_INT_STAT_8_OFFSET               0x00000104
> +#define IPU_IPU_INT_STAT_9_OFFSET               0x00000108
> +#define IPU_IPU_INT_STAT_10_OFFSET              0x0000010C
> +#define IPU_IPU_INT_STAT_11_OFFSET              0x00000110
> +#define IPU_IPU_INT_STAT_12_OFFSET              0x00000114
> +#define IPU_IPU_INT_STAT_13_OFFSET              0x00000118
> +#define IPU_IPU_INT_STAT_14_OFFSET              0x0000011C
> +#define IPU_IPU_INT_STAT_15_OFFSET              0x00000120
> +#define IPU_IPU_CUR_BUF_0_OFFSET                0x00000124
> +#define IPU_IPU_CUR_BUF_1_OFFSET                0x00000128
> +#define IPU_IPU_ALT_CUR_BUF_0_OFFSET            0x0000012C
> +#define IPU_IPU_ALT_CUR_BUF_1_OFFSET            0x00000130
> +#define IPU_IPU_SRM_STAT_OFFSET                 0x00000134
> +#define IPU_IPU_PROC_TASKS_STAT_OFFSET          0x00000138
> +#define IPU_IPU_DISP_TASKS_STAT_OFFSET          0x0000013C
> +#define IPU_IPU_CH_BUF0_RDY0_OFFSET             0x00000140
> +#define IPU_IPU_CH_BUF0_RDY1_OFFSET             0x00000144
> +#define IPU_IPU_CH_BUF1_RDY0_OFFSET             0x00000148
> +#define IPU_IPU_CH_BUF1_RDY1_OFFSET             0x0000014C
> +#define IPU_IPU_CH_DB_MODE_SEL0_OFFSET          0x00000150
> +#define IPU_IPU_CH_DB_MODE_SEL1_OFFSET          0x00000154
> +#define IPU_IPU_ALT_CH_BUF0_RDY0_OFFSET         0x00000158
> +#define IPU_IPU_ALT_CH_BUF0_RDY1_OFFSET         0x0000015C
> +#define IPU_IPU_ALT_CH_BUF1_RDY0_OFFSET         0x00000160
> +#define IPU_IPU_ALT_CH_BUF1_RDY1_OFFSET         0x00000164
> +#define IPU_IPU_ALT_CH_DB_MODE_SEL0_OFFSET      0x00000168
> +#define IPU_IPU_ALT_CH_DB_MODE_SEL1_OFFSET      0x0000016C
> +#define CSP_IPUV3_CPMEM_REGS_OFFSET             0x00100000
> +
> +// IPU DIx Registers
> +#define IPU_DIx_GENERAL_OFFSET                  0x00000000
> +#define IPU_DIx_BS_CLKGEN0_OFFSET               0x00000004
> +#define IPU_DIx_BS_CLKGEN1_OFFSET               0x00000008
> +#define IPU_DIx_SW_GEN0_1_OFFSET                0x0000000C
> +#define IPU_DIx_SW_GEN0_2_OFFSET                0x00000010
> +#define IPU_DIx_SW_GEN0_3_OFFSET                0x00000014
> +#define IPU_DIx_SW_GEN0_4_OFFSET                0x00000018
> +#define IPU_DIx_SW_GEN0_5_OFFSET                0x0000001C
> +#define IPU_DIx_SW_GEN0_6_OFFSET                0x00000020
> +#define IPU_DIx_SW_GEN0_7_OFFSET                0x00000024
> +#define IPU_DIx_SW_GEN0_8_OFFSET                0x00000028
> +#define IPU_DIx_SW_GEN0_9_OFFSET                0x0000002C
> +#define IPU_DIx_SW_GEN1_1_OFFSET                0x00000030
> +#define IPU_DIx_SW_GEN1_2_OFFSET                0x00000034
> +#define IPU_DIx_SW_GEN1_3_OFFSET                0x00000038
> +#define IPU_DIx_SW_GEN1_4_OFFSET                0x0000003C
> +#define IPU_DIx_SW_GEN1_5_OFFSET                0x00000040
> +#define IPU_DIx_SW_GEN1_6_OFFSET                0x00000044
> +#define IPU_DIx_SW_GEN1_7_OFFSET                0x00000048
> +#define IPU_DIx_SW_GEN1_8_OFFSET                0x0000004C
> +#define IPU_DIx_SW_GEN1_9_OFFSET                0x00000050
> +#define IPU_DIx_SYNC_AS_GEN_OFFSET              0x00000054
> +#define IPU_DIx_DW_GEN_OFFSET                   0x00000058
> +#define IPU_DIx_DW_SET0_OFFSET                  0x00000088
> +#define IPU_DIx_DW_SET1_OFFSET                  0x000000B8
> +#define IPU_DIx_DW_SET2_OFFSET                  0x000000E8
> +#define IPU_DIx_DW_SET3_OFFSET                  0x00000118
> +#define IPU_DIx_STP_REP_OFFSET                  0x00000148
> +#define IPU_DIx_STP_REP_9_OFFSET                0x00000158
> +#define IPU_DIx_SER_CONF_OFFSET                 0x0000015C
> +#define IPU_DIx_SSC_OFFSET                      0x00000160
> +#define IPU_DIx_POL_OFFSET                      0x00000164
> +#define IPU_DIx_AW0_OFFSET                      0x00000168
> +#define IPU_DIx_AW1_OFFSET                      0x0000016C
> +#define IPU_DIx_SCR_CONF_OFFSET                 0x00000170
> +#define IPU_DIx_STAT_OFFSET                     0x00000174
> +
> +// IPU IDMAC Registers
> +#define IPU_IDMAC_LOCK_EN_1                     0x00008024
> +#define IPU_IDMAC_LOCK_EN_2                     0x00008028
> +
> +// IPU DisplayInterface0 Registers
> +#define IPU_DISPLAY_INTERFACE_0_OFFSET          0x00040000
> +#define IPU_DI0_BS_CLKGEN0_OFFSET               0x00040004
> +#define IPU_DI0_BS_CLKGEN1_OFFSET               0x00040008
> +#define IPU_DI0_SW_GEN0_1_OFFSET                0x0004000C
> +#define IPU_DI0_SW_GEN0_2_OFFSET                0x00040010
> +#define IPU_DI0_SW_GEN0_3_OFFSET                0x00040014
> +#define IPU_DI0_SW_GEN0_4_OFFSET                0x00040018
> +#define IPU_DI0_SW_GEN0_5_OFFSET                0x0004001C
> +#define IPU_DI0_SW_GEN0_6_OFFSET                0x00040020
> +#define IPU_DI0_SW_GEN0_7_OFFSET                0x00040024
> +#define IPU_DI0_SW_GEN0_8_OFFSET                0x00040028
> +#define IPU_DI0_SW_GEN0_9_OFFSET                0x0004002C
> +#define IPU_DI0_SW_GEN1_1_OFFSET                0x00040030
> +#define IPU_DI0_SW_GEN1_2_OFFSET                0x00040034
> +#define IPU_DI0_SW_GEN1_3_OFFSET                0x00040038
> +#define IPU_DI0_SW_GEN1_4_OFFSET                0x0004003C
> +#define IPU_DI0_SW_GEN1_5_OFFSET                0x00040040
> +#define IPU_DI0_SW_GEN1_6_OFFSET                0x00040044
> +#define IPU_DI0_SW_GEN1_7_OFFSET                0x00040048
> +#define IPU_DI0_SW_GEN1_8_OFFSET                0x0004004C
> +#define IPU_DI0_SW_GEN1_9_OFFSET                0x00040050
> +#define IPU_DI0_SYNC_AS_GEN_OFFSET              0x00040054
> +#define IPU_DI0_DW_GEN_OFFSET                   0x00040058
> +#define IPU_DI0_DW_SET0_OFFSET                  0x00040088
> +#define IPU_DI0_DW_SET1_OFFSET                  0x000400B8
> +#define IPU_DI0_DW_SET2_OFFSET                  0x000400E8
> +#define IPU_DI0_DW_SET3_OFFSET                  0x00040118
> +#define IPU_DI0_STP_REP_OFFSET                  0x00040148
> +#define IPU_DI0_STP_REP_9_OFFSET                0x00040158
> +#define IPU_DI0_SER_CONF_OFFSET                 0x0004015C
> +#define IPU_DI0_SSC_OFFSET                      0x00040160
> +#define IPU_DI0_POL_OFFSET                      0x00040164
> +#define IPU_DI0_AW0_OFFSET                      0x00040168
> +#define IPU_DI0_AW1_OFFSET                      0x0004016C
> +#define IPU_DI0_SCR_CONF_OFFSET                 0x00040170
> +#define IPU_DI0_STAT_OFFSET                     0x00040174
> +
> +// IPU DisplayInterface1 Registers
> +#define IPU_DISPLAY_INTERFACE_1_OFFSET          0x00048000
> +#define IPU_DI1_BS_CLKGEN0_OFFSET               0x00048004
> +#define IPU_DI1_BS_CLKGEN1_OFFSET               0x00048008
> +#define IPU_DI1_SW_GEN0_1_OFFSET                0x0004800C
> +#define IPU_DI1_SW_GEN0_2_OFFSET                0x00048010
> +#define IPU_DI1_SW_GEN0_3_OFFSET                0x00048014
> +#define IPU_DI1_SW_GEN0_4_OFFSET                0x00048018
> +#define IPU_DI1_SW_GEN0_5_OFFSET                0x0004801C
> +#define IPU_DI1_SW_GEN0_6_OFFSET                0x00048020
> +#define IPU_DI1_SW_GEN0_7_OFFSET                0x00048024
> +#define IPU_DI1_SW_GEN0_8_OFFSET                0x00048028
> +#define IPU_DI1_SW_GEN0_9_OFFSET                0x0004802C
> +#define IPU_DI1_SW_GEN1_1_OFFSET                0x00048030
> +#define IPU_DI1_SW_GEN1_2_OFFSET                0x00048034
> +#define IPU_DI1_SW_GEN1_3_OFFSET                0x00048038
> +#define IPU_DI1_SW_GEN1_4_OFFSET                0x0004803C
> +#define IPU_DI1_SW_GEN1_5_OFFSET                0x00048040
> +#define IPU_DI1_SW_GEN1_6_OFFSET                0x00048044
> +#define IPU_DI1_SW_GEN1_7_OFFSET                0x00048048
> +#define IPU_DI1_SW_GEN1_8_OFFSET                0x0004804C
> +#define IPU_DI1_SW_GEN1_9_OFFSET                0x00048050
> +#define IPU_DI1_SYNC_AS_GEN_OFFSET              0x00048054
> +#define IPU_DI1_DW_GEN_OFFSET                   0x00048058
> +#define IPU_DI1_DW_SET0_OFFSET                  0x00048088
> +#define IPU_DI1_DW_SET1_OFFSET                  0x000480B8
> +#define IPU_DI1_DW_SET2_OFFSET                  0x000480E8
> +#define IPU_DI1_DW_SET3_OFFSET                  0x00048118
> +#define IPU_DI1_STP_REP_OFFSET                  0x00048148
> +#define IPU_DI1_STP_REP_9_OFFSET                0x00048158
> +#define IPU_DI1_SER_CONF_OFFSET                 0x0004815C
> +#define IPU_DI1_SSC_OFFSET                      0x00048160
> +#define IPU_DI1_POL_OFFSET                      0x00048164
> +#define IPU_DI1_AW0_OFFSET                      0x00048168
> +#define IPU_DI1_AW1_OFFSET                      0x0004816C
> +#define IPU_DI1_SCR_CONF_OFFSET                 0x00048170
> +#define IPU_DI1_STAT_OFFSET                     0x00048174
> +
> +#endif  /* _IPU_H_ */
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
> new file mode 100644
> index 000000000000..e6eb3b31bb07
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
> @@ -0,0 +1,93 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMXDisplay.h>
> +
> +#include "Display.h"
> +#include "Lvds.h"
> +#include "Edid.h"
> +
> +EFI_STATUS
> +InitLvds (
> +  IN  DISPLAY_CONTEXT   *DisplayContextPtr
> +  )
> +{
> +  DISPLAY_INTERFACE_CONTEXT   *pLvdsDisplayContext;
> +  EFI_STATUS                  Status;
> +  LDB_CTRL_REG                LdbCtrlReg;
> +
> +  Status = EFI_SUCCESS;
> +  pLvdsDisplayContext = &DisplayContextPtr->DiContext[Lvds0Display];
> +  ZeroMem (pLvdsDisplayContext, sizeof (*pLvdsDisplayContext));
> +
> +  pLvdsDisplayContext->MmioBasePtr = (VOID *)LDB_BASE;
> +  if (pLvdsDisplayContext->MmioBasePtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to map LDB register\n", __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +  // LVDS CH1 enabled, routed to DisplayInterface0; ipu_di01_vsync_active_low
> +  LdbCtrlReg.Reg = MmioRead32 ((UINT32)pLvdsDisplayContext->MmioBasePtr + LDB_CTRL);
> +  LdbCtrlReg.ch0_mode = 1;
> +  LdbCtrlReg.ch1_mode = 1;
> +  LdbCtrlReg.di0_vs_polarity = 1;
> +  LdbCtrlReg.di1_vs_polarity = 1;
> +  MmioWrite32 ((UINT32)pLvdsDisplayContext->MmioBasePtr + LDB_CTRL, LdbCtrlReg.Reg);
> +
> +  // No EDID available
> +  pLvdsDisplayContext->EdidDataSize = 0;
> +
> +  Status = GetPreferredTiming (
> +             pLvdsDisplayContext->EdidData,
> +             pLvdsDisplayContext->EdidDataSize,
> +             &pLvdsDisplayContext->PreferredTiming
> +           );
> +  if (Status != EFI_SUCCESS) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to retrieve LVDS preferred timing\n",
> +      __FUNCTION__));
> +    goto Exit;
> +  }
> +
> +Exit:
> +  return Status;
> +}
> +
> +EFI_STATUS
> +SetLvdsPower (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  BOOLEAN                     PowerState
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_STATUS
> +SetLvdsDisplay (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *pLvdsDisplayContext,
> +  IN  DISPLAY_TIMING              *Timings
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
> new file mode 100644
> index 000000000000..b45201fb45fc
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
> @@ -0,0 +1,67 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _LVDS_H_
> +#define _LVDS_H_

IMX_ prefix please.

> +
> +// LDB Register Base Address
> +#define LDB_BASE 0x020E0008
> +
> +// LDB Control Register offset
> +#define LDB_CTRL    0
> +
> +#pragma pack(push, 1)
> +
> +// LDB_CTRL_REG
> +typedef union {
> +  struct {
> +    UINT32 ch0_mode : 2;
> +    UINT32 ch1_mode : 2;
> +    UINT32 split_mode_en : 1;
> +    UINT32 data_width_ch0 : 1;
> +    UINT32 bit_mapping_ch0 : 1;
> +    UINT32 data_width_ch1 : 1;
> +    UINT32 bit_mapping_ch1 : 1;
> +    UINT32 di0_vs_polarity : 1;
> +    UINT32 di1_vs_polarity : 1;
> +    UINT32 Reserved11_15 : 5;
> +    UINT32 lvds_clk_shift : 3;
> +    UINT32 Reserved19 : 1;
> +    UINT32 counter_reset_val : 2;
> +    UINT32 Reserved22_31 : 10;

Please rename all struct members to CamelCase.

/
    Leif

> +  };
> +  UINT32 Reg;
> +}  LDB_CTRL_REG;
> +
> +#pragma pack(pop)
> +
> +EFI_STATUS
> +InitLvds (
> +  IN  DISPLAY_CONTEXT   *DisplayContextPtr
> +  );
> +
> +EFI_STATUS
> +SetLvdsPower (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *HdmiDisplayContextPtr,
> +  IN  BOOLEAN                     PowerState
> +  );
> +
> +EFI_STATUS
> +SetLvdsDisplay (
> +  IN  DISPLAY_INTERFACE_CONTEXT   *LvdsDisplayContextPtr,
> +  IN  DISPLAY_TIMING              *Timings
> +  );
> +
> +#endif  /* _LVDS_H_ */
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 23/27] Silicon/NXP: Add i.MX6 Smbios Driver
  2018-09-21  8:26 ` [PATCH edk2-platforms 23/27] Silicon/NXP: Add i.MX6 Smbios Driver Chris Co
@ 2018-12-14 23:07   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 23:07 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:15AM +0000, Chris Co wrote:
> This adds support populating the SMBIOS tables on an i.MX6 SoC.
> Platforms just need to define the relevant PCDs in their dsc file and
> this driver will fill out the SMBIOS table structures.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c   | 1774 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h   |   44 +
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf |   84 +
>  3 files changed, 1902 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
> new file mode 100644
> index 000000000000..93c56dec254b
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
> @@ -0,0 +1,1774 @@
> +/** @file
> +
> +  Static SMBIOS Table for the SolidRun HummingBoard-Edge iMX6 Quad platform
> +  Derived from EmulatorPkg package
> +
> +  Note SMBIOS 2.7.1 Required structures:
> +    BIOS Information (Type 0)
> +    System Information (Type 1)
> +    Board Information (Type 2)
> +    System Enclosure (Type 3)
> +    Processor Information (Type 4) - CPU Driver
> +    Cache Information (Type 7) - For cache that is external to processor
> +    Physical Memory Array (Type 16)
> +    Memory Device (Type 17) - For each socketed system-memory Device
> +    Memory Array Mapped Address (Type 19) - One per contiguous block per Physical Memroy Array
> +    System Boot Information (Type 32)
> +
> +  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2012, Apple Inc. All rights reserved.<BR>
> +  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
> +  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
> +  Copyright (c) 2015, ARM Limited. All rights reserved.
> +  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Guid/SmBios.h>
> +
> +#include <IndustryStandard/SmBios.h>
> +
> +#include <Library/ArmLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiLib.h>
> +
> +#include <Protocol/Smbios.h>
> +
> +#include "PlatformSmbiosDxe.h"
> +
> +// Default SMBIOS Tables for i.MX6
> +SMBIOS_TABLE_TYPE0 mBiosInfoType0 = {
> +  {
> +    EFI_SMBIOS_TYPE_BIOS_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE0),
> +    SMBIOS_HANDLE_PI_RESERVED
> +  },
> +  1,                    // Vendor String
> +  2,                    // BiosVersion String
> +  0xE000,               // BiosSegment
> +  3,                    // BiosReleaseDate String
> +  (FixedPcdGet32 (PcdFdSize) - 1) / SIZE_64KB, // BiosSize
> +  {       // BiosCharacteristics
> +    0,    //  Reserved                          :2;
> +    0,    //  Unknown                           :1;
> +    0,    //  BiosCharacteristicsNotSupported   :1;
> +    0,    //  IsaIsSupported                    :1;
> +    0,    //  McaIsSupported                    :1;
> +    0,    //  EisaIsSupported                   :1;
> +    1,    //  PciIsSupported                    :1;
> +    0,    //  PcmciaIsSupported                 :1;
> +    0,    //  PlugAndPlayIsSupported            :1;
> +    0,    //  ApmIsSupported                    :1;
> +    1,    //  BiosIsUpgradable                  :1;
> +    0,    //  BiosShadowingAllowed              :1;
> +    0,    //  VlVesaIsSupported                 :1;
> +    0,    //  EscdSupportIsAvailable            :1;
> +    0,    //  BootFromCdIsSupported             :1;
> +    1,    //  SelectableBootIsSupported         :1;
> +    0,    //  RomBiosIsSocketed                 :1;
> +    0,    //  BootFromPcmciaIsSupported         :1;
> +    0,    //  EDDSpecificationIsSupported       :1;
> +    0,    //  JapaneseNecFloppyIsSupported      :1;
> +    0,    //  JapaneseToshibaFloppyIsSupported  :1;
> +    0,    //  Floppy525_360IsSupported          :1;
> +    0,    //  Floppy525_12IsSupported           :1;
> +    0,    //  Floppy35_720IsSupported           :1;
> +    0,    //  Floppy35_288IsSupported           :1;
> +    0,    //  PrintScreenIsSupported            :1;
> +    0,    //  Keyboard8042IsSupported           :1;
> +    0,    //  SerialIsSupported                 :1;
> +    0,    //  PrinterIsSupported                :1;
> +    0,    //  CgaMonoIsSupported                :1;
> +    0,    //  NecPc98                           :1;
> +    0     //  ReservedForVendor                 :32;
> +  },
> +  {       // BIOSCharacteristicsExtensionBytes[]
> +    0x01, //  AcpiIsSupported                   :1;
> +          //  UsbLegacyIsSupported              :1;
> +          //  AgpIsSupported                    :1;
> +          //  I2OBootIsSupported                :1;
> +          //  Ls120BootIsSupported              :1;
> +          //  AtapiZipDriveBootIsSupported      :1;
> +          //  Boot1394IsSupported               :1;
> +          //  SmartBatteryIsSupported           :1;
> +    0x0C, //  BiosBootSpecIsSupported           :1;
> +          //  FunctionKeyNetworkBootIsSupported :1;
> +          //  TargetContentDistributionEnabled  :1;
> +          //  UefiSpecificationSupported        :1;
> +          //  VirtualMachineSupported           :1;
> +          //  ExtensionByte2Reserved            :3;
> +  },
> +  FixedPcdGet32 (PcdFirmwareRevision) >> 16, // SystemBiosMajorRelease
> +  FixedPcdGet32 (PcdFirmwareRevision) & 0xff, // SystemBiosMinorRelease
> +  0xFF,   // EmbeddedControllerFirmwareMajorRelease
> +  0xFF,   // EmbeddedControllerFirmwareMinorRelease
> +};
> +
> +SMBIOS_TABLE_TYPE1 mSysInfoType1 = {
> +  {
> +    EFI_SMBIOS_TYPE_SYSTEM_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE1),
> +    SMBIOS_HANDLE_PI_RESERVED
> +  },
> +  1,    // Manufacturer String
> +  2,    // ProductName String
> +  3,    // Version String
> +  4,    // SerialNumber String
> +  { 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } },
> +  SystemWakeupTypePowerSwitch, // WakeUp Type
> +  5,    // SKUNumber String
> +  6,    // Family String
> +};
> +
> +SMBIOS_TABLE_TYPE2 mBoardInfoType2 = {
> +  {
> +    EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE2),
> +    SMBIOS_HANDLE_BOARD
> +  },
> +  1,      // Manufacturer String
> +  2,      // ProductName String
> +  3,      // Version String
> +  4,      // SerialNumber String
> +  5,      // AssetTag String
> +  {       // FeatureFlag
> +    1,    //  Motherboard           :1;
> +    0,    //  RequiresDaughterCard  :1;
> +    0,    //  Removable             :1;
> +    0,    //  Replaceable           :1;
> +    0,    //  HotSwappable          :1;
> +    0,    //  Reserved              :3;
> +  },
> +  6,                        // LocationInChassis String
> +  SMBIOS_HANDLE_CHASSIS,    // ChassisHandle;
> +  BaseBoardTypeMotherBoard, // BoardType;
> +  1,                        // NumberOfContainedObjectHandles;
> +  { SMBIOS_HANDLE_PROCESSOR } // ContainedObjectHandles[1];
> +};
> +
> +SMBIOS_TABLE_TYPE3 mEnclosureInfoType3 = {
> +  {
> +    EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE,
> +    sizeof (SMBIOS_TABLE_TYPE3),
> +    SMBIOS_HANDLE_CHASSIS
> +  },
> +  1,                          // Manufacturer String
> +  MiscChassisTypeOther,       // Type;
> +  2,                          // Version String
> +  3,                          // SerialNumber String
> +  4,                          // AssetTag String
> +  ChassisStateSafe,           // BootupState;
> +  ChassisStateSafe,           // PowerSupplyState;
> +  ChassisStateSafe,           // ThermalState;
> +  ChassisSecurityStatusNone,  // SecurityStatus;
> +  { 0, 0, 0, 0 },             // OemDefined[4];
> +  0,                          // Height;
> +  0,                          // NumberofPowerCords;
> +  0,                          // ContainedElementCount;
> +  0,                          // ContainedElementRecordLength;
> +  { { 0 } },                  // ContainedElements[1];
> +};
> +
> +SMBIOS_TABLE_TYPE4 mProcessorInfoType4 = {
> +  {
> +    EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE4),
> +    SMBIOS_HANDLE_PROCESSOR
> +  },
> +  1,                                // Socket String;
> +  CentralProcessor,                 // ProcessorType;
> +  ProcessorFamilyIndicatorFamily2,  // ProcessorFamily;
> +  2,                                // ProcessorManufacture String;
> +  {{0,},{0.}}, // ProcessorId;
> +  3,      // ProcessorVersion String;
> +  {       // Voltage;
> +    1,    // ProcessorVoltageCapability5V        :1;
> +    1,    // ProcessorVoltageCapability3_3V      :1;
> +    1,    // ProcessorVoltageCapability2_9V      :1;
> +    0,    // ProcessorVoltageCapabilityReserved  :1;
> +    0,    // ProcessorVoltageReserved            :3;
> +    0     // ProcessorVoltageIndicateLegacy      :1;
> +  },
> +  0,                      // ExternalClock;
> +  0,                      // MaxSpeed;
> +  0,                      // CurrentSpeed;
> +  0x41,                   // Status;
> +  ProcessorUpgradeOther,  // ProcessorUpgrade;
> +  SMBIOS_HANDLE_L1I,      // L1CacheHandle;
> +  SMBIOS_HANDLE_L2U,      // L2CacheHandle;
> +  0xFFFF,                 // L3CacheHandle;
> +  4,                      // SerialNumber;
> +  5,                      // AssetTag;
> +  6,                      // PartNumber;
> +  0,                      // CoreCount;
> +  0,                      // EnabledCoreCount;
> +  0,                      // ThreadCount;
> +  0,                      // ProcessorCharacteristics;
> +  ProcessorFamilyARMv7,   // ProcessorFamily2;
> +};
> +
> +SMBIOS_TABLE_TYPE7 mCacheInfoType7L1I = {
> +  {
> +    EFI_SMBIOS_TYPE_CACHE_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE7),
> +    SMBIOS_HANDLE_L1I
> +  },
> +  1,      // SocketDesignation String
> +  0x0180, // Cache Configuration
> +  0x0020, // Maximum Size 32k
> +  0x0020, // Install Size 32k
> +  {       // Supported SRAM Type
> +    0,    //Other             :1
> +    0,    //Unknown           :1
> +    0,    //NonBurst          :1
> +    1,    //Burst             :1
> +    0,    //PiplelineBurst    :1
> +    1,    //Synchronous       :1
> +    0,    //Asynchronous      :1
> +    0     //Reserved          :9
> +  },
> +  {       // Current SRAM Type
> +    0,    //Other             :1
> +    0,    //Unknown           :1
> +    0,    //NonBurst          :1
> +    1,    //Burst             :1
> +    0,    //PiplelineBurst    :1
> +    1,    //Synchronous       :1
> +    0,    //Asynchronous      :1
> +    0     //Reserved          :9
> +  },
> +  0,                      // Cache Speed unknown
> +  CacheErrorMultiBit,     // Error Correction Multi
> +  CacheTypeInstruction,   // System Cache Type
> +  CacheAssociativity2Way  // Associativity
> +};
> +
> +SMBIOS_TABLE_TYPE7 mCacheInfoType7L1D = {
> +  {
> +    EFI_SMBIOS_TYPE_CACHE_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE7),
> +    SMBIOS_HANDLE_L1D
> +  },
> +  1,      // SocketDesignation String
> +  0x0180, // Cache Configuration
> +  0x0020, // Maximum Size 32k
> +  0x0020, // Install Size 32k
> +  {       // Supported SRAM Type
> +    0,    //Other             :1
> +    0,    //Unknown           :1
> +    0,    //NonBurst          :1
> +    1,    //Burst             :1
> +    0,    //PiplelineBurst    :1
> +    1,    //Synchronous       :1
> +    0,    //Asynchronous      :1
> +    0     //Reserved          :9
> +  },
> +  {       // Current SRAM Type
> +    0,    //Other             :1
> +    0,    //Unknown           :1
> +    0,    //NonBurst          :1
> +    1,    //Burst             :1
> +    0,    //PiplelineBurst    :1
> +    1,    //Synchronous       :1
> +    0,    //Asynchronous      :1
> +    0     //Reserved          :9
> +  },
> +  0,                      // Cache Speed unknown
> +  CacheErrorMultiBit,     // Error Correction Multi
> +  CacheTypeData,          // System Cache Type
> +  CacheAssociativity2Way  // Associativity
> +};
> +
> +SMBIOS_TABLE_TYPE7 mCacheInfoType7L2U = {
> +  {
> +    EFI_SMBIOS_TYPE_CACHE_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE7),
> +    SMBIOS_HANDLE_L2U
> +  },
> +  1,      // SocketDesignation String
> +  0x0181, // Cache Configuration
> +  0,      // Maximum Size
> +  0,      // Install Size
> +  {       // Supported SRAM Type
> +    0,    //Other             :1
> +    0,    //Unknown           :1
> +    0,    //NonBurst          :1
> +    1,    //Burst             :1
> +    0,    //PiplelineBurst    :1
> +    1,    //Synchronous       :1
> +    0,    //Asynchronous      :1
> +    0     //Reserved          :9
> +  },
> +  {       // Current SRAM Type
> +    0,    //Other             :1
> +    0,    //Unknown           :1
> +    0,    //NonBurst          :1
> +    1,    //Burst             :1
> +    0,    //PiplelineBurst    :1
> +    1,    //Synchronous       :1
> +    0,    //Asynchronous      :1
> +    0     //Reserved          :9
> +  },
> +  0,                      // Cache Speed unknown
> +  CacheErrorMultiBit,     // Error Correction Multi
> +  CacheTypeUnified,       // System Cache Type
> +  CacheAssociativity2Way  // Associativity
> +};
> +
> +SMBIOS_TABLE_TYPE16 mPhysicalMemoryArrayInfoType16 = {
> +  {
> +    EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY,
> +    sizeof (SMBIOS_TABLE_TYPE16),
> +    SMBIOS_HANDLE_MEMORY_ARRAY
> +  },
> +  MemoryArrayLocationSystemBoard, // Location;
> +  MemoryArrayUseSystemMemory,     // Use;
> +  MemoryErrorCorrectionNone,      // MemoryErrorCorrection;
> +  0x80000000,                     // MaximumCapacity
> +  0xFFFE,                         // MemoryErrorInformationHandle;
> +  1,                              // NumberOfMemoryDevices;
> +  0x80000000ULL,                  // ExtendedMaximumCapacity
> +};
> +
> +SMBIOS_TABLE_TYPE17 mMemoryDeviceInfoType17 = {
> +  {
> +    EFI_SMBIOS_TYPE_MEMORY_DEVICE,
> +    sizeof (SMBIOS_TABLE_TYPE17),
> +    SMBIOS_HANDLE_MEMORY_DEVICE
> +  },
> +  SMBIOS_HANDLE_MEMORY_ARRAY, // MemoryArrayHandle;
> +  0xFFFE,     // MemoryErrorInformationHandle;
> +  0xFFFF,     // TotalWidth;
> +  0xFFFF,     // DataWidth;
> +  0xFFFF,     // Size; When bit 15 is 0: Size in MB
> +              // When bit 15 is 1: Size in KB, and continues in ExtendedSize
> +  MemoryFormFactorRowOfChips,  // FormFactor;
> +  0,                        // DeviceSet;
> +  1,                        // DeviceLocator String
> +  2,                        // BankLocator String
> +  MemoryTypeDdr3,           // MemoryType;
> +  {           // TypeDetail;
> +    0,        // Reserved        :1;
> +    0,        // Other           :1;
> +    0,        // Unknown         :1;
> +    0,        // FastPaged       :1;
> +    0,        // StaticColumn    :1;
> +    0,        // PseudoStatic    :1;
> +    0,        // Rambus          :1;
> +    0,        // Synchronous     :1;
> +    0,        // Cmos            :1;
> +    0,        // Edo             :1;
> +    0,        // WindowDram      :1;
> +    0,        // CacheDram       :1;
> +    0,        // Nonvolatile     :1;
> +    0,        // Registered      :1;
> +    1,        // Unbuffered      :1;
> +    0,        // Reserved1       :1;
> +  },
> +  0,          // Speed;
> +  0,          // Manufacturer String
> +  0,          // SerialNumber String
> +  0,          // AssetTag String
> +  0,          // PartNumber String
> +  0,          // Attributes;
> +  0,          // ExtendedSize;
> +  0,          // ConfiguredMemoryClockSpeed;
> +};
> +
> +SMBIOS_TABLE_TYPE19 mMemoryArrayMappedInfoType19 = {
> +  {
> +    EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS,
> +    sizeof (SMBIOS_TABLE_TYPE19),
> +    SMBIOS_HANDLE_PI_RESERVED
> +  },
> +  0xFFFFFFFF, // StartingAddress;
> +  0xFFFFFFFF, // EndingAddress;
> +  SMBIOS_HANDLE_MEMORY_ARRAY, // MemoryArrayHandle;
> +  1,          // PartitionWidth;
> +  0xFFFFFFFF, // ExtendedStartingAddress;
> +  0xFFFFFFFF, // ExtendedEndingAddress;
> +};
> +
> +SMBIOS_TABLE_TYPE32 mBootInfoType32 = {
> +  {
> +    EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION,
> +    sizeof (SMBIOS_TABLE_TYPE32),
> +    SMBIOS_HANDLE_PI_RESERVED
> +  },
> +  { 0, 0, 0, 0, 0, 0 },         // Reserved[6];
> +  BootInformationStatusNoError  // BootStatus
> +};
> +
> +struct MonthDescription {
> +  CONST CHAR8* MonthStr;
> +  UINT32    MonthInt;
> +} gMonthDescription[] = {
> +  { "Jan", 1 },
> +  { "Feb", 2 },
> +  { "Mar", 3 },
> +  { "Apr", 4 },
> +  { "May", 5 },
> +  { "Jun", 6 },
> +  { "Jul", 7 },
> +  { "Aug", 8 },
> +  { "Sep", 9 },
> +  { "Oct", 10 },
> +  { "Nov", 11 },
> +  { "Dec", 12 },
> +  { "???", 1 },  // Use 1 as default month
> +};
> +
> +EFI_STATUS
> +LogSmbiosData (
> +  IN       UINT8                      *Buffer,
> +  IN  OUT  EFI_SMBIOS_HANDLE          *SmbiosHandle
> +  )
> +{
> +  EFI_STATUS         Status;
> +  EFI_SMBIOS_PROTOCOL       *Smbios;
> +
> +  *SmbiosHandle = ((EFI_SMBIOS_TABLE_HEADER *)Buffer)->Handle;
> +  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = Smbios->Add (
> +                    Smbios,
> +                    NULL,
> +                    SmbiosHandle,
> +                    (EFI_SMBIOS_TABLE_HEADER *)Buffer
> +                    );
> +
> +  return Status;
> +}
> +
> +VOID
> +GetReleaseTime (
> +  EFI_TIME *Time
> +  )
> +{
> +  CONST CHAR8      *ReleaseDate = __DATE__;
> +  CONST CHAR8      *ReleaseTime = __TIME__;
> +  UINTN            i;
> +
> +  for (i = 0; i < 12; i++) {
> +    if (0 == AsciiStrnCmp (ReleaseDate, gMonthDescription[i].MonthStr, 3)) {

No Jeopardy comparisons, please.

> +      break;
> +    }
> +  }
> +  Time->Month = gMonthDescription[i].MonthInt;
> +  Time->Day = AsciiStrDecimalToUintn (ReleaseDate + 4);
> +  Time->Year = AsciiStrDecimalToUintn (ReleaseDate + 7);
> +  Time->Hour = AsciiStrDecimalToUintn (ReleaseTime);
> +  Time->Minute = AsciiStrDecimalToUintn (ReleaseTime + 3);
> +  Time->Second = AsciiStrDecimalToUintn (ReleaseTime + 6);

I'm also not generally a fan of the fixed-position string parsing.
Can you add some comments so it's clear which values are being
extracted?

> +
> +  return;
> +}
> +
> +UINT64
> +GetImx6SerialNumber (
> +  VOID
> +  )
> +{
> +  UINT64 ProcessorSerialNumber;
> +
> +  ProcessorSerialNumber = ((UINT64)MmioRead32 (OCOTP_BANK_0_WORD_2)) << 32;
> +  ProcessorSerialNumber |=(UINT64)MmioRead32 (OCOTP_BANK_0_WORD_1);

Space after =.

> +
> +  DEBUG ((DEBUG_INFO, "iMX6 Serial Number %08X%08Xh \r\n",
> +          (UINT32) (ProcessorSerialNumber >> 32), (UINT32)ProcessorSerialNumber));
> +  return ProcessorSerialNumber;
> +}

On the whole, another patch that's hard to review manually.

Have you run the https://wiki.ubuntu.com/FirmwareTestSuite/ smbios tests?

/
    Leif


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 24/27] Silicon/NXP: Add i.MX6 common dsc and fdf files
  2018-09-21  8:26 ` [PATCH edk2-platforms 24/27] Silicon/NXP: Add i.MX6 common dsc and fdf files Chris Co
@ 2018-12-14 23:36   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-14 23:36 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:16AM +0000, Chris Co wrote:
> This adds the common dsc and fdf definitions for NXP i.MX6 platforms.
> Platform dsc definitions will define $(BOARD_NAME), $(IMX_FAMILY),
> $(IMX_CHIP_TYPE), $(DRAM_SIZE), and $(BOARD_DIR) to indicate
> i.MX SoC family and board-specific configurations.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc | 897 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc | 287 +++++++
>  Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc | 148 ++++

I would prefer for these to be named .dsc.inc and .fdf.inc.

>  3 files changed, 1332 insertions(+)
> 
> diff --git a/Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc b/Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
> new file mode 100644
> index 000000000000..743a022c2b4a
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
> @@ -0,0 +1,897 @@
> +#
> +# iMX6 Quad and Dual SOM platforms common description
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +
> +################################################################################
> +#
> +# [Defines] Section
> +#
> +################################################################################
> +[Defines]
> +  PLATFORM_NAME                  = iMX6
> +  PLATFORM_GUID                  = F01954EE-8AC4-45BC-80E5-511EAE64C38C
> +  PLATFORM_VERSION               = 0.1
> +  DSC_SPECIFICATION              = 0x00010019
> +  OUTPUT_DIRECTORY               = Build/$(BOARD_NAME)
> +  SUPPORTED_ARCHITECTURES        = ARM
> +  BUILD_TARGETS                  = DEBUG|RELEASE

Please add NOOPT as well.

> +  SKUID_IDENTIFIER               = DEFAULT
> +
> +!include Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
> +
> +################################################################################
> +#
> +# [BuildOptions] Section
> +#
> +################################################################################
> +[BuildOptions]
> +  GCC:*_*_*_CC_FLAGS = -D$(BOARD_NAME) -DCPU_$(IMX_FAMILY) -DSOCTYPE_$(IMX_CHIP_TYPE) -Wno-unused-local-typedefs

Why the disabled warning?

> +  GCC:*_*_*_OBJCOPY_PATH = noop
> +  GCC:*_*_*_SYMRENAME_PATH = noop

Hmm?

> +  *_*_*_ASL_PATH == asl.exe
> +  *_*_*_ASL_FLAGS == /MsftInternal
> +  *_*_*_ASL_OUTFLAGS == /Fo=
> +
> +# CPU_* compiler flag is used to select constants for iMX6.h
> +
> +[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLICATION]
> +  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
> +
> +[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
> +  GCC:*_*_ARM_DLINK_FLAGS = -z common-page-size=0x1000

You can probably drop the common-page-size overrides now, we've
changed the toolchain profiles.

> +
> +################################################################################
> +#
> +# [LibraryClasses] Sections
> +#
> +# When parsing the DSC file, the precedence rules will followed.
> +#  1. If a Library Class Instance (INF) is specified in the EDK II [Components] section
> +#     (INF files <LibraryClasses> sub-section,) then it will be used.
> +#  2. If not specified in the [Components] section, then the Library Class Instance that is
> +#     defined in the [LibraryClasses.$(ARCH).$(MODULE_TYPE)] section will be used.
> +#  3. If not specified in the [LibraryClasses.$(ARCH).$(MODULE_TYPE)] section, then
> +#     the Library Class Instance that is defined in the
> +#     [LibraryClasses.Common.$(MODULE_TYPE)] section will be used.
> +#  4. If not specified in the [LibraryClasses.Common.$(MODULE_TYPE)] section, then
> +#     the Library Class Instance that is defined in the [LibraryClasses.$(ARCH)] section
> +#     will be used.
> +#  5. If not specified in the [LibraryClasses.$(ARCH)] section, then the Library Class
> +#     Instance that is defined in the [LibraryClasses] Section or
> +#     [LibraryClasses.Common] section will be used.
> +#  6. It is an error if it has not been specified in one of the above sections
> +#
> +################################################################################
> +
> +[LibraryClasses.common]
> +  #
> +  # CPU and Timing
> +  #
> +  ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
> +  ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
> +  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
> +  ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
> +  CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
> +  ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
> +  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
> +  RealTimeClockLib|Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
> +  DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
> +  CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf
> +  TimerLib|Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
> +
> +  #
> +  # Memory
> +  #
> +  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
> +  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
> +  MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
> +  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
> +  DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf
> +  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> +
> +  #
> +  # Platform
> +  #
> +  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
> +  PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
> +  ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
> +  EfiResetSystemLib|ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf
> +
> +  #
> +  # Peripherals
> +  #
> +  UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
> +  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
> +  NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
> +
> +  #
> +  # UEFI Services and Runtime
> +  #
> +  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
> +  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
> +  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
> +  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
> +  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
> +  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
> +  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
> +
> +  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
> +  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
> +
> +  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
> +  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
> +
> +  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
> +
> +  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
> +
> +  #
> +  # Human Interface Infrastructure (HII)
> +  #
> +  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
> +  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
> +
> +  #
> +  # BDS
> +  #
> +  BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
> +  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
> +  PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> +  FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
> +  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
> +
> +  #
> +  # Shell
> +  #
> +  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
> +  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
> +
> +  #
> +  # Serial, Console and Debugging
> +  #
> +  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
> +  SerialPortLib|Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
> +  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
> +
> +  # Enable debug prints in both release and debug builds
> +  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
> +  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
> +  #
> +  # The Standard IO window in the debugger will show load and unload events for symbols.
> +  #
> +!if $(CONFIG_DUMP_SYMBOL_INFO) == TRUE
> +  PeCoffExtraActionLib|Platform/Microsoft/Library/LauterbachPeCoffExtraActionLib/LauterbachPeCoffExtraActionLib.inf
> +!else
> +  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
> +!endif
> +
> +  #
> +  # Display
> +  #
> +  iMXDisplayLib|Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
> +
> +  #
> +  # Security
> +  #
> +  TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
> +  Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
> +  Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
> +
> +  #
> +  # iMX6 Specifics
> +  #
> +  iMXIoMuxLib|Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
> +!if $(IMX_FAMILY) == IMX6SX
> +  iMX6ClkPwrLib|Silicon/NXP/iMX6Pkg/Library/iMX6SxClkPwrLib/iMX6SxClkPwrLib.inf
> +!else
> +  iMX6ClkPwrLib|Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
> +!endif
> +  iMX6UsbPhyLib|Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
> +
> +[LibraryClasses.ARM]
> +  #
> +  # It is not possible to prevent the ARM compiler for generic intrinsic functions.
> +  # This library provides the instrinsic functions generate by a given compiler.
> +  # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
> +  #
> +  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
> +  NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
> +
> +[LibraryClasses.common.SEC]
> +  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> +  ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
> +  ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf
> +  ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
> +  ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
> +  HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
> +  LzmaDecompressLib|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
> +  MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf
> +  MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
> +  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
> +  PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
> +  PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
> +  PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
> +  PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
> +  DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLibBase.inf
> +
> +[LibraryClasses.common.PEI_CORE]
> +  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
> +  ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
> +  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
> +  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
> +
> +[LibraryClasses.common.DXE_CORE]
> +  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
> +  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
> +  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> +  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
> +  PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
> +
> +[LibraryClasses.common.DXE_DRIVER]
> +  ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
> +  ArmGicArchLib|ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
> +  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
> +  DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf
> +  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
> +  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
> +  PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> +  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
> +  ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
> +
> +!if $(CONFIG_OPTEE) == TRUE
> +  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> +  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> +  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +  HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
> +  Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
> +!endif
> +
> +[LibraryClasses.common.UEFI_APPLICATION]
> +  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
> +  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
> +  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
> +  UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
> +  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
> +  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
> +  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +  ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
> +
> +!if $(CONFIG_OPTEE) == TRUE
> +  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> +!endif
> +
> +[LibraryClasses.common.UEFI_DRIVER]
> +  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
> +  UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
> +  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
> +  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +
> +[LibraryClasses.common.DXE_RUNTIME_DRIVER]
> +  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> +  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
> +  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
> +  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
> +  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
> +
> +!if $(CONFIG_OPTEE) == TRUE
> +!if $(CONFIG_MEASURED_BOOT) == TRUE
> +  TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
> +!endif
> +!endif
> +
> +################################################################################
> +#
> +# PCD Sections
> +#
> +################################################################################
> +
> +########################
> +#
> +# ArmPkg PCDs
> +#
> +########################
> +[PcdsFeatureFlag.common]
> +  #
> +  # Use the Vector Table location in CpuDxe. We will not copy the Vector Table at
> +  # PcdCpuVectorBaseAddress
> +  #
> +  gArmTokenSpaceGuid.PcdRelocateVectorTable|FALSE

Don't think that one does anything anymore.

> +
> +[PcdsFixedAtBuild.common]
> +  gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE

Nor that one.

> +  gArmTokenSpaceGuid.PcdVFPEnabled|1
> +
> +  #
> +  # ARM General Interrupt Controller settings
> +  #
> +  gArmTokenSpaceGuid.PcdGicDistributorBase|0x00A01000
> +  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x00A00100
> +  gArmTokenSpaceGuid.PcdArmPrimaryCore|0x000
> +
> +  #
> +  # ARM L2x0 PCDs
> +  #
> +  #gArmTokenSpaceGuid.PcdL2x0ControllerBase|0x00A02000

Blimey, there's a blast from the past.
Please just delete rather than commenting out.

> +
> +  #
> +  # GPT Timer Frequency
> +  # Set to 1KHz, which equals to 1us resolution
> +  #
> +  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|1000000
> +
> +########################
> +#
> +# ArmPlatformPkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +  # Size of the region used by UEFI in permanent memory (Reserved 16MB)
> +  gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x01000000
> +
> +!if $(IMX_FAMILY) == IMX6SX
> +  #
> +  # Refer to the detailed memory map at OpteeClientPkg PCDs section below
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryStartAddress|0x80000000
> +  gArmTokenSpaceGuid.PcdSystemMemoryBase|0x829D4000
> +  !if $(DRAM_SIZE) == DRAM_512MB
> +  #
> +  # Board DDR starts at 0x80000000 and ends 0x9FFF0000 (512MB)
> +  # SystemMemorySize is 0x9FFF0000 - PcdSystemMemoryBase
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x9FFF0000
> +  gArmTokenSpaceGuid.PcdSystemMemorySize|0x1D61C000
> +  !elseif $(DRAM_SIZE) == DRAM_1GB
> +  #
> +  # Board DDR starts at 0x80000000 and ends 0xBFFF0000 (1GB)
> +  # SystemMemorySize is 0xBFFF0000 - PcdSystemMemoryBase
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0xBFFF0000
> +  gArmTokenSpaceGuid.PcdSystemMemorySize|0x3D61C000
> +  !else
> +  #
> +  # Board DDR starts at 0x80000000 and ends 0xFFFF0000 (2GB)
> +  # SystemMemorySize is 0xFFFF0000 - PcdSystemMemoryBase
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0xFFFF0000
> +  gArmTokenSpaceGuid.PcdSystemMemorySize|0x7D61C000
> +  !endif
> +!else
> +  giMX6TokenSpaceGuid.PcdMemoryStartAddress|0x10000000
> +  gArmTokenSpaceGuid.PcdSystemMemoryBase|0x12A00000
> +
> +  !if $(DRAM_SIZE) == DRAM_512MB
> +  #
> +  # Board DDR starts at 0x10000000 and ends 0x2FFF0000 (512MB)
> +  # SystemMemorySize is 0x2FFF0000 - PcdSystemMemoryBase
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x2FFF0000
> +  gArmTokenSpaceGuid.PcdSystemMemorySize|0x1D5F0000
> +  !elseif $(DRAM_SIZE) == DRAM_1GB
> +  #
> +  # Board DDR starts at 0x10000000 and ends 0x4FFF0000 (1GB)
> +  # SystemMemorySize is 0x4FFF0000 - PcdSystemMemoryBase
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x4FFF0000
> +  gArmTokenSpaceGuid.PcdSystemMemorySize|0x3D5F0000
> +  !else
> +  #
> +  # Board DDR starts at 0x10000000 and ends 0x8FFF0000 (2GB)
> +  # SystemMemorySize is 0x8FFF0000 - PcdSystemMemoryBase
> +  #
> +  giMX6TokenSpaceGuid.PcdMemoryEndAddress|0x8FFF0000
> +  gArmTokenSpaceGuid.PcdSystemMemorySize|0x7D5F0000
> +  !endif
> +!endif
> +
> +!if $(CONFIG_MPCORE) == TRUE
> +  !if (($(IMX_CHIP_TYPE) == QUAD) || ($(IMX_CHIP_TYPE) == QUADPLUS))
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount|4
> +  !elseif (($(IMX_CHIP_TYPE) == DUAL) || ($(IMX_CHIP_TYPE) == DUALLITE))
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount|2
> +  !else
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount|1
> +  !endif
> +!else
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount|1
> +!endif
> +
> +########################
> +#
> +# MdePkg PCDs
> +#
> +########################
> +[PcdsFeatureFlag.common]
> +  gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE
> +  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE
> +  gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
> +  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
> +
> +[PcdsFixedAtBuild.common]
> +  gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000
> +  gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000
> +  gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000
> +  gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000
> +  gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF
> +  gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0
> +  gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320
> +  gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|1
> +
> +  #
> +  # DEBUG_ASSERT_ENABLED       0x01
> +  # DEBUG_PRINT_ENABLED        0x02
> +  # DEBUG_CODE_ENABLED         0x04
> +  # CLEAR_MEMORY_ENABLED       0x08
> +  # ASSERT_BREAKPOINT_ENABLED  0x10
> +  # ASSERT_DEADLOOP_ENABLED    0x20
> +  #
> +  !if $(TARGET) == RELEASE
> +    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x23
> +  !else
> +    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f
> +  !endif
> +
> +  #
> +  # Debug Flags as defined in DebugLib.h
> +  #
> +  # DEBUG_INIT      0x00000001  // Initialization
> +  # DEBUG_WARN      0x00000002  // Warnings
> +  # DEBUG_LOAD      0x00000004  // Load events
> +  # DEBUG_FS        0x00000008  // EFI File system
> +  # DEBUG_POOL      0x00000010  // Alloc & Free (pool)
> +  # DEBUG_PAGE      0x00000020  // Alloc & Free (page)
> +  # DEBUG_INFO      0x00000040  // Informational debug messages
> +  # DEBUG_DISPATCH  0x00000080  // PEI/DXE/SMM Dispatchers
> +  # DEBUG_VARIABLE  0x00000100  // Variable
> +  # DEBUG_BM        0x00000400  // Boot Manager
> +  # DEBUG_BLKIO     0x00001000  // BlkIo Driver
> +  # DEBUG_NET       0x00004000  // Network Io Driver
> +  # DEBUG_UNDI      0x00010000  // UNDI Driver
> +  # DEBUG_LOADFILE  0x00020000  // LoadFile
> +  # DEBUG_TEEC      0x00040000  // TEE Client Tracings
> +  # DEBUG_EVENT     0x00080000  // Event messages
> +  # DEBUG_GCD       0x00100000  // Global Coherency Database changes
> +  # DEBUG_CACHE     0x00200000  // Memory range cachability changes
> +  # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
> +  #                             // significantly impact boot performance
> +  # DEBUG_ERROR     0x80000000  // Error
> +  #
> +  # By default only enable init, error, warning and load debug prints to minimize
> +  # debug messages. Use "0x8FEF4DCF" for detailed debugging purposes.
> +  #
> +!if $(TARGET) == RELEASE
> +  #
> +  # In release builds enable error, warning, and load (base and entry point)
> +  #
> +  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel| 0x80000006
> +!else
> +  #
> +  # In debug builds enable error, cache, info, load, warn, and init
> +  #
> +  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel| 0x80000047
> +!endif
> +  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
> +
> +########################
> +#
> +# MdeModulePkg PCDs
> +#
> +########################
> +[PcdsFeatureFlag.common]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE
> +
> +  ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe.
> +  #  It could be set FALSE to save size.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
> +
> +[PcdsFixedAtBuild.common]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
> +  gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
> +  # GUID of the UI app
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
> +
> +[PcdsPatchableInModule]
> +  # Console Resolution
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|1920
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|1080
> +
> +########################
> +#
> +# EmbeddedPkg PCDs
> +#
> +########################
> +[PcdsFeatureFlag.common]
> +  gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE
> +
> +[PcdsFixedAtBuild.common]
> +  #
> +  # Optional feature to help prevent EFI memory map fragments
> +  # Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob
> +  # Values are in EFI Pages (4K). DXE Core will make sure that
> +  # at least this much of each type of memory can be allocated
> +  # from a single memory range. This way you only end up with
> +  # maximum of two fragements for each type in the memory map
> +  # (the memory used, and the free memory that was prereserved
> +  # but not used).
> +  #
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|3000
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0
> +
> +  #
> +  # Timer Configuration
> +  #
> +  # The timer period is configured in units of 100ns. We configure it for 10ms
> +  # timer ticks which will be used mainly by DXE Core to keep track of system
> +  # time and hence keep track of all events.
> +  #
> +  gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000
> +
> +########################
> +#
> +# IntelFrameworkModulePkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +  # GUID of the UEFI Shell
> +  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }
> +
> +########################
> +#
> +# OpteeClientPkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +!if $(IMX_FAMILY) == IMX6SX
> +  #
> +  # Reserved for TPM2 ACPI
> +  # 0x82000000 - 0x82002FFF
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0x82000000
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0x3000
> +
> +  #
> +  # iMX Plaform Memory Layout
> +  #
> +  # +-------------------+===> (0x80000000) PcdTrustZonePrivateMemoryBase (OPTEE image base address)
> +  # | TZ Private Memory |  ^
> +  # | (OPTEE)           |  |  (0x01E00000) PcdTrustZonePrivateMemorySize 30MB
> +  # |                   |  v
> +  # +-------------------+===> (0x81E00000) PcdTrustZoneSharedMemoryBase (includes mobj bookkeeping page)
> +  # | TZ Shared Memory  |  ^
> +  # |                   |  |  (0x00200000) PcdTrustZoneSharedMemorySize 2MB
> +  # |                   |  v
> +  # +-------------------|===> (0x82000000) PcdTpm2AcpiBufferBase
> +  # | TPM2 Control Area |  ^
> +  # |                   |  |  (0x00003000) PcdTpm2AcpiBufferSize 12KB
> +  # |                   |  v
> +  # +-------------------+===> (0x82003000) PcdGlobalDataBaseAddress
> +  # | Global Data       |  ^
> +  # |                   |  |  (0x00001000) PcdGlobalDataSize 4KB
> +  # |                   |  v
> +  # +-------------------+===> (0x82004000) PcdFdBaseAddress (UEFI Load Address)
> +  # | UEFI              |  ^
> +  # |                   |  |  (0x001D0000) PcdFdSize 1856KB
> +  # |                   |  v
> +  # +-------------------+===> (0x821D4000) PcdFrameBufferBase
> +  # | FrameBuffer       |  ^
> +  # |                   |  |  (0x00800000) PcdFrameBufferSize 8MB
> +  # |                   |  v
> +  # +-------------------+===> (0x829D4000) PcdSystemMemoryBase
> +  # | Operating System  |  ^
> +  # | Memory            |  |
> +  # |                   |  |
> +  # |                   |  v
> +  # +------------------ +===>
> +
> +  DEFINE GLOBAL_DATA_BASE_ADDRESS = 0x82003000
> +
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0x80000000
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|0x01E00000
> +
> +  #
> +  # TrustZone shared memory (2Mb)
> +  # This memory is managed by the normal world but shared with the OpTEE OS.
> +  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
> +  #    CFG_SHMEM_START & CFG_SHMEM_SIZE
> +  # NOTE: The first page of the SHMEM is owned by OPTEE for mobj bookkeeping
> +  # and we should not touch it. We will skip the first 4K of SHMEM and take that
> +  # into account for SHMEM size in PcdTrustZoneSharedMemorySize.
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0x81E00000
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0x00200000
> +
> +  giMX6TokenSpaceGuid.PcdFrameBufferBase|0x821D4000
> +
> +!else
> +  #
> +  # Reserved for TPM2 ACPI
> +  # 0x10814000 - 0x10816FFF
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase|0x10814000
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize|0x3000
> +
> +  #
> +  # iMX Plaform Memory Layout
> +  #
> +  # +-------------------+===> (0x10000000) PcdFrameBufferBase (DDR Start Address)
> +  # |Frame Buffer       |  ^
> +  # |                   |  |  (0x00800000) PcdFrameBufferSize 8MB
> +  # |                   |  v
> +  # +-------------------+===
> +  # |                   |     Gap
> +  # +-------------------|===> (0x10814000) PcdTpm2AcpiBufferBase
> +  # |TPM2 Control Area  |  ^
> +  # |                   |  |  (0x3000) 12KB
> +  # |                   |  v
> +  # +-------------------+===> (0x10817000) PcdGlobalDataBaseAddress
> +  # | Global Data       |  ^
> +  # |                   |  |  (0x1000) PcdGlobalDataSize 4KB
> +  # |                   |  v
> +  # +-------------------+===
> +  # | Gap               |
> +  # +-------------------+===> (0x10820000) UEFI Load Address
> +  # | UEFI              |  ^
> +  # |                   |  |  (0x1D0000) 1920KB
> +  # |                   |  v
> +  # +-------------------+===> (0x10A00000) PcdTrustZonePrivateMemoryBase (OPTEE image base address)
> +  # | TZ Private Memory |  ^
> +  # | (OPTEE)           |  |  (0x1E00000) 30MB
> +  # |                   |  v
> +  # +-------------------+===> (0x12800000) PcdTrustZoneSharedMemoryBase (includes mobj bookkeeping page)
> +  # | TZ Shared Memory  |  ^
> +  # |                   |  |  (0x200000) 2MB
> +  # |                   |  v
> +  # +-------------------+===> (0x12A00000) PcdSystemMemoryBase
> +  # | Operating System  |  ^
> +  # | Memory            |  |  (0x3D5F0000) 982MB for 1GB DRAM OR
> +  # |                   |  |  (0x7D5F0000) 2005MB for 2GB DRAM
> +  # |                   |  v
> +  # +------------------ +===
> +  #
> +  # Reserved for Optee private memory (31M)
> +  # 0x10A00000 - 0x127FFFFF
> +  #
> +  # TrustZone private memory (?Mb OPTEE + ?Mb PSCI)
> +  # 0x8E000000 - 8FEFFFFF
> +  # This memory is managed privately by the OpTEE OS.
> +  #    CFG_DDR_TEETZ_RESERVED_START & CFG_DDR_TEETZ_RESERVED_START
> +  #
> +
> +  DEFINE GLOBAL_DATA_BASE_ADDRESS = 0x10817000
> +
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase|0x10A00000
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize|0x01E00000
> +
> +  #
> +  # TrustZone shared memory (2Mb)
> +  # 0x12800000 - 0x129FFFFF
> +  # This memory is managed by the normal world but shared with the OpTEE OS.
> +  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
> +  #    CFG_SHMEM_START & CFG_SHMEM_SIZE
> +  # NOTE: The first page of the SHMEM is owned by OPTEE for mobj bookkeeping
> +  # and we should not touch it. We will skip the first 4K of SHMEM and take that
> +  # into account for SHMEM size in PcdTrustZoneSharedMemorySize.
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase|0x12800000
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize|0x00200000
> +
> +  giMX6TokenSpaceGuid.PcdFrameBufferBase|0x10000000
> +
> +!endif
> +########################
> +#
> +# SecurityPkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +  #
> +  # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
> +  #
> +  gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04
> +  gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04
> +  gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
> +
> +  #
> +  # PcdTpmInstanceGuid tells the Tcg2 Driver which TPM version is being used.
> +  # The below GUID is TPMv2 GUID.
> +  #
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{ 0x5a, 0xf2, 0x6b, 0x28, 0xc3, 0xc2, 0x8c, 0x40, 0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17 }
> +
> +  ## Sets the default Physical Presence flags that are consumed by the PP TrEE library.
> +  #
> +  # Options are defined in TrEEPhysicalPresenceData.h
> +  # Current setting:
> +  #   TREE_FLAG_NO_PPI_CLEAR
> +  #
> +  #gEfiSecurityPkgTokenSpaceGuid.PcdPPDefaultTrEEFlags|0x02
> +
> +  ## Indicates whether or not the Tcg2Dxe should measure CRTM instead of PEI.
> +  # TRUE means the Tcg2Dxe will measure CRTM.
> +  #
> +  #gEfiSecurityPkgTokenSpaceGuid.PcdLateMeasureCRTM|TRUE
> +
> +[PcdsDynamicExDefault.common.DEFAULT]
> +  gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap|0x0
> +
> +########################
> +#
> +# MsPkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +
> +  #
> +  # SD first FAT partition device path:
> +  # VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,03000000)/SD(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)
> +  #
> +  # eMMC first FAT partition device path:
> +  # VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,04000000)/eMMC(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)
> +  #
> +  # Use the SDCard first fat partition for logging and misc storage.
> +  #
> +  gMsPkgTokenSpaceGuid.PcdStorageMediaPartitionDevicePath|L"VenHw(AAFB8DAA-7340-43AC-8D49-0CCE14812489,03000000)/SD(0x0)/HD(1,MBR,0xAE420040,0x1000,0x20000)"
> +
> +!if $(CONFIG_SECURE_BOOT) == TRUE
> +  gMsPkgTokenSpaceGuid.PcdSecureBootEnable|TRUE
> +!else
> +  gMsPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE
> +!endif

What is this Pcd used for?

> +
> +########################
> +#
> +# iMXPlatformPkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +
> +  # Global data area
> +  giMXPlatformTokenSpaceGuid.PcdGlobalDataBaseAddress|$(GLOBAL_DATA_BASE_ADDRESS)
> +  giMXPlatformTokenSpaceGuid.PcdGlobalDataSize|0x1000
> +
> +################################################################################
> +#
> +# [Components] Section
> +#
> +################################################################################
> +[Components.common]
> +
> +  #
> +  # SEC (PrePi)
> +  #
> +  ArmPlatformPkg/PrePi/PeiMPCore.inf
> +
> +  #
> +  # DXE Core
> +  #
> +  MdeModulePkg/Core/Dxe/DxeMain.inf {
> +    <LibraryClasses>
> +      NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
> +  }
> +  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
> +    <LibraryClasses>
> +      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> +  }
> +
> +  #
> +  # DXE required Architectural Protocols as defined by UEFI 2.6 specs
> +  #
> +  # BDS Arch Protocol
> +  # CPU Arch Protocol
> +  # Metronome Arch Protocol
> +  # Real Time Clock Arch Protocol
> +  # Reset Arch Protocol
> +  # Runtime Arch Protocol
> +  # Security Arch Protocol
> +  # Timer Arch Protocol
> +  # Variable Arch Protocol
> +  # Variable Write Arch Protocol
> +  # EFI Capsule Arch Protocol
> +  # Watchdog Timer Arch Protocol
> +  #
> +
> +  ArmPkg/Drivers/CpuDxe/CpuDxe.inf
> +  EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
> +  EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
> +  EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
> +  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
> +  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
> +    <LibraryClasses>
> +      NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
> +      NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
> +  }
> +  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
> +  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> +  ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
> +  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> +
> +  #
> +  # Serial Console
> +  #
> +  MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
> +  EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
> +  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
> +
> +  #
> +  # Filesystem Stack
> +  #
> +  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
> +  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
> +  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
> +  FatPkg/EnhancedFatDxe/Fat.inf
> +  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
> +  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
> +
> +  # PCIe support
> +  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
> +
> +  #
> +  # Generic Bds (Not Intel's)
> +  #
> +  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
> +  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
> +  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
> +  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
> +  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
> +  MdeModulePkg/Application/UiApp/UiApp.inf {
> +    <LibraryClasses>
> +      NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
> +      NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
> +      NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
> +  }
> +
> +  #
> +  # Shell
> +  #
> +  ShellPkg/Application/Shell/Shell.inf {
> +    <LibraryClasses>
> +      ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
> +      BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
> +      HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
> +      NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
> +      NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
> +      NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
> +      NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
> +      NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
> +      NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
> +      NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
> +      PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
> +
> +    <PcdsFixedAtBuild>
> +      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
> +      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> +      gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
> +  }
> +
> +MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
> +
> +#
> +# Boilerplate for compiling UEFI applications and UEFI drivers with the
> +# standard library.
> +#
> +!include StdLib/StdLib.inc

Wait, what?
Please tell me we're not actually using that?

/
    Leif

> diff --git a/Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc b/Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
> new file mode 100644
> index 000000000000..877f575d7999
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
> @@ -0,0 +1,287 @@
> +#
> +# FLASH layout file for iMX6 Quad and Dual SOM boards.
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +
> +# Continuation of [FV.FvMain]
> +  INF MdeModulePkg/Core/Dxe/DxeMain.inf
> +  INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
> +
> +  #
> +  # PI DXE Drivers producing Architectural Protocols (EFI Services)
> +  #
> +  INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
> +
> +  INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
> +  INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
> +  INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> +  INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +  INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> +
> +  INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
> +  # Timers
> +  INF Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
> +
> +  INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
> +  INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
> +  INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
> +
> +  INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
> +  INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
> +  INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
> +
> +  #
> +  # Filesystem Stack
> +  #
> +  INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
> +  INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
> +  INF FatBinPkg/EnhancedFatDxe/Fat.inf
> +  INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
> +  INF Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
> +  INF Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
> +
> +  #
> +  # PCIe
> +  #
> +  INF Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
> +
> +  #
> +  # Bds
> +  #
> +  INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
> +  INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
> +  INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
> +  INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
> +  INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
> +  INF MdeModulePkg/Application/UiApp/UiApp.inf
> +
> +  #
> +  # UEFI application (Shell Embedded Boot Loader)
> +  #
> +  INF ShellPkg/Application/Shell/Shell.inf
> +
> +INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
> +
> +[FV.FVMAIN_COMPACT]
> +FvAlignment        = 8
> +ERASE_POLARITY     = 1
> +MEMORY_MAPPED      = TRUE
> +STICKY_WRITE       = TRUE
> +LOCK_CAP           = TRUE
> +LOCK_STATUS        = TRUE
> +WRITE_DISABLED_CAP = TRUE
> +WRITE_ENABLED_CAP  = TRUE
> +WRITE_STATUS       = TRUE
> +WRITE_LOCK_CAP     = TRUE
> +WRITE_LOCK_STATUS  = TRUE
> +READ_DISABLED_CAP  = TRUE
> +READ_ENABLED_CAP   = TRUE
> +READ_STATUS        = TRUE
> +READ_LOCK_CAP      = TRUE
> +READ_LOCK_STATUS   = TRUE
> +
> +  INF ArmPlatformPkg/PrePi/PeiMPCore.inf
> +
> +  FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
> +    SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
> +      SECTION FV_IMAGE = FVMAIN
> +    }
> +  }
> +
> +
> +################################################################################
> +#
> +# Rules are use with the [FV] section's module INF type to define
> +# how an FFS file is created for a given INF file. The following Rule are the default
> +# rules for the different module type. User can add the customized rules to define the
> +# content of the FFS file.
> +#
> +################################################################################
> +
> +
> +############################################################################
> +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section   #
> +############################################################################
> +#
> +#[Rule.Common.DXE_DRIVER]
> +#  FILE DRIVER = $(NAMED_GUID) {
> +#    DXE_DEPEX    DXE_DEPEX               Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +#    COMPRESS PI_STD {
> +#      GUIDED {
> +#        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
> +#        UI       STRING="$(MODULE_NAME)" Optional
> +#        VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
> +#      }
> +#    }
> +#  }
> +#
> +############################################################################
> +!if 0
> +[Rule.Common.SEC]
> +  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
> +    TE  TE    Align = 32                $(INF_OUTPUT)/$(MODULE_NAME).efi
> +  }
> +
> +[Rule.Common.PEI_CORE]
> +  FILE PEI_CORE = $(NAMED_GUID) {
> +    TE     TE                           $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI     STRING ="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.PEIM]
> +  FILE PEIM = $(NAMED_GUID) {
> +    PEI_DEPEX PEI_DEPEX Optional       $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32      PE32                     $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI       STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.PEIM.TIANOCOMPRESSED]
> +  FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
> +    PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
> +      PE32      PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
> +      UI        STRING="$(MODULE_NAME)" Optional
> +    }
> +  }
> +
> +[Rule.Common.DXE_CORE]
> +  FILE DXE_CORE = $(NAMED_GUID) {
> +    PE32     PE32                       $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI       STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +
> +[Rule.Common.UEFI_DRIVER]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.DXE_DRIVER]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.DXE_RUNTIME_DRIVER]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.UEFI_APPLICATION]
> +  FILE APPLICATION = $(NAMED_GUID) {
> +    UI     STRING ="$(MODULE_NAME)" Optional
> +    PE32   PE32                         $(INF_OUTPUT)/$(MODULE_NAME).efi
> +  }
> +
> +[Rule.Common.UEFI_DRIVER.BINARY]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX DXE_DEPEX Optional      |.depex
> +    PE32      PE32                    |.efi
> +    UI        STRING="$(MODULE_NAME)" Optional
> +    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
> +  }
> +
> +[Rule.Common.UEFI_APPLICATION.BINARY]
> +  FILE APPLICATION = $(NAMED_GUID) {
> +    PE32      PE32                    |.efi
> +    UI        STRING="$(MODULE_NAME)" Optional
> +    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
> +  }
> +!endif
> +
> +[Rule.Common.SEC]
> +  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
> +    TE  TE    Align = 32                $(INF_OUTPUT)/$(MODULE_NAME).efi
> +  }
> +
> +[Rule.Common.PEI_CORE]
> +  FILE PEI_CORE = $(NAMED_GUID) {
> +    TE     TE                           $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI     STRING ="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.PEIM]
> +  FILE PEIM = $(NAMED_GUID) {
> +     PEI_DEPEX PEI_DEPEX Optional       $(INF_OUTPUT)/$(MODULE_NAME).depex
> +     PE32      PE32                     $(INF_OUTPUT)/$(MODULE_NAME).efi
> +     UI       STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.PEIM.TIANOCOMPRESSED]
> +  FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
> +    PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
> +      PE32      PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
> +      UI        STRING="$(MODULE_NAME)" Optional
> +    }
> +  }
> +
> +[Rule.Common.DXE_CORE]
> +  FILE DXE_CORE = $(NAMED_GUID) {
> +    PE32     PE32                       $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI       STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +
> +[Rule.Common.UEFI_DRIVER]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.DXE_DRIVER]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.DXE_RUNTIME_DRIVER]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
> +    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.UEFI_APPLICATION]
> +  FILE APPLICATION = $(NAMED_GUID) {
> +    UI     STRING ="$(MODULE_NAME)" Optional
> +    PE32   PE32                         $(INF_OUTPUT)/$(MODULE_NAME).efi
> +  }
> +
> +[Rule.Common.USER_DEFINED.ACPITABLE]
> +  FILE FREEFORM = $(NAMED_GUID) {
> +    RAW          ACPI                 |.acpi
> +    RAW          ASL Optional         |.aml
> +    UI           STRING="$(MODULE_NAME)" Optional
> +  }
> +
> +[Rule.Common.UEFI_DRIVER.BINARY]
> +  FILE DRIVER = $(NAMED_GUID) {
> +    DXE_DEPEX DXE_DEPEX Optional      |.depex
> +    PE32      PE32                    |.efi
> +    UI        STRING="$(MODULE_NAME)" Optional
> +    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
> +  }
> +
> +[Rule.Common.UEFI_APPLICATION.BINARY]
> +  FILE APPLICATION = $(NAMED_GUID) {
> +    PE32      PE32                    |.efi
> +    UI        STRING="$(MODULE_NAME)" Optional
> +    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
> +  }
> diff --git a/Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc b/Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
> new file mode 100644
> index 000000000000..cf3b68556a4e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
> @@ -0,0 +1,148 @@
> +#
> +# iMX6 Common Configurations Definition
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +
> +[Defines]
> +
> +  # Display surface will not be drawn to.
> +!ifndef CONFIG_HEADLESS
> +  DEFINE CONFIG_HEADLESS = FALSE
> +!endif
> +
> +  # Useful if working with Lauterbach JTAG. Will dump to console the complete
> +  # command to copy and past into the Lauterbach command line to load symbols
> +  # for each module.
> +  # Use in conjution with Informational debug messages:
> +  # DEBUG_INFO      0x00000040
> +!ifndef CONFIG_DUMP_SYMBOL_INFO
> +  DEFINE CONFIG_DUMP_SYMBOL_INFO = FALSE
> +!endif
> +
> +  # Enable if PSCI is implemented.
> +!ifndef CONFIG_MPCORE
> +  DEFINE CONFIG_MPCORE = TRUE
> +!endif
> +
> +  # Disable the PCIexpress stack by default. Enable on demand.
> +!ifndef CONFIG_PCIE
> +  DEFINE CONFIG_PCIE = FALSE
> +!endif
> +
> +  # States whether OPTEE boot flow is in effect or not. This has the following
> +  # implications:
> +  # - OPTEE owns the SecureWorld and UEFI has to run in NormalWorld.
> +  # - Specific memory layout that is defined in the platform .dsc file.
> +  # - Temp: Running in single-core until PSCI is enabled.
> +  # WARNING: Don't set this to FALSE unless you know what you are doing. Running
> +  # UEFI in SecureWorld will most likely result in boot failure due to lack of
> +  # proper CPU sec configuration. That is by UEFI design.
> +!ifndef CONFIG_OPTEE
> +  DEFINE CONFIG_OPTEE = TRUE
> +!endif
> +
> +  # Allow collecting performance tracing from OPTEE hot code paths
> +  # Performance summary results can be inspected with the shell app Dp.efi
> +!ifndef CONFIG_OPTEE_PROFILE
> +  DEFINE CONFIG_OPTEE_PROFILE = FALSE
> +!endif
> +
> +  # Call build with -D CONFIG_SECURE_UEFI=1 to enable the follwing security features
> +!if $(CONFIG_SECURE_UEFI) == TRUE
> +
> +  # UEFI authenticated variable runtime services
> +!ifndef CONFIG_AUTH_VAR
> +  DEFINE CONFIG_AUTH_VAR = TRUE
> +!endif
> +
> +  # TPM stack for the fTPM
> +!ifndef CONFIG_MEASURED_BOOT
> +  DEFINE CONFIG_MEASURED_BOOT = TRUE
> +!endif
> +
> +  # If Platform Key (PK) is provisioned, then SecureBoot variables will get
> +  # updated to reflect that SecureBoot is enabled. Otherwise, SecureBoot
> +  # variables will indicate that the feature is disabled, and the OS will
> +  # not boot apply SecureBoot policies
> +!ifndef CONFIG_SECURE_BOOT
> +  DEFINE CONFIG_SECURE_BOOT = TRUE
> +!endif
> +
> +  # Provison SecureBoot with MS test certs and keys that are baked into the FV
> +  # on first UEFI boot if SecureBoot found to be not provisioned
> +  DEFINE CONFIG_SECURE_BOOT_AUTO_CONFIG = TRUE
> +!else
> +
> +!ifndef CONFIG_AUTH_VAR
> +  DEFINE CONFIG_AUTH_VAR = FALSE
> +!endif
> +
> +!ifndef CONFIG_MEASURED_BOOT
> +  DEFINE CONFIG_MEASURED_BOOT = FALSE
> +!endif
> +
> +!ifndef CONFIG_SECURE_BOOT
> +  DEFINE CONFIG_SECURE_BOOT = FALSE
> +!endif
> +
> +!endif
> +
> +[BuildOptions]
> +#
> +# For each enabled CONFIG_* flag in the dsc files, define that flag in C code.
> +# Description of each CONFIG_* flag exist in iMX6DefaultConfigDsc.inc
> +# Note: The = sign in BuildOptions section appends to the existing macro, while
> +# == can be used to replace its value. See the EDK2 DSC specs.
> +#
> +!if $(CONFIG_HEADLESS) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_HEADLESS=1
> +!endif
> +
> +!if $(CONFIG_DUMP_SYMBOL_INFO) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_DUMP_SYMBOL_INFO=1
> +!endif
> +
> +!if $(CONFIG_MPCORE) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_MPCORE=1
> +!endif
> +
> +!if $(CONFIG_USB) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_USB=1
> +!endif
> +
> +!if $(CONFIG_PCIE) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_PCIE=1
> +!endif
> +
> +!if $(CONFIG_OPTEE) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_OPTEE=1
> +!endif
> +
> +!if $(CONFIG_OPTEE_PROFILE) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DOPTEE_PROFILE=1
> +!endif
> +
> +!if $(CONFIG_AUTH_VAR) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_AUTH_VAR=1
> +!endif
> +
> +!if $(CONFIG_MEASURED_BOOT) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_MEASURED_BOOT=1
> +!endif
> +
> +!if $(CONFIG_SECURE_BOOT) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_SECURE_BOOT=1
> +!endif
> +
> +!if $(CONFIG_SECURE_BOOT_AUTO_CONFIG) == TRUE
> +  GCC:*_*_*_CC_FLAGS = -DCONFIG_SECURE_BOOT_AUTO_CONFIG=1
> +!endif
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 25/27] Platform/Solidrun: Add Hummingboard Peripheral Initialization
  2018-09-21  8:26 ` [PATCH edk2-platforms 25/27] Platform/Solidrun: Add Hummingboard Peripheral Initialization Chris Co
@ 2018-12-15 12:12   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-15 12:12 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Michael D Kinney, Ard Biesheuvel

On Fri, Sep 21, 2018 at 08:26:17AM +0000, Chris Co wrote:
> This adds support to initialize the different peripherals on
> the Solidrun i.MX 6Quad Hummingboard Edge.  It will initialize the
> pad mux and clocks for the different peripherals.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> ---
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c  | 634 ++++++++++++++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h  | 705 ++++++++++++++++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf |  91 +++
>  3 files changed, 1430 insertions(+)

I would prefer for the directory to be
HummingBoardEdge/Library/iMX6BoardLib2GBQ or similar. No _ in names.

> 
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
> new file mode 100644
> index 000000000000..73e63484288c
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
> @@ -0,0 +1,634 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*  Copyright 2018 NXP
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <IndustryStandard/Tpm20.h>
> +#include <IndustryStandard/Tpm2Acpi.h>
> +
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/SerialPortLib.h>
> +#include <Library/TimerLib.h>
> +
> +#include "iMX6BoardInit.h"
> +
> +STATIC CONST IMX_CLK_GATE GatesToTurnOff[] = {

m-prefix.

> +  IMX_ASRC_CLK_ENABLE,
> +  IMX_CAN1_CLK_ENABLE,
> +  IMX_CAN1_SERIAL_CLK_ENABLE,
> +  IMX_CAN2_CLK_ENABLE,
> +  IMX_CAN2_SERIAL_CLK_ENABLE,
> +  IMX_DCIC1_CLK_ENABLE,
> +  IMX_DCIC2_CLK_ENABLE,
> +  IMX_DTCP_CLK_ENABLE,
> +  IMX_ECSPI1_CLK_ENABLE,
> +  IMX_ECSPI2_CLK_ENABLE,
> +  IMX_ECSPI3_CLK_ENABLE,
> +  IMX_ECSPI4_CLK_ENABLE,
> +  IMX_ECSPI5_CLK_ENABLE,
> +  IMX_ENET_CLK_ENABLE,
> +  IMX_ESAI_CLK_ENABLE,
> +  IMX_I2C1_SERIAL_CLK_ENABLE,
> +  IMX_I2C2_SERIAL_CLK_ENABLE,
> +  IMX_I2C3_SERIAL_CLK_ENABLE,
> +  IMX_IIM_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE,
> +  IMX_IPU1_DI1_CLK_ENABLE,
> +  IMX_IPU2_CLK_ENABLE,
> +  IMX_IPU2_DI0_CLK_ENABLE,
> +  IMX_IPU2_DI1_CLK_ENABLE,
> +  IMX_LDB_DI0_CLK_ENABLE,
> +  IMX_LDB_DI1_CLK_ENABLE,
> +  IMX_MIPI_CORE_CFG_CLK_ENABLE,
> +  IMX_MLB_CLK_ENABLE,
> +  IMX_PL301_MX6QPER1_BCHCLK_ENABLE,
> +  IMX_PWM2_CLK_ENABLE,
> +  IMX_PWM3_CLK_ENABLE,
> +  IMX_PWM4_CLK_ENABLE,
> +  IMX_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE,
> +  IMX_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE,
> +  IMX_SPDIF_CLK_ENABLE,
> +  IMX_SSI1_CLK_ENABLE,
> +  IMX_SSI2_CLK_ENABLE,
> +  IMX_SSI3_CLK_ENABLE,
> +  IMX_EIM_SLOW_CLK_ENABLE,
> +  IMX_VDOAXICLK_CLK_ENABLE,
> +  IMX_VPU_CLK_ENABLE,
> +};
> +
> +STATIC CONST IMX_CLK_GATE GatesToTurnOn[] = {

m-prefix.

> +  IMX_SDMA_CLK_ENABLE,
> +  IMX_SPBA_CLK_ENABLE,
> +  IMX_GPT_SERIAL_CLK_ENABLE,
> +  IMX_USBOH3_CLK_ENABLE,
> +  IMX_PWM1_CLK_ENABLE
> +};
> +
> +STATIC IMX_PAD GpioPins[] = {

m-prefix.

> +  IMX_PAD_ENET_RX_ER,
> +  IMX_PAD_EIM_A22,
> +  IMX_PAD_EIM_A21,
> +  IMX_PAD_EIM_A20,
> +  IMX_PAD_EIM_A19,
> +  IMX_PAD_EIM_A18,
> +  IMX_PAD_EIM_A17,
> +  IMX_PAD_EIM_A16,
> +  IMX_PAD_EIM_EB0,
> +  IMX_PAD_EIM_EB1,
> +  IMX_PAD_EIM_DA0,
> +  IMX_PAD_EIM_DA1,
> +  IMX_PAD_EIM_DA2,
> +  IMX_PAD_EIM_DA3,
> +  IMX_PAD_EIM_DA4,
> +  IMX_PAD_EIM_DA5,
> +  IMX_PAD_EIM_DA6,
> +  IMX_PAD_EIM_DA7,
> +  IMX_PAD_EIM_DA8,
> +  IMX_PAD_EIM_DA9,
> +  IMX_PAD_EIM_DA10,
> +  IMX_PAD_EIM_DA11,
> +  IMX_PAD_EIM_DA12,
> +  IMX_PAD_EIM_DA13,
> +  IMX_PAD_EIM_DA14,
> +  IMX_PAD_EIM_DA15,
> +  IMX_PAD_EIM_D26,
> +  IMX_PAD_EIM_D27,
> +  IMX_PAD_EIM_D30,
> +  IMX_PAD_EIM_D31,
> +  IMX_PAD_EIM_A24,
> +  IMX_PAD_EIM_A23,
> +  IMX_PAD_GPIO_16,
> +};
> +
> +CONST IMX_CLK_GATE UartClockGatesToTurnOn[] = {

m-prefix.

> +  IMX_PLL3_MAIN_CLK, // IMX_UART_CLK_ENABLE,
> +  IMX_UART_CLK_ROOT  // UART_SERIAL_CLK_ENABLE,
> +};
> +
> +/**
> +  Turn off clock gates which are not needed during boot. The PEP is responsible
> +  to ungate clocks as needed.
> +**/
> +STATIC
> +VOID
> +GateUnusedClocks (
> +  VOID
> +  )
> +{
> +  ImxClkPwrSetClockGates (
> +    GatesToTurnOff,
> +    sizeof (GatesToTurnOff) / sizeof (GatesToTurnOff[0]),

ARRAY_SIZE.

> +    IMX_CLOCK_GATE_STATE_OFF);
> +}
> +
> +/**
> +  Turn on required clocks, that are not handled by the PEP.
> +**/
> +STATIC
> +VOID
> +UngateRequiredClocks (
> +  VOID
> +  )
> +{
> +  ImxClkPwrSetClockGates (
> +    GatesToTurnOn,
> +    sizeof (GatesToTurnOn) / sizeof (GatesToTurnOn[0]),
> +    IMX_CLOCK_GATE_STATE_ON);
> +}
> +
> +STATIC
> +VOID
> +EnetInit (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_ANALOG_REGISTERS   *pCcmAnalogReg;

No volatile, no Hungarian notation. Throughout.

> +  IMX_CCM_ANALOG_PLL_ENET_REG         CcmAnalogPllReg;
> +  UINT32                              Counter;
> +
> +  // Apply ENET pin-muxing configurations (ALT 1)
> +  ImxPadConfig (IMX_PAD_ENET_MDIO, IMX_PAD_ENET_MDIO_ENET_MDIO);
> +  ImxPadConfig (IMX_PAD_ENET_MDC, IMX_PAD_ENET_MDC_ENET_MDC);
> +  ImxPadConfig (IMX_PAD_KEY_ROW4, IMX_PAD_CFG_KEY_ROW4_GPIO4_IO15);
> +  ImxPadConfig (IMX_PAD_DI0_PIN2, IMX_PAD_DI0_PIN2_GPIO4_IO18);
> +  ImxPadConfig (IMX_PAD_GPIO_16, IMX_PAD_GPIO_16_ENET_REF_CLK);
> +  ImxPadConfig (IMX_PAD_ENET_REF_CLK, IMX_PAD_ENET_REF_CLK_ENET_REF_CLK);
> +  ImxPadConfig (IMX_PAD_RGMII_TD0, IMX_PAD_RGMII_TD0_RGMII_TD0);
> +  ImxPadConfig (IMX_PAD_RGMII_TD1, IMX_PAD_RGMII_TD1_RGMII_TD1);
> +  ImxPadConfig (IMX_PAD_RGMII_TD2, IMX_PAD_RGMII_TD2_RGMII_TD2);
> +  ImxPadConfig (IMX_PAD_RGMII_TD3, IMX_PAD_RGMII_TD3_RGMII_TD3);
> +  ImxPadConfig (IMX_PAD_RGMII_TXC, IMX_PAD_RGMII_TXC_RGMII_TXC);
> +  ImxPadConfig (IMX_PAD_RGMII_TX_CTL, IMX_PAD_RGMII_TX_CTL_RGMII_TX_CTL);
> +
> +  ImxPadConfig (IMX_PAD_RGMII_RD0, IMX_PAD_RGMII_RD0_ENET_RGMII_RD0);
> +  ImxPadConfig (IMX_PAD_RGMII_RD1, IMX_PAD_RGMII_RD1_ENET_RGMII_RD1);
> +  ImxPadConfig (IMX_PAD_RGMII_RD2, IMX_PAD_RGMII_RD2_ENET_RGMII_RD2);
> +  ImxPadConfig (IMX_PAD_RGMII_RD3, IMX_PAD_RGMII_RD3_ENET_RGMII_RD3);
> +  ImxPadConfig (IMX_PAD_RGMII_RXC, IMX_PAD_RGMII_RXC_ENET_RGMII_RXC);
> +  ImxPadConfig (IMX_PAD_RGMII_RX_CTL, IMX_PAD_RGMII_RX_CTL_RGMII_RX_CTL);
> +
> +  // Enable ENET PLL, also required for PCIe
> +  pCcmAnalogReg = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE;
> +  CcmAnalogPllReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogReg->PLL_ENET);
> +  CcmAnalogPllReg.POWERDOWN = 0;
> +  CcmAnalogPllReg.ENABLE = 1;
> +  MmioWrite32 ((UINTN)&pCcmAnalogReg->PLL_ENET, CcmAnalogPllReg.AsUint32);
> +
> +  for (Counter = 0; Counter < 100; Counter++) {
> +    CcmAnalogPllReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogReg->PLL_ENET);
> +    if (CcmAnalogPllReg.LOCK != 0) {
> +      break;
> +    }
> +    MicroSecondDelay (100);
> +  }
> +  if (CcmAnalogPllReg.LOCK == 0) {
> +    DEBUG ((DEBUG_ERROR, "%a: PLL_ENET is not locked!\n", __FUNCTION__));
> +    return;
> +  }
> +
> +  // Enable PCIe output 125Mhz
> +  CcmAnalogPllReg.BYPASS = 0;
> +  CcmAnalogPllReg.ENABLE_125M = 1;
> +  CcmAnalogPllReg.DIV_SELECT = PLL_ENET_DIV_SELECT_25MHZ;
> +  MmioWrite32 ((UINTN)&pCcmAnalogReg->PLL_ENET, CcmAnalogPllReg.AsUint32);
> +  MicroSecondDelay (50000);
> +
> +  if (CcmAnalogPllReg.LOCK == 0) {
> +    DEBUG ((DEBUG_ERROR, "%a: PLL_ENET is not locked!\n", __FUNCTION__));
> +  }
> +}
> +
> +/**
> +  Set SSI3 clock dividers to provide a bit clock capable of
> +  providing a clock suitable for stereo 44.1 KHz playback at 32 bit
> +  from PLL3 PFD2 which runs at 508.2 MHz.
> +
> +  We only need to scale down the PLL3 FPD2 clock by 1:15 to provide a
> +  reference clock.  The WDM audio class driver will later setup additional
> +  dividers in the SSI3 block to provide the required bit clock rate.
> +
> +  This routine also handles all GPIO/PadConfig init required for audio.
> +**/
> +STATIC
> +VOID
> +SetupAudio (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmReg;
> +  IMX_CCM_CCOSR_REG           CcosrReg;
> +  IMX_CCM_CS1CDR_REG          CsicdrReg;
> +
> +  pCcmReg = (IMX_CCM_REGISTERS *)IMX_CCM_BASE;
> +  CsicdrReg = (IMX_CCM_CS1CDR_REG) MmioRead32 ((UINTN)&pCcmReg->CS1CDR);
> +  CsicdrReg.ssi3_clk_pred = 0; // divide by 1.
> +  CsicdrReg.ssi3_clk_podf = 14; // divide by 15.
> +  MmioWrite32 ((UINTN)&pCcmReg->CS1CDR, CsicdrReg.AsUint32);
> +
> +  // Enable output on CCM_CLKO1, select pll3_sw_clk/2 as the source.
> +  CcosrReg = (IMX_CCM_CCOSR_REG) MmioRead32 ((UINTN)&pCcmReg->CCOSR);
> +  CcosrReg.CLKO1_SEL = 0;
> +  CcosrReg.CLKO1_DIV = 0;
> +  CcosrReg.CLKO1_EN = 1;
> +
> +  MmioWrite32 ((UINTN)&pCcmReg->CCOSR, CcosrReg.AsUint32);
> +  // Set GPIO05 alt config to ALT3 (CCM_CLKO1).
> +  // This clock drives the master clock for the audio codec.
> +  ImxPadConfig (IMX_PAD_GPIO_5, IMX_PAD_CFG_GPIO_5_CCM_CLKO1);
> +
> +  // Set alt config for KEY_COL0, KEY_ROW0, KEY_COL1 to ALT2 (AUD5_TXC/TXD/TXFS)
> +  // DSP_DAT19 is set to ALT3 for AUD5_RXD.
> +  ImxPadConfig (IMX_PAD_KEY_COL0, IMX_PAD_CFG_KEY_COL0_AUD5_TXC);
> +  ImxPadConfig (IMX_PAD_KEY_ROW0, IMX_PAD_CFG_KEY_ROW0_AUD5_TXD);
> +  ImxPadConfig (IMX_PAD_KEY_COL1, IMX_PAD_CFG_KEY_COL1_AUD5_TXFS);
> +  ImxPadConfig (IMX_PAD_DISP0_DAT19, IMX_PAD_CFG_DISP0_DAT19_AUD5_RXD);
> +}
> +
> +/**
> +  Initialize clock and power for modules on the SoC.
> +**/
> +VOID
> +ImxClkPwrInit (
> +  VOID
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  GateUnusedClocks();
> +  UngateRequiredClocks();
> +
> +  if (FeaturePcdGet (PcdGpuEnable)) {
> +    Status = ImxClkPwrGpuEnable ();
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    Status = ImxClkPwrIpuLDBxEnable ();
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +
> +  Status = ImxClkPwrIpuDIxEnable();
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ASSERT_EFI_ERROR (ImxClkPwrValidateClocks ());
> +}
> +
> +/**
> +  Initialize SDHC modules on the SOC and perform required pin-muxing
> +**/
> +VOID
> +SdhcInit (
> +  VOID
> +  )
> +{
> +  // uSDHC2: SDCard Socket
> +  ImxPadConfig (IMX_PAD_SD2_CLK, IMX_PAD_CFG_SD2_CLK_SD2_CLK);
> +  ImxPadConfig (IMX_PAD_SD2_CMD, IMX_PAD_CFG_SD2_CMD_SD2_CMD);
> +  ImxPadConfig (IMX_PAD_SD2_DAT0, IMX_PAD_CFG_SD2_DAT0_SD2_DATA0);
> +  ImxPadConfig (IMX_PAD_SD2_DAT1, IMX_PAD_CFG_SD2_DAT1_SD2_DATA1);
> +  ImxPadConfig (IMX_PAD_SD2_DAT2, IMX_PAD_CFG_SD2_DAT2_SD2_DATA2);
> +  ImxPadConfig (IMX_PAD_SD2_DAT3, IMX_PAD_CFG_SD2_DAT3_SD2_DATA3);
> +  ImxPadConfig (IMX_PAD_GPIO_4, IMX_PAD_CFG_GPIO_4_SD2_CD_B);
> +  ImxPadConfig (IMX_PAD_KEY_ROW1, IMX_PAD_CFG_KEY_ROW1_SD2_VSELECT);
> +
> +#if DEBUG

Hmm. #if DEBUG and #ifdef DEBUG appears to be used somewhat
interchangingly.
On the whole, although I haven't mentioned it before, I would also
prefer to see "#if !defined(MDEPKG_NDEBUG)" - more idiomatic.

You can then add
GCC:RELEASE_*_*_CC_FLAGS  = -DMDEPKG_NDEBUG
to the platform/SoC .dsc(.inc).

> +  DEBUG ((DEBUG_INIT, "uSDHC2 PAD Config:\n"));
> +  ImxPadDumpConfig ("CLK", IMX_PAD_SD2_CLK);
> +  ImxPadDumpConfig ("CMD", IMX_PAD_SD2_CMD);
> +  ImxPadDumpConfig ("DAT0", IMX_PAD_SD2_DAT0);
> +  ImxPadDumpConfig ("DAT1", IMX_PAD_SD2_DAT1);
> +  ImxPadDumpConfig ("DAT2", IMX_PAD_SD2_DAT2);
> +  ImxPadDumpConfig ("DAT3", IMX_PAD_SD2_DAT3);
> +  ImxPadDumpConfig ("VSELECT", IMX_PAD_KEY_ROW1);
> +  ImxPadDumpConfig ("CD", IMX_PAD_GPIO_4);
> +#endif // DEBUG
> +
> +  // Power-on SDCard through the GPIO signal connected to
> +  // Q1 MOSFET Gate acting as a switch to SDCard VDD supply voltage
> +  ImxPadConfig (IMX_PAD_DISP0_DAT9, IMX_PAD_CFG_DISP0_DAT9_GPIO4_IO30);
> +  ImxGpioDirection (IMX_GPIO_BANK4, 30, IMX_GPIO_DIR_OUTPUT);
> +  ImxGpioWrite (IMX_GPIO_BANK4, 30, IMX_GPIO_LOW);
> +
> +  // Pre-configure the GPIO ALT5 of all SD2_* pads to be input pins.
> +  // SD2_CLK: GPIO1_IO10
> +  ImxGpioDirection (IMX_GPIO_BANK1, 10, IMX_GPIO_DIR_INPUT);
> +
> +  // SD2_CMD: GPIO1_IO11
> +  ImxGpioDirection (IMX_GPIO_BANK1, 11, IMX_GPIO_DIR_INPUT);
> +
> +  // SD2_DATA0: GPIO1_IO15
> +  ImxGpioDirection (IMX_GPIO_BANK1, 15, IMX_GPIO_DIR_INPUT);
> +
> +  // SD2_DATA1: GPIO1_IO14
> +  ImxGpioDirection (IMX_GPIO_BANK1, 14, IMX_GPIO_DIR_INPUT);
> +
> +  // SD2_DATA2: GPIO1_IO13
> +  ImxGpioDirection (IMX_GPIO_BANK1, 13, IMX_GPIO_DIR_INPUT);
> +
> +  // SD2_DATA3: GPIO1_IO12
> +  ImxGpioDirection (IMX_GPIO_BANK1, 12, IMX_GPIO_DIR_INPUT);
> +
> +  // uSDHC3: eMMC Socket
> +  ImxPadConfig (IMX_PAD_SD3_CLK, IMX_PAD_CFG_SD3_CLK_SD3_CLK);
> +  ImxPadConfig (IMX_PAD_SD3_CMD, IMX_PAD_CFG_SD3_CMD_SD3_CMD);
> +  ImxPadConfig (IMX_PAD_SD3_RST, IMX_PAD_CFG_SD3_RST_SD3_RST);
> +  ImxPadConfig (IMX_PAD_SD3_DAT0, IMX_PAD_CFG_SD3_DAT0_SD3_DATA0);
> +  ImxPadConfig (IMX_PAD_SD3_DAT1, IMX_PAD_CFG_SD3_DAT1_SD3_DATA1);
> +  ImxPadConfig (IMX_PAD_SD3_DAT2, IMX_PAD_CFG_SD3_DAT2_SD3_DATA2);
> +  ImxPadConfig (IMX_PAD_SD3_DAT3, IMX_PAD_CFG_SD3_DAT3_SD3_DATA3);
> +  ImxPadConfig (IMX_PAD_SD3_DAT4, IMX_PAD_CFG_SD3_DAT4_SD3_DATA4);
> +  ImxPadConfig (IMX_PAD_SD3_DAT5, IMX_PAD_CFG_SD3_DAT5_SD3_DATA5);
> +  ImxPadConfig (IMX_PAD_SD3_DAT6, IMX_PAD_CFG_SD3_DAT6_SD3_DATA6);
> +  ImxPadConfig (IMX_PAD_SD3_DAT7, IMX_PAD_CFG_SD3_DAT7_SD3_DATA7);
> +}
> +
> +/**
> +  Initialize EHCI modules on the SOC and perform required pin-muxing.
> +  This routine also initializes PHY0(OTG) and PHY1 (USBH1).
> +**/
> +VOID
> +EhciInit (
> +  VOID
> +  )
> +{
> +  volatile IMX_IOMUXC_GPR_REGISTERS   *pIoMuxGprReg;
> +  IMX_IOMUXC_GPR1_REG                 IoMuxGpr1Reg;
> +
> +  // Pin-mux OTG Over Current
> +  ImxPadConfig (IMX_PAD_KEY_COL4, IMX_PAD_CFG_KEY_COL4_USB_OTG_OC);
> +
> +  // Pin-mux and enable OTG power
> +  ImxPadConfig (IMX_PAD_EIM_D22, IMX_PAD_CFG_EIM_DATA22_GPIO3_IO22_USB_OTG_PWR);
> +  ImxGpioDirection (IMX_GPIO_BANK3, 22, IMX_GPIO_DIR_OUTPUT);
> +  ImxGpioWrite (IMX_GPIO_BANK3, 22, IMX_GPIO_HIGH);
> +
> +  // Pin-mux and configure USB_OTG_ID as HOST
> +  ImxPadConfig (IMX_PAD_GPIO_1, IMX_PAD_CFG_GPIO01_USB_OTG_ID_HOST);
> +
> +  // Configure USB_OTG_ID pin
> +  pIoMuxGprReg = (IMX_IOMUXC_GPR_REGISTERS *) IOMUXC_GPR_BASE_ADDRESS;
> +  IoMuxGpr1Reg = (IMX_IOMUXC_GPR1_REG) MmioRead32 ((UINTN)&pIoMuxGprReg->GPR1);
> +  IoMuxGpr1Reg.USB_OTG_ID_SEL = IMX_IOMUXC_GPR1_USB_OTG_ID_SEL_GPIO_1;
> +  MmioWrite32 ((UINTN)&pIoMuxGprReg->GPR1, IoMuxGpr1Reg.AsUint32);
> +
> +  // Pin-mux and enable USBH1 power
> +  ImxPadConfig (IMX_PAD_GPIO_0, IMX_PAD_CFG_GPIO0_GPIO1_IO0_USBH1_PWR);
> +  ImxGpioDirection (IMX_GPIO_BANK1, 0, IMX_GPIO_DIR_OUTPUT);
> +  ImxGpioWrite (IMX_GPIO_BANK1, 0, IMX_GPIO_HIGH);
> +
> +  // Initialize PHY0 (OTG)
> +  ImxUsbPhyInit (IMX_USBPHY0);
> +
> +  // Initialize PHY1 (USBH1)
> +  ImxUsbPhyInit (IMX_USBPHY1);
> +}
> +
> +/**
> +  Initialize I2C modules on the SOC and perform required pin-muxing
> +**/
> +VOID
> +I2cInit (
> +  VOID
> +  )
> +{
> +  // Enable 1.8V and 3.3V power rails for sensors connected to I2C1.
> +  // The SENSOR_PWR_EN on EIM_EB3 line powers the pullups on I2c1.
> +  ImxPadConfig (IMX_PAD_EIM_EB3, IMX_PAD_CFG_EIM_EB3_GPIO2_IO31);
> +  ImxGpioDirection (IMX_GPIO_BANK2, 31, IMX_GPIO_DIR_OUTPUT);
> +  ImxGpioWrite (IMX_GPIO_BANK2, 31, IMX_GPIO_HIGH); // set GPIO2_IO31 to 1
> +  DEBUG ((DEBUG_INFO, "%a: Mux IMX_PAD_EIM_EB3 to GPIO Alt5. Set GPIO2_IO31\n",
> +          __FUNCTION__));
> +
> +  // Configure I2C1. EIM_D21 is I2C1_SCL and EIM_D28 is I2C1_SDA. Alt6, Alt1
> +  ImxPadConfig (IMX_PAD_EIM_D21, IMX_PAD_CFG_EIM_D21_I2C1_SCL);
> +  ImxPadConfig (IMX_PAD_EIM_D28, IMX_PAD_CFG_EIM_D28_I2C1_SDA);
> +  DEBUG ((DEBUG_INFO, "%a: I2C1 pin muxed via EIM D28,21\n", __FUNCTION__));
> +
> +  // I2C2 is used by GOP/Windows display driver. Do not configure I2C2 SCL via KEY_COL3, SDA via KEY_ROW3
> +
> +  // Configure I2C3 SCL via EIM_D17, SDA via EIM_D18. Inputs Alt6
> +  ImxPadConfig (IMX_PAD_EIM_D17, IMX_PAD_CFG_EIM_D17_I2C3_SCL);
> +  ImxPadConfig (IMX_PAD_EIM_D18, IMX_PAD_CFG_EIM_D18_I2C3_SDA);
> +  DEBUG ((DEBUG_INFO, "%a: I2C3 pin muxed EIM_D17, 18\n", __FUNCTION__));
> +}
> +
> +/**
> +  Initialize SPI modules on the SOC and perform required pin-muxing
> +**/
> +VOID
> +SpiInit (
> +  VOID
> +  )
> +{
> +  UINT32  RegValue;
> +  // On Hummingboard only ESPI2 is exposed.
> +  // Configure the return path for ECSPI2_MISO
> +  RegValue = MmioRead32 (IOMUXC_ECSPI2_MISO_SELECT_INPUT);
> +  RegValue &= ~3;

A #define for that 3?

> +  RegValue |= (IMX_IOMUXC_ECSPI2_MISO_EIM_OE_B_ALT2 << 0);

That << 0 doesn't really add any clarity.

> +  MmioWrite32 (IOMUXC_ECSPI2_MISO_SELECT_INPUT, RegValue);
> +}
> +
> +/**
> +  Initialize PCI Express module on the SOC and perform required pin-muxing
> +**/
> +VOID
> +PcieInit (
> +  VOID
> +  )
> +{
> +  // PCIe GPIO Reset
> +  ImxPadConfig (IMX_PAD_SD4_DAT3, IMX_PAD_CFG_SD4_DATA3_GPIO2_IO11);
> +  ImxGpioDirection (IMX_GPIO_BANK2, 11, IMX_GPIO_DIR_OUTPUT);
> +  ImxGpioWrite (IMX_GPIO_BANK2, 11, IMX_GPIO_LOW);
> +}
> +
> +/**
> +  Initialize exposed GPIO pins on carrier board. By default some
> +  pins are set to CMOS inputs while others are set to Schmitt
> +  triggers.  Normalize them all to Schmitt trigger inputs by setting
> +  the hysteresis bit (16) in the pad ctl register.
> +**/
> +VOID
> +GpioInit (
> +  VOID
> +  )
> +{
> +  UINT32  i;
> +  IMX_PAD CurPad;
> +
> +  for (i = 0; i < sizeof (GpioPins) / sizeof (IMX_PAD); ++i) {
> +    CurPad = GpioPins[i];
> +    MmioOr32 (IMX_IOMUXC_BASE + _IMX_PAD_CTL_OFFSET (CurPad), 1 << 16);

A #define for that 1 << 16?

> +  }
> +}
> +
> +/**
> +  Initalize the PWM controllers
> +  PWM1 is exposed through Mikrobus header
> +  Pinmux pad DISP0_DAT8 to (ALT2) PWM1_OUT
> +**/
> +VOID
> +PwmInit (
> +  VOID
> +  )
> +{
> +  ImxPadConfig (IMX_PAD_DISP0_DAT8, IMX_PAD_CFG_DISP0_DAT8_PWM1_OUT);
> +}
> +
> +/**
> +    Initalize the UART controllers
> +**/
> +VOID
> +UartInit (
> +  VOID
> +  )
> +{
> +  // UARTs share same Clock:
> +  // PLL3 (480 MHz) -> pll3_sw_clk -> CG -> /6 -> uart_clk_root = 80 MHz
> +  ImxClkPwrSetClockGates (
> +    UartClockGatesToTurnOn,
> +    sizeof (UartClockGatesToTurnOn) / sizeof (UartClockGatesToTurnOn[0]),

ARRAY_SIZE

> +    IMX_CLOCK_GATE_STATE_ON);
> +
> +  // Configure pin mux for UART 1 and UART 3
> +  ImxPadConfig (IMX_PAD_CSI0_DAT11, IMX_PAD_UART1_RX_DATA);
> +  ImxPadConfig (IMX_PAD_CSI0_DAT10, IMX_PAD_UART1_TX_DATA);
> +  ImxPadConfig (IMX_PAD_EIM_D25, IMX_PAD_UART3_RX_DATA);
> +  ImxPadConfig (IMX_PAD_EIM_D24, IMX_PAD_UART3_TX_DATA);
> +
> +  SerialPortInitialize ();
> +  SerialPortWrite (
> +    (UINT8 *)SERIAL_DEBUG_PORT_INIT_MSG,
> +    (UINTN)sizeof (SERIAL_DEBUG_PORT_INIT_MSG));
> +}
> +
> +/**
> +    Initialize the TPM2 control area.
> +**/
> +VOID
> +Tpm2AcpiControlAreaInit (
> +  VOID
> +  )
> +{
> +  EFI_TPM2_ACPI_CONTROL_AREA  *pControlArea;
> +  EFI_PHYSICAL_ADDRESS        BaseAddress;
> +  UINT32                      BufferSize;
> +
> +  BaseAddress = PcdGet64 (PcdTpm2AcpiBufferBase);
> +  BufferSize = PcdGet32 (PcdTpm2AcpiBufferSize);
> +
> +  if ((BaseAddress == 0) || (BufferSize == 0)) {
> +    // TPM not enabled
> +    return;
> +  }
> +
> +  ASSERT (BufferSize >= EFI_PAGE_SIZE * 3);
> +
> +  pControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *) ((UINTN)BaseAddress);
> +  ZeroMem (pControlArea, sizeof (EFI_TPM2_ACPI_CONTROL_AREA));
> +  BufferSize = EFI_PAGE_SIZE;
> +  pControlArea->Command = (UINT64) ((UINTN) (pControlArea + 1));
> +  pControlArea->CommandSize = BufferSize;
> +  pControlArea->Response = pControlArea->Command + BufferSize;
> +  pControlArea->ResponseSize = BufferSize;
> +}
> +
> +/**
> +  Initalize LVDS
> +**/
> +VOID
> +LvdsInit (
> +  VOID
> +  )
> +{
> +  volatile IMX_CCM_REGISTERS  *pCcmReg;
> +  IMX_CCM_CCGR3_REG           Ccgr3Reg;
> +
> +  pCcmReg = (IMX_CCM_REGISTERS *) IMX_CCM_BASE;
> +  Ccgr3Reg = (IMX_CCM_CCGR3_REG) MmioRead32 ((UINTN) &pCcmReg->CCGR[3]);
> +  Ccgr3Reg.ldb_di0_clk_enable = 0x3;
> +  MmioWrite32 ((UINTN) &pCcmReg->CCGR[3], Ccgr3Reg.AsUint32);
> +
> +  // initalize backlight pin
> +  ImxPadConfig (IMX_PAD_SD4_DAT1, IMX_PAD_CFG_SD4_DATA1_GPIO2_IO09);
> +  ImxGpioDirection (IMX_GPIO_BANK2, 9, IMX_GPIO_DIR_OUTPUT);
> +  ImxGpioWrite (IMX_GPIO_BANK2, 9, IMX_GPIO_HIGH);
> +}
> +
> +/**
> +  Initialize controllers that must setup at the early stage for iMX6 Quad
> +**/
> +RETURN_STATUS
> +ArmPlatformInitialize (
> +  IN  UINTN                     MpId
> +  )
> +{
> +  if (!ArmPlatformIsPrimaryCore (MpId)) {
> +    return RETURN_SUCCESS;
> +  }
> +
> +  ImxClkPwrInit ();
> +
> +  // initialize default UEFI debug port early so we can use its debug output
> +  SerialPortInitialize ();
> +  SerialPortWrite (
> +    (UINT8 *)SERIAL_DEBUG_PORT_INIT_MSG,
> +    (UINTN)sizeof (SERIAL_DEBUG_PORT_INIT_MSG));
> +
> +  // Initialize timer early on because the following init path will be calling
> +  // delay functions. PrePi.c calls ArmPlatformInitialize before it calls
> +  // TimerConstructor to initialize the timer.
> +  TimerConstructor ();
> +
> +  SdhcInit ();
> +  EhciInit ();
> +  EnetInit ();
> +  I2cInit ();
> +  SpiInit ();
> +  PcieInit ();
> +  SetupAudio ();
> +  GpioInit ();
> +  PwmInit ();
> +
> +  if (FeaturePcdGet (PcdLvdsEnable)) {
> +    LvdsInit ();
> +  }
> +
> +  Tpm2AcpiControlAreaInit ();
> +
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Return the current Boot Mode
> +
> +  This function returns the boot reason on the platform
> +
> +**/
> +EFI_BOOT_MODE
> +ArmPlatformGetBootMode (
> +  VOID
> +  )
> +{
> +  return BOOT_WITH_FULL_CONFIGURATION;
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
> new file mode 100644
> index 000000000000..08ac78b16e8f
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
> @@ -0,0 +1,705 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#ifndef _IMX6_BOARD_INIT_H_
> +#define _IMX6_BOARD_INIT_H_
> +
> +#include <iMX6.h>
> +#include <iMX6ClkPwr.h>
> +#include <iMX6IoMux.h>
> +#include <iMX6Timer.h>
> +#include <iMX6UsbPhy.h>
> +
> +//  Prebaked pad configurations that include mux and drive settings where
> +//  each enum named as IMX_<MODULE-NAME>_PADCFG contains configurations
> +//  for pads used by that module
> +typedef enum {
> +  IMX_PAD_ENET_MDIO_ENET_MDIO = _IMX_MAKE_PADCFG (

Can you make the enum members CamelCase please?

> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_ENABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_PULL,
> +                                  IMX_PUS_100K_OHM_PU,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_ENET_MDIO_ALT1_ENET_MDIO),

Urgh, sorry, but I probably missed that as feedback on "Silicon/NXP:
Add i.MX6 SoC header files", but enum members CamelCase everywhere
please. (Enum and macro names upper-case and _.)

/
    Leif

> +
> +  IMX_PAD_ENET_MDC_ENET_MDC = _IMX_MAKE_PADCFG (
> +                                IMX_SRE_SLOW,
> +                                IMX_DSE_40_OHM,
> +                                IMX_SPEED_MEDIUM,
> +                                IMX_ODE_DISABLE,
> +                                IMX_PKE_DISABLE,
> +                                IMX_PUE_PULL,
> +                                IMX_PUS_100K_OHM_PU,
> +                                IMX_HYS_ENABLED,
> +                                IMX_SION_DISABLED,
> +                                IMX_IOMUXC_ENET_MDC_ALT1_ENET_MDC),
> +
> +  IMX_PAD_CFG_KEY_ROW4_GPIO4_IO15 = _IMX_MAKE_PADCFG (
> +                                      IMX_SRE_SLOW,
> +                                      IMX_DSE_40_OHM,
> +                                      IMX_SPEED_MEDIUM,
> +                                      IMX_ODE_DISABLE,
> +                                      IMX_PKE_DISABLE,
> +                                      IMX_PUE_PULL,
> +                                      IMX_PUS_100K_OHM_PD,
> +                                      IMX_HYS_ENABLED,
> +                                      IMX_SION_DISABLED,
> +                                      IMX_IOMUXC_KEY_ROW4_ALT5_GPIO4_IO15),
> +
> +  IMX_PAD_DI0_PIN2_GPIO4_IO18 = _IMX_MAKE_PADCFG (
> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_DISABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_PULL,
> +                                  IMX_PUS_100K_OHM_PD,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_DI0_PIN2_ALT5_GPIO4_IO18),
> +
> +  IMX_PAD_GPIO_16_ENET_REF_CLK = _IMX_MAKE_PADCFG_INPSEL (
> +                                   IMX_SRE_SLOW,
> +                                   IMX_DSE_40_OHM,
> +                                   IMX_SPEED_MEDIUM,
> +                                   IMX_ODE_DISABLE,
> +                                   IMX_PKE_DISABLE,
> +                                   IMX_PUE_PULL,
> +                                   IMX_PUS_100K_OHM_PU,
> +                                   IMX_HYS_ENABLED,
> +                                   IMX_SION_DISABLED,
> +                                   IMX_IOMUXC_GPIO_16_ALT2_ENET_REF_CLK,
> +                                   IOMUXC_ENET_REF_CLK_SELECT_INPUT,
> +                                   GPIO16_ALT2),
> +
> +  IMX_PAD_RGMII_TXC_RGMII_TXC = _IMX_MAKE_PADCFG (
> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_DISABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_PULL,
> +                                  IMX_PUS_100K_OHM_PU,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_RGMII_TXC_ALT1_RGMII_TXC),
> +
> +  IMX_PAD_RGMII_TD0_RGMII_TD0 = _IMX_MAKE_PADCFG (
> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_DISABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_KEEP,
> +                                  IMX_PUS_100K_OHM_PU,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_RGMII_TD0_ALT1_RGMII_TD0),
> +
> +  IMX_PAD_RGMII_TD1_RGMII_TD1 = _IMX_MAKE_PADCFG (
> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_DISABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_KEEP,
> +                                  IMX_PUS_100K_OHM_PU,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_RGMII_TD1_ALT1_RGMII_TD1),
> +
> +  IMX_PAD_RGMII_TD2_RGMII_TD2 = _IMX_MAKE_PADCFG (
> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_DISABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_KEEP,
> +                                  IMX_PUS_100K_OHM_PU,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_RGMII_TD2_ALT1_RGMII_TD2),
> +
> +  IMX_PAD_RGMII_TD3_RGMII_TD3 = _IMX_MAKE_PADCFG (
> +                                  IMX_SRE_SLOW,
> +                                  IMX_DSE_40_OHM,
> +                                  IMX_SPEED_MEDIUM,
> +                                  IMX_ODE_DISABLE,
> +                                  IMX_PKE_DISABLE,
> +                                  IMX_PUE_KEEP,
> +                                  IMX_PUS_100K_OHM_PU,
> +                                  IMX_HYS_ENABLED,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_RGMII_TD3_ALT1_RGMII_TD3),
> +
> +  IMX_PAD_RGMII_TX_CTL_RGMII_TX_CTL = _IMX_MAKE_PADCFG (
> +                                        IMX_SRE_SLOW,
> +                                        IMX_DSE_40_OHM,
> +                                        IMX_SPEED_MEDIUM,
> +                                        IMX_ODE_DISABLE,
> +                                        IMX_PKE_DISABLE,
> +                                        IMX_PUE_PULL,
> +                                        IMX_PUS_100K_OHM_PU,
> +                                        IMX_HYS_ENABLED,
> +                                        IMX_SION_DISABLED,
> +                                        IMX_IOMUXC_RGMII_TX_CTL_ALT1_RGMII_TX_CTL),
> +
> +  IMX_PAD_ENET_REF_CLK_ENET_REF_CLK = _IMX_MAKE_PADCFG (
> +                                        IMX_SRE_FAST,
> +                                        IMX_DSE_40_OHM,
> +                                        IMX_SPEED_MEDIUM,
> +                                        IMX_ODE_DISABLE,
> +                                        IMX_PKE_DISABLE,
> +                                        IMX_PUE_KEEP,
> +                                        IMX_PUS_100K_OHM_PD,
> +                                        IMX_HYS_DISABLED,
> +                                        IMX_SION_DISABLED,
> +                                        IMX_IOMUXC_ENET_REF_CLK_ALT1_ENET_TX_CLK),
> +
> +  IMX_PAD_RGMII_RXC_ENET_RGMII_RXC = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_DISABLE,
> +                                       IMX_PUE_KEEP,
> +                                       IMX_PUS_100K_OHM_PU,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_RGMII_RXC_ALT1_RGMII_RXC),
> +
> +  IMX_PAD_RGMII_RD0_ENET_RGMII_RD0 = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_DISABLE,
> +                                       IMX_PUE_KEEP,
> +                                       IMX_PUS_100K_OHM_PD,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_RGMII_RD0_ALT1_RGMII_RD0),
> +
> +  IMX_PAD_RGMII_RD1_ENET_RGMII_RD1 = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_DISABLE,
> +                                       IMX_PUE_KEEP,
> +                                       IMX_PUS_100K_OHM_PD,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_RGMII_RD1_ALT1_RGMII_RD1),
> +
> +  IMX_PAD_RGMII_RD2_ENET_RGMII_RD2 = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_DISABLE,
> +                                       IMX_PUE_KEEP,
> +                                       IMX_PUS_100K_OHM_PU,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_RGMII_RD2_ALT1_RGMII_RD2),
> +
> +  IMX_PAD_RGMII_RD3_ENET_RGMII_RD3 = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_DISABLE,
> +                                       IMX_PUE_KEEP,
> +                                       IMX_PUS_100K_OHM_PU,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_RGMII_RD3_ALT1_RGMII_RD3),
> +
> +  IMX_PAD_RGMII_RX_CTL_RGMII_RX_CTL = _IMX_MAKE_PADCFG (
> +                                        IMX_SRE_SLOW,
> +                                        IMX_DSE_40_OHM,
> +                                        IMX_SPEED_MEDIUM,
> +                                        IMX_ODE_DISABLE,
> +                                        IMX_PKE_DISABLE,
> +                                        IMX_PUE_KEEP,
> +                                        IMX_PUS_100K_OHM_PD,
> +                                        IMX_HYS_ENABLED,
> +                                        IMX_SION_DISABLED,
> +                                        IMX_IOMUXC_RGMII_RX_CTL_ALT1_RGMII_RX_CTL),
> +} IMX_ENET_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_CFG_EIM_DATA22_GPIO3_IO22_USB_OTG_PWR = _IMX_MAKE_PADCFG (
> +                                                    IMX_SRE_SLOW,
> +                                                    IMX_DSE_40_OHM,
> +                                                    IMX_SPEED_MEDIUM,
> +                                                    IMX_ODE_DISABLE,
> +                                                    IMX_PKE_ENABLE,
> +                                                    IMX_PUE_PULL,
> +                                                    IMX_PUS_100K_OHM_PU,
> +                                                    IMX_HYS_ENABLED,
> +                                                    IMX_SION_DISABLED,
> +                                                    IMX_IOMUXC_EIM_D22_ALT5_GPIO3_IO22),
> +
> +  IMX_PAD_CFG_KEY_COL4_USB_OTG_OC = _IMX_MAKE_PADCFG_INPSEL (
> +                                      IMX_SRE_SLOW,
> +                                      IMX_DSE_40_OHM,
> +                                      IMX_SPEED_LOW,
> +                                      IMX_ODE_DISABLE,
> +                                      IMX_PKE_ENABLE,
> +                                      IMX_PUE_PULL,
> +                                      IMX_PUS_100K_OHM_PU,
> +                                      IMX_HYS_ENABLED,
> +                                      IMX_SION_DISABLED,
> +                                      IMX_IOMUXC_KEY_COL4_ALT2_USB_OTG_OC,
> +                                      IOMUXC_USB_OTG_OC_SELECT_INPUT,
> +                                      KEY_COL4_ALT2),
> +
> +  IMX_PAD_CFG_GPIO0_GPIO1_IO0_USBH1_PWR = _IMX_MAKE_PADCFG (
> +                                            IMX_SRE_SLOW,
> +                                            IMX_DSE_40_OHM,
> +                                            IMX_SPEED_MEDIUM,
> +                                            IMX_ODE_DISABLE,
> +                                            IMX_PKE_ENABLE,
> +                                            IMX_PUE_PULL,
> +                                            IMX_PUS_100K_OHM_PU,
> +                                            IMX_HYS_ENABLED,
> +                                            IMX_SION_DISABLED,
> +                                            IMX_IOMUXC_GPIO_0_ALT5_GPIO1_IO00),
> +
> +  IMX_PAD_CFG_GPIO01_USB_OTG_ID_HOST = _IMX_MAKE_PADCFG (
> +                                         IMX_SRE_FAST,
> +                                         IMX_DSE_90_OHM,
> +                                         IMX_SPEED_MEDIUM,
> +                                         IMX_ODE_DISABLE,
> +                                         IMX_PKE_ENABLE,
> +                                         IMX_PUE_PULL,
> +                                         IMX_PUS_100K_OHM_PD,
> +                                         IMX_HYS_ENABLED,
> +                                         IMX_SION_DISABLED,
> +                                         IMX_IOMUXC_GPIO_1_ALT3_USB_OTG_ID),
> +
> +  IMX_PAD_CFG_GPIO01_USB_OTG_ID_DEVICE = _IMX_MAKE_PADCFG (
> +                                           IMX_SRE_FAST,
> +                                           IMX_DSE_90_OHM,
> +                                           IMX_SPEED_MEDIUM,
> +                                           IMX_ODE_DISABLE,
> +                                           IMX_PKE_ENABLE,
> +                                           IMX_PUE_PULL,
> +                                           IMX_PUS_100K_OHM_PU,
> +                                           IMX_HYS_ENABLED,
> +                                           IMX_SION_DISABLED,
> +                                           IMX_IOMUXC_GPIO_1_ALT3_USB_OTG_ID),
> +} IMX_EHCI_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_CFG_SD4_DATA3_GPIO2_IO11 = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_ENABLE,
> +                                       IMX_PUE_PULL,
> +                                       IMX_PUS_100K_OHM_PU,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_SD4_DAT3_ALT5_GPIO2_IO11),
> +} IMX_IMX6Q_PCIE_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_CFG_EIM_EB3_GPIO2_IO31 = _IMX_MAKE_PADCFG (
> +                                     IMX_SRE_SLOW,
> +                                     IMX_DSE_260_OHM,
> +                                     IMX_SPEED_LOW,
> +                                     IMX_ODE_DISABLE,
> +                                     IMX_PKE_DISABLE,
> +                                     IMX_PUE_PULL,
> +                                     IMX_PUS_100K_OHM_PU,
> +                                     IMX_HYS_DISABLED,
> +                                     IMX_SION_ENABLED,
> +                                     IMX_IOMUXC_EIM_EB3_ALT5_GPIO2_IO31),
> +
> +  IMX_PAD_CFG_EIM_D21_I2C1_SCL = _IMX_MAKE_PADCFG_INPSEL (
> +                                   IMX_SRE_FAST,
> +                                   IMX_DSE_40_OHM,
> +                                   IMX_SPEED_MEDIUM,
> +                                   IMX_ODE_ENABLE,
> +                                   IMX_PKE_ENABLE,
> +                                   IMX_PUE_PULL,
> +                                   IMX_PUS_47K_OHM_PU,
> +                                   IMX_HYS_ENABLED,
> +                                   IMX_SION_ENABLED,
> +                                   IMX_IOMUXC_EIM_D21_ALT6_I2C1_SCL,
> +                                   IOMUXC_I2C1_SCL_IN_SELECT_INPUT,
> +                                   EIM_DATA21_ALT6),
> +
> +  IMX_PAD_CFG_EIM_D28_I2C1_SDA = _IMX_MAKE_PADCFG_INPSEL (
> +                                   IMX_SRE_FAST,
> +                                   IMX_DSE_40_OHM,
> +                                   IMX_SPEED_MEDIUM,
> +                                   IMX_ODE_ENABLE,
> +                                   IMX_PKE_ENABLE,
> +                                   IMX_PUE_PULL,
> +                                   IMX_PUS_47K_OHM_PU,
> +                                   IMX_HYS_ENABLED,
> +                                   IMX_SION_ENABLED,
> +                                   IMX_IOMUXC_EIM_D28_ALT1_I2C1_SDA,
> +                                   IOMUXC_I2C1_SDA_IN_SELECT_INPUT,
> +                                   EIM_DATA28_ALT1),
> +
> +  IMX_PAD_CFG_EIM_D17_I2C3_SCL = _IMX_MAKE_PADCFG_INPSEL (
> +                                   IMX_SRE_FAST,
> +                                   IMX_DSE_40_OHM,
> +                                   IMX_SPEED_MEDIUM,
> +                                   IMX_ODE_ENABLE,
> +                                   IMX_PKE_ENABLE,
> +                                   IMX_PUE_PULL,
> +                                   IMX_PUS_47K_OHM_PU,
> +                                   IMX_HYS_ENABLED,
> +                                   IMX_SION_ENABLED,
> +                                   IMX_IOMUXC_EIM_D17_ALT6_I2C3_SCL,
> +                                   IOMUXC_I2C3_SCL_IN_SELECT_INPUT,
> +                                   EIM_DATA17_ALT6),
> +
> +  IMX_PAD_CFG_EIM_D18_I2C3_SDA = _IMX_MAKE_PADCFG_INPSEL (
> +                                   IMX_SRE_FAST,
> +                                   IMX_DSE_40_OHM,
> +                                   IMX_SPEED_MEDIUM,
> +                                   IMX_ODE_ENABLE,
> +                                   IMX_PKE_ENABLE,
> +                                   IMX_PUE_PULL,
> +                                   IMX_PUS_47K_OHM_PU,
> +                                   IMX_HYS_ENABLED,
> +                                   IMX_SION_ENABLED,
> +                                   IMX_IOMUXC_EIM_D18_ALT6_I2C3_SDA,
> +                                   IOMUXC_I2C3_SDA_IN_SELECT_INPUT,
> +                                   EIM_DATA18_ALT6),
> +} IMX_I2C_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_CFG_GPIO_5_CCM_CLKO1 = _IMX_MAKE_PADCFG (
> +                                   IMX_SRE_SLOW,
> +                                   IMX_DSE_40_OHM,
> +                                   IMX_SPEED_MEDIUM,
> +                                   IMX_ODE_DISABLE,
> +                                   IMX_PKE_ENABLE,
> +                                   IMX_PUE_PULL,
> +                                   IMX_PUS_100K_OHM_PU,
> +                                   IMX_HYS_ENABLED,
> +                                   IMX_SION_DISABLED,
> +                                   IMX_IOMUXC_GPIO_5_ALT3_CCM_CLKO1),
> +
> +  IMX_PAD_CFG_KEY_COL0_AUD5_TXC = _IMX_MAKE_PADCFG_INPSEL (
> +                                    IMX_SRE_SLOW,
> +                                    IMX_DSE_40_OHM,
> +                                    IMX_SPEED_MEDIUM,
> +                                    IMX_ODE_DISABLE,
> +                                    IMX_PKE_ENABLE,
> +                                    IMX_PUE_PULL,
> +                                    IMX_PUS_100K_OHM_PU,
> +                                    IMX_HYS_ENABLED,
> +                                    IMX_SION_DISABLED,
> +                                    IMX_IOMUXC_KEY_COL0_ALT2_AUD5_TXC,
> +                                    IOMUXC_AUD5_INPUT_TXCLK_AMX_SELECT_INPUT,
> +                                    KEY_COL0_ALT2),
> +
> +  IMX_PAD_CFG_KEY_ROW0_AUD5_TXD = _IMX_MAKE_PADCFG_INPSEL (
> +                                    IMX_SRE_SLOW,
> +                                    IMX_DSE_40_OHM,
> +                                    IMX_SPEED_MEDIUM,
> +                                    IMX_ODE_DISABLE,
> +                                    IMX_PKE_ENABLE,
> +                                    IMX_PUE_PULL,
> +                                    IMX_PUS_100K_OHM_PU,
> +                                    IMX_HYS_ENABLED,
> +                                    IMX_SION_DISABLED,
> +                                    IMX_IOMUXC_KEY_ROW0_ALT2_AUD5_TXD,
> +                                    IOMUXC_AUD5_INPUT_DB_AMX_SELECT_INPUT,
> +                                    KEY_ROW0_ALT2),
> +
> +  IMX_PAD_CFG_KEY_COL1_AUD5_TXFS = _IMX_MAKE_PADCFG_INPSEL (
> +                                     IMX_SRE_SLOW,
> +                                     IMX_DSE_40_OHM,
> +                                     IMX_SPEED_MEDIUM,
> +                                     IMX_ODE_DISABLE,
> +                                     IMX_PKE_ENABLE,
> +                                     IMX_PUE_PULL,
> +                                     IMX_PUS_100K_OHM_PU,
> +                                     IMX_HYS_ENABLED,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_KEY_COL1_ALT2_AUD5_TXFS,
> +                                     IOMUXC_AUD5_INPUT_TXFS_AMX_SELECT_INPUT,
> +                                     KEY_COL1_ALT2),
> +
> +  IMX_PAD_CFG_DISP0_DAT19_AUD5_RXD = _IMX_MAKE_PADCFG_INPSEL (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_ENABLE,
> +                                       IMX_PUE_PULL,
> +                                       IMX_PUS_100K_OHM_PU,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_DISP0_DAT19_ALT3_AUD5_RXD,
> +                                       IOMUXC_AUD5_INPUT_DA_AMX_SELECT_INPUT,
> +                                       DISP0_DATA19_ALT3),
> +} IMX_AUDIO_PADCFG;
> +
> +typedef enum {
> +  IMX_USDHC_CMD_PAD_CTL = _IMX_MAKE_PAD_CTL (
> +                            IMX_SRE_FAST,
> +                            IMX_DSE_33_OHM,
> +                            IMX_SPEED_MEDIUM,
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_ENABLE,
> +                            IMX_PUE_PULL,
> +                            IMX_PUS_47K_OHM_PU,
> +                            IMX_HYS_ENABLED),
> +
> +  IMX_USDHC_CLK_PAD_CTL = _IMX_MAKE_PAD_CTL (
> +                            IMX_SRE_FAST,
> +                            IMX_DSE_33_OHM,
> +                            IMX_SPEED_MEDIUM,
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_DISABLE,
> +                            0,
> +                            0,
> +                            IMX_HYS_ENABLED),
> +
> +  IMX_USDHC_DAT_PAD_CTL = _IMX_MAKE_PAD_CTL (
> +                            IMX_SRE_FAST,
> +                            IMX_DSE_33_OHM,
> +                            IMX_SPEED_MEDIUM,
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_ENABLE,
> +                            IMX_PUE_PULL,
> +                            IMX_PUS_47K_OHM_PU,
> +                            IMX_HYS_ENABLED),
> +
> +  IMX_USDHC_GPIO_PAD_CTL = _IMX_MAKE_PAD_CTL (
> +                             IMX_SRE_FAST,
> +                             IMX_DSE_33_OHM,
> +                             IMX_SPEED_LOW,
> +                             IMX_ODE_DISABLE,
> +                             IMX_PKE_DISABLE,
> +                             0,
> +                             0,
> +                             IMX_HYS_ENABLED),
> +
> +  IMX_USDHC_CD_PAD_CTL = _IMX_MAKE_PAD_CTL (
> +                           IMX_SRE_FAST,
> +                           IMX_DSE_33_OHM,
> +                           IMX_SPEED_LOW,
> +                           IMX_ODE_DISABLE,
> +                           IMX_PKE_ENABLE,
> +                           IMX_PUE_PULL,
> +                           IMX_PUS_47K_OHM_PU,
> +                           IMX_HYS_ENABLED),
> +
> +  IMX_PAD_CFG_SD2_CLK_SD2_CLK = _IMX_MAKE_PADCFG2 (
> +                                  IMX_USDHC_CLK_PAD_CTL,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_SD2_CLK_ALT0_SD2_CLK),
> +
> +  IMX_PAD_CFG_SD2_CMD_SD2_CMD = _IMX_MAKE_PADCFG2 (
> +                                  IMX_USDHC_CMD_PAD_CTL,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_SD2_CMD_ALT0_SD2_CMD),
> +
> +  IMX_PAD_CFG_SD2_DAT0_SD2_DATA0 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD2_DAT0_ALT0_SD2_DATA0),
> +
> +  IMX_PAD_CFG_SD2_DAT1_SD2_DATA1 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD2_DAT1_ALT0_SD2_DATA1),
> +
> +  IMX_PAD_CFG_SD2_DAT2_SD2_DATA2 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD2_DAT2_ALT0_SD2_DATA2),
> +
> +  IMX_PAD_CFG_SD2_DAT3_SD2_DATA3 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD2_DAT3_ALT0_SD2_DATA3),
> +
> +  IMX_PAD_CFG_KEY_ROW1_SD2_VSELECT = _IMX_MAKE_PADCFG2 (
> +                                       IMX_USDHC_GPIO_PAD_CTL,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_KEY_ROW1_ALT6_SD2_VSELECT),
> +
> +  IMX_PAD_CFG_GPIO_4_SD2_CD_B = _IMX_MAKE_PADCFG2 (
> +                                  IMX_USDHC_CD_PAD_CTL,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_GPIO_4_ALT6_SD2_CD_B),
> +
> +  IMX_PAD_CFG_DISP0_DAT9_GPIO4_IO30 = _IMX_MAKE_PADCFG2 (
> +                                        IMX_USDHC_GPIO_PAD_CTL,
> +                                        IMX_SION_DISABLED,
> +                                        IMX_IOMUXC_DISP0_DAT9_ALT5_GPIO4_IO30),
> +} IMX_USDHC2_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_CFG_SD3_CLK_SD3_CLK = _IMX_MAKE_PADCFG2 (
> +                                  IMX_USDHC_CLK_PAD_CTL,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_SD3_CLK_ALT0_SD3_CLK),
> +
> +  IMX_PAD_CFG_SD3_CMD_SD3_CMD = _IMX_MAKE_PADCFG2 (
> +                                  IMX_USDHC_CMD_PAD_CTL,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_SD3_CMD_ALT0_SD3_CMD),
> +
> +  IMX_PAD_CFG_SD3_RST_SD3_RST = _IMX_MAKE_PADCFG2 (
> +                                  IMX_USDHC_GPIO_PAD_CTL,
> +                                  IMX_SION_DISABLED,
> +                                  IMX_IOMUXC_SD3_RST_ALT0_SD3_RESET),
> +
> +  IMX_PAD_CFG_SD3_DAT0_SD3_DATA0 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT0_ALT0_SD3_DATA0),
> +
> +  IMX_PAD_CFG_SD3_DAT1_SD3_DATA1 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT1_ALT0_SD3_DATA1),
> +
> +  IMX_PAD_CFG_SD3_DAT2_SD3_DATA2 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT2_ALT0_SD3_DATA2),
> +
> +  IMX_PAD_CFG_SD3_DAT3_SD3_DATA3 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT3_ALT0_SD3_DATA3),
> +
> +  IMX_PAD_CFG_SD3_DAT4_SD3_DATA4 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT4_ALT0_SD3_DATA4),
> +
> +  IMX_PAD_CFG_SD3_DAT5_SD3_DATA5 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT5_ALT0_SD3_DATA5),
> +
> +  IMX_PAD_CFG_SD3_DAT6_SD3_DATA6 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT6_ALT0_SD3_DATA6),
> +
> +  IMX_PAD_CFG_SD3_DAT7_SD3_DATA7 = _IMX_MAKE_PADCFG2 (
> +                                     IMX_USDHC_DAT_PAD_CTL,
> +                                     IMX_SION_DISABLED,
> +                                     IMX_IOMUXC_SD3_DAT7_ALT0_SD3_DATA7),
> +} IMX_USDHC3_PADCFG;
> +
> +typedef enum {
> +  IMX_PWM_CLK_PAD_CTL = _IMX_MAKE_PAD_CTL (
> +                          IMX_SRE_FAST,
> +                          IMX_DSE_33_OHM,
> +                          IMX_SPEED_LOW,
> +                          IMX_ODE_DISABLE,
> +                          IMX_PKE_DISABLE,
> +                          0,
> +                          0,
> +                          IMX_HYS_ENABLED),
> +
> +  IMX_PAD_CFG_DISP0_DAT8_PWM1_OUT = _IMX_MAKE_PADCFG2 (
> +                                      IMX_PWM_CLK_PAD_CTL,
> +                                      IMX_SION_DISABLED,
> +                                      IMX_IOMUXC_DISP0_DAT8_ALT2_PWM1_OUT),
> +} IMX_PWM_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_UART1_RX_DATA = _IMX_MAKE_PADCFG_INPSEL (
> +                            IMX_SRE_SLOW,
> +                            IMX_DSE_40_OHM,     // 25 Ohm @ 3.3V, 40 Ohm @ 1.8V
> +                            IMX_SPEED_MEDIUM,   // 10 MEDIUM - 100, 150 MHz
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_ENABLE,       // 12 Pull/Keeper Enabled
> +                            IMX_PUE_PULL,         // 13 Pull Enabled
> +                            IMX_PUS_100K_OHM_PU,  // 14-15 100K Ohm Pull Up
> +                            IMX_HYS_ENABLED,
> +                            IMX_SION_DISABLED,
> +                            IMX_IOMUXC_CSI0_DAT11_ALT3_UART1_RX_DATA,
> +                            IOMUXC_UART1_UART_RX_DATA_SELECT_INPUT,
> +                            CSI0_DATA11_ALT3),
> +
> +  IMX_PAD_UART1_TX_DATA = _IMX_MAKE_PADCFG (
> +                            IMX_SRE_SLOW,
> +                            IMX_DSE_40_OHM,
> +                            IMX_SPEED_MEDIUM,
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_ENABLE,
> +                            IMX_PUE_PULL,
> +                            IMX_PUS_100K_OHM_PU,
> +                            IMX_HYS_ENABLED,
> +                            IMX_SION_DISABLED,
> +                            IMX_IOMUXC_CSI0_DAT10_ALT3_UART1_TX_DATA),
> +
> +  IMX_PAD_UART3_RX_DATA = _IMX_MAKE_PADCFG_INPSEL (
> +                            IMX_SRE_SLOW,
> +                            IMX_DSE_40_OHM,
> +                            IMX_SPEED_MEDIUM,
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_ENABLE,
> +                            IMX_PUE_PULL,
> +                            IMX_PUS_100K_OHM_PU,
> +                            IMX_HYS_ENABLED,
> +                            IMX_SION_DISABLED,
> +                            IMX_IOMUXC_EIM_D25_ALT2_UART3_RX_DATA,
> +                            IOMUXC_UART3_UART_RX_DATA_SELECT_INPUT,
> +                            EIM_DATA25_ALT2),
> +
> +  IMX_PAD_UART3_TX_DATA = _IMX_MAKE_PADCFG (
> +                            IMX_SRE_SLOW,
> +                            IMX_DSE_40_OHM,
> +                            IMX_SPEED_MEDIUM,
> +                            IMX_ODE_DISABLE,
> +                            IMX_PKE_ENABLE,
> +                            IMX_PUE_PULL,
> +                            IMX_PUS_100K_OHM_PU,
> +                            IMX_HYS_ENABLED,
> +                            IMX_SION_DISABLED,
> +                            IMX_IOMUXC_EIM_D24_ALT2_UART3_TX_DATA),
> +} IMX_UART_PADCFG;
> +
> +typedef enum {
> +  IMX_PAD_CFG_SD4_DATA1_GPIO2_IO09 = _IMX_MAKE_PADCFG (
> +                                       IMX_SRE_SLOW,
> +                                       IMX_DSE_40_OHM,
> +                                       IMX_SPEED_MEDIUM,
> +                                       IMX_ODE_DISABLE,
> +                                       IMX_PKE_ENABLE,
> +                                       IMX_PUE_PULL,
> +                                       IMX_PUS_100K_OHM_PU,
> +                                       IMX_HYS_ENABLED,
> +                                       IMX_SION_DISABLED,
> +                                       IMX_IOMUXC_SD4_DAT1_ALT5_GPIO2_IO09),
> +
> +} IMX_IMX6Q_LDB_PADCFG;
> +
> +#endif /* _IMX6_BOARD_INIT_H_ */
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
> new file mode 100644
> index 000000000000..687b9a59930d
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
> @@ -0,0 +1,91 @@
> +#/* @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#*/
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = iMX6BoardLib
> +  FILE_GUID                      = 736343a0-1d96-11e0-aaaa-0002a5d5c51b
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = ArmPlatformLib
> +  DEFINE BOARD_LIB_COMMON_DIR    = Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[LibraryClasses]
> +  ArmLib
> +  iMX6ClkPwrLib
> +  iMX6UsbPhyLib
> +  IoLib
> +  MemoryAllocationLib
> +  SerialPortLib
> +
> +[Sources.common]
> +  $(BOARD_LIB_COMMON_DIR)/iMX6BoardHelper.S    | GCC
> +  $(BOARD_LIB_COMMON_DIR)/iMX6BoardMem.c
> +  $(BOARD_LIB_COMMON_DIR)/iMX6QBoardCoreDef.c
> +  iMX6BoardInit.c
> +
> +[FeaturePcd]
> +  giMX6TokenSpaceGuid.PcdGpuEnable
> +  giMX6TokenSpaceGuid.PcdLvdsEnable
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdArmPrimaryCore
> +  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
> +  gArmTokenSpaceGuid.PcdFdBaseAddress
> +  gArmTokenSpaceGuid.PcdFdSize
> +  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
> +  gArmTokenSpaceGuid.PcdSystemMemoryBase
> +  gArmTokenSpaceGuid.PcdSystemMemorySize
> +
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount
> +
> +  giMX6TokenSpaceGuid.PcdFrameBufferBase
> +  giMX6TokenSpaceGuid.PcdFrameBufferSize
> +  giMX6TokenSpaceGuid.PcdSrcBase
> +
> +  giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange
> +
> +  #
> +  # TPM2 control area
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize
> +
> +  #
> +  # TrustZone private memory
> +  # This memory is managed privately by the OpTEE OS.
> +  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
> +  #    CFG_DDR_TEETZ_RESERVED_START & CFG_DDR_TEETZ_RESERVED_START
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemoryBase
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZonePrivateMemorySize
> +
> +  #
> +  # TrustZone shared memory
> +  # This memory is manager by the normal world but shared with the OpTEE OS.
> +  # It must match OpTEE optee_os/core/arch/arm/plat-imx/platform_config.h:
> +  #    CFG_SHMEM_START & CFG_SHMEM_SIZE
> +  #
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemoryBase
> +  gOpteeClientPkgTokenSpaceGuid.PcdTrustZoneSharedMemorySize
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 26/27] Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables
  2018-09-21  8:26 ` [PATCH edk2-platforms 26/27] Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables Chris Co
@ 2018-12-15 12:19   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-15 12:19 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Michael D Kinney, Ard Biesheuvel

On Fri, Sep 21, 2018 at 08:26:18AM +0000, Chris Co wrote:
> This adds ACPI table support for SolidRun's i.MX 6Quad Hummingboard Edge
> platform.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> ---
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf      |  55 ++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl            |  38 +++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl      |  71 ++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl |  33 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl        |  54 +++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl        |  32 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl        | 234 +++++++++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl       | 144 ++++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl        |  43 +++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl       | 198 +++++++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl        | 343 ++++++++++++++++++++
>  11 files changed, 1245 insertions(+)
> 
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
> new file mode 100644
> index 000000000000..2386c60d211d
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
> @@ -0,0 +1,55 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = PlatformAcpiTables
> +  FILE_GUID                      = 7E374E25-8E01-4FEE-87F2-390C23C606CD
> +  MODULE_TYPE                    = USER_DEFINED
> +  VERSION_STRING                 = 1.0
> +  DEFINE COMMON_ACPI_DIR         = Silicon/NXP/iMX6Pkg/AcpiTables
> +
> +[Sources]
> +  DSDT.asl
> +  $(COMMON_ACPI_DIR)/Csrt.aslc
> +  $(COMMON_ACPI_DIR)/Dbg2.aslc
> +  $(COMMON_ACPI_DIR)/Fadt.aslc
> +  $(COMMON_ACPI_DIR)/Madt.aslc
> +  $(COMMON_ACPI_DIR)/Mcfg.aslc
> +  $(COMMON_ACPI_DIR)/Tpm2.aslc
> +  $(COMMON_ACPI_DIR)/Spcr.aslc
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
> +  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
> +  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> +
> +[FixedPcd]
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount
> +
> +  gArmTokenSpaceGuid.PcdGicDistributorBase
> +  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
> +
> +  giMX6TokenSpaceGuid.PcdPcieDeviceConfigBase
> +  giMX6TokenSpaceGuid.PcdPcieHostConfigBase
> +
> +  giMXPlatformTokenSpaceGuid.PcdKdUartInstance
> +
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferBase
> +  gOpteeClientPkgTokenSpaceGuid.PcdTpm2AcpiBufferSize
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
> new file mode 100644
> index 000000000000..6e639bb838a6
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
> @@ -0,0 +1,38 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include "Dsdt-Common.h"
> +
> +#define SOC_TYPE 0x00000063  // iMX6 Quad

Is there no definition of this in a header we can use?

Other than that, I don't really have any further comments.

/
    Leif

> +
> +DefinitionBlock ("DSDT.aml", "DSDT", 5, "MSFT", "EDK2", 1)
> +{
> +  Scope (\_SB_) {
> +    include ("Dsdt-Platform.asl")
> +    include ("Dsdt-Gpio.asl")
> +    include ("Dsdt-Gfx.asl")
> +    include ("Dsdt-Usb.asl")
> +    include ("Dsdt-PCIe.asl")
> +    include ("Dsdt-Sdhc.asl")
> +    include ("Dsdt-Enet.asl")
> +    include ("Dsdt-Audio.asl")
> +    include ("Dsdt-AudioCodec.asl")
> +    include ("Dsdt-Uart.asl")
> +    include ("Dsdt-I2c.asl")
> +    include ("Dsdt-Spi.asl")
> +    include ("Dsdt-Rhp.asl")
> +    include ("Dsdt-Pwm.asl")
> +    include ("Dsdt-TrEE.asl")
> +  } // \_SB_
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
> new file mode 100644
> index 000000000000..23fbf5f52677
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
> @@ -0,0 +1,71 @@
> +/** @file
> +*
> +*  iMX6 Quad Synchronous Serial Interface (SSI)
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (SSI1)
> +{
> +  Name (_HID, "NXP010A")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02028000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 78 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SSI2)
> +{
> +  Name (_HID, "NXP010A")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0202C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 79 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SSI3)
> +{
> +  Name (_HID, "NXP010A")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02030000, 0x4000, )
> +      MEMORY32FIXED (ReadWrite, 0x021d8000, 0x38, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 80 }
> +      MsftFunctionConfig (Shared, PullDown, 0, "\\_SB.SSI3", 0, ResourceConsumer, ) { 7, 5 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
> new file mode 100644
> index 000000000000..8ab9bece73d7
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
> @@ -0,0 +1,33 @@
> +/** @file
> +*
> +*  iMX6 Quad Freescale SGTL5000 audio codec
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (ACDK)
> +{
> +  Name (_HID, "SGTL5000")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      I2CSerialBus (0x0a, ControllerInitiated, 400000, AddressingMode7Bit,
> +                    "\\_SB.I2C1", 0, ResourceConsumer)
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
> new file mode 100644
> index 000000000000..7e1d0cc2c9ab
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
> @@ -0,0 +1,54 @@
> +/** @file
> +*
> +*  iMX6 Quad I2C Controllers
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (I2C1)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +// Device (I2C2)
> +// do not include I2C2 resources since it is pin muxed to HDMI
> +
> +Device (I2C3)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
> new file mode 100644
> index 000000000000..59565c576a71
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
> @@ -0,0 +1,32 @@
> +/** @file
> +*  iMX6 Quad Pulse Width Modulator (PWM)
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (PWM1)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
> new file mode 100644
> index 000000000000..be5048fe3963
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
> @@ -0,0 +1,234 @@
> +/** @file
> +*
> +*  iMX6 Quad Resource Hub Proxy
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (RHPX)
> +{
> +  Name (_HID, "MSFT8000")
> +  Name (_CID, "MSFT8000")
> +  Name (_UID, 1)
> +
> +  Name (_CRS, ResourceTemplate() {
> +    // Index 0
> +    I2CSerialBus (0xFFFF,, 0,, "\\_SB.I2C3",,,,)
> +
> +    // Index 1
> +    SPISerialBus (             // SCKL
> +      // MOSI
> +      // MISO
> +      // CE0
> +      0,                      // Device selection (CE0)
> +      PolarityLow,            // Device selection polarity
> +      FourWireMode,           // wiremode
> +      8,                      // databit len
> +      ControllerInitiated,    // slave mode
> +      4000000,                // connection speed
> +      ClockPolarityLow,       // clock polarity
> +      ClockPhaseFirst,        // clock phase
> +      "\\_SB.SPI2",           // ResourceSource: SPI bus controller name
> +      0,                      // ResourceSourceIndex
> +                              // Resource usage
> +                              // DescriptorName: creates name for
> +                              //   offset of resource descriptor
> +    )                         // Vendor Data
> +
> +    // SPDIF_IN - GPIO1_IO24 PAD_ENET_RX_ER
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 24 } // 0 * 32 + 24
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 24 }
> +
> +    // DISP1_DATA17 - GPIO2_IO16 PAD_EIM_ADDR22
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 48 } // 1 * 32 + 16
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 48 }
> +
> +    // DISP1_DATA16 - GPIO2_IO17 PAD_EIM_ADDR21
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 49 } // 1 * 32 + 17
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 49 }
> +
> +    // DISP1_DATA15 - GPIO2_IO18 PAD_EIM_ADDR20
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 50 } // 1 * 32 + 18
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 50 }
> +
> +    // DISP1_DATA14 - GPIO2_IO19 PAD_EIM_ADDR19
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 51 } // 1 * 32 + 19
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 51 }
> +
> +    // DISP1_DATA13 - GPIO2_IO20 PAD_EIM_ADDR18
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 52 } // 1 * 32 + 20
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 52 }
> +
> +    // DISP1_DATA12 - GPIO2_IO21 PAD_EIM_ADDR17
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 53 } // 1 * 32 + 21
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 53 }
> +
> +    // DI1_DISP_CLK - GPIO2_IO22 PAD_EIM_ADDR16
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 54 } // 1 * 32 + 22
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 54 }
> +
> +    // DISP1_DATA11 - GPIO2_IO28 PAD_EIM_EB0
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 60 } // 1 * 32 + 28
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 60 }
> +
> +    // DISP1_DATA10 - GPIO2_IO29 PAD_EIM_EB1
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 61 } // 1 * 32 + 29
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 61 }
> +
> +    // DISP1_DATA09 - GPIO3_IO00 PAD_EIM_AD00
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 64 } // 2 * 32 + 0
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 64 }
> +
> +    // DISP1_DATA08 - GPIO3_IO01 PAD_EIM_AD01
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 65 } // 2 * 32 + 1
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 65 }
> +
> +    // DISP1_DATA07 - GPIO3_IO02 PAD_EIM_AD02
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 66 } // 2 * 32 + 2
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 66 }
> +
> +    // DISP1_DATA06 - GPIO3_IO03 PAD_EIM_AD03
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 67 } // 2 * 32 + 3
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 67 }
> +
> +    // DISP1_DATA05 - GPIO3_IO04 PAD_EIM_AD04
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 68 } // 2 * 32 + 4
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 68 }
> +
> +    // DISP1_DATA04 - GPIO3_IO05 PAD_EIM_AD05
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 69 } // 2 * 32 + 5
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 69 }
> +
> +    // DISP1_DATA03 - GPIO3_IO06 PAD_EIM_AD06
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 70 } // 2 * 32 + 6
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 70 }
> +
> +    // DISP1_DATA02 - GPIO3_IO07 PAD_EIM_AD07
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 71 } // 2 * 32 + 7
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 71 }
> +
> +    // DISP1_DATA01 - GPIO3_IO08 PAD_EIM_AD08
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 72 } // 2 * 32 + 8
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 72 }
> +
> +    // DISP1_DATA00 - GPIO3_IO09 PAD_EIM_AD09
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 73 } // 2 * 32 + 9
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 73 }
> +
> +    // DI1_PIN15 - GPIO3_IO10 PAD_EIM_AD10
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 74 } // 2 * 32 + 10
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 74 }
> +
> +    // DI1_PIN02 - GPIO3_IO11 PAD_EIM_AD11
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 75 } // 2 * 32 + 11
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 75 }
> +
> +    // DI1_PIN03 - GPIO3_IO12 PAD_EIM_AD12
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 76 } // 2 * 32 + 12
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 76 }
> +
> +    // DI1_D0_CS - GPIO3_IO13 PAD_EIM_AD13
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 77 } // 2 * 32 + 13
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 77 }
> +
> +    // DI1_D1_CS - GPIO3_IO14 PAD_EIM_AD14
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 78 } // 2 * 32 + 14
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 78 }
> +
> +    // DI1_PIN01 - GPIO3_IO15 PAD_EIM_AD15
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 79 } // 2 * 32 + 15
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 79 }
> +
> +    // DISP1_DATA22 - GPIO3_IO26 PAD_EIM_DATA26
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 90 } // 2 * 32 + 26
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 90 }
> +
> +    // DISP1_DATA23 - GPIO3_IO27 PAD_EIM_DATA27
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 91 } // 2 * 32 + 27
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 91 }
> +
> +    // DISP1_DATA21 - GPIO3_IO30 PAD_EIM_DATA30
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 94 } // 2 * 32 + 20
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 94 }
> +
> +    // DISP1_DATA20 - GPIO3_IO31 PAD_EIM_DATA31
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 95 } // 2 * 32 + 31
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 95 }
> +
> +    // DISP1_DATA19 - GPIO5_IO04 PAD_EIM_ADDR24
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 132 } // 4 * 32 + 4
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 132 }
> +
> +    // DISP1_DATA18 - GPIO6_IO06 PAD_EIM_ADDR23
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 166 } // 5 * 32 + 6
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 166 }
> +
> +    // SPDIF_OUT - GPIO7_IO12 PAD_GPIO17
> +    GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,, ) { 204 } // 6 * 32 + 12
> +    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPIO",) { 204 }
> +  })
> +
> +  Name (_DSD, Package() {
> +    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +    Package() {
> +      // I2C3
> +      Package (2) { "bus-I2C-I2C3", Package() { 0 } },
> +
> +      // SPI 2
> +      Package (2) { "bus-SPI-SPI2", Package() { 1 } }, // Index 1
> +      Package (2) { "SPI2-MinClockInHz", 115 },        // 115 Hz
> +      Package (2) { "SPI2-MaxClockInHz", 12000000 },   // 12 MHz
> +      // Data bit length
> +      Package (2) { "SPI2-SupportedDataBitLengths", Package() { 8, 16, 32 } },
> +
> +      // GPIO Pin Count and supported drive modes
> +      Package (2) { "GPIO-PinCount", 206 },
> +      Package (2) { "GPIO-UseDescriptorPinNumbers", 1 },
> +
> +      // InputHighImpedance, InputPullUp, InputPullDown, OutputCmos
> +      Package (2) { "GPIO-SupportedDriveModes", 0xf },
> +    }
> +  })
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
> new file mode 100644
> index 000000000000..d3f275d21473
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
> @@ -0,0 +1,144 @@
> +/** @file
> +*
> +*  iMX6 Quad Ultra Secured Digital Host Controllers (uSDHC)
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// uSDHC1: WLAN SDIO Socket
> +Device (SDH1)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Name (_S1D, 0x1)
> +  Name (_S2D, 0x1)
> +  Name (_S3D, 0x1)
> +  Name (_S4D, 0x1)
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +
> +  Device (TIWL)
> +  {
> +    Name (_ADR, 0)
> +    // TODO: We must replace these HID and CID values with valid ones
> +    Name (_HID, "TI_WLAN")
> +    Name (_CID, "TI_WLAN")
> +    Name (_UID, 1)
> +
> +    Method (_STA) {
> +      Return(0xf)
> +    }
> +
> +    Method (_CRS, 0x0, NotSerialized) {
> +      Name (RBUF, ResourceTemplate () {
> +        GpioInt(Edge, ActiveHigh, Exclusive, PullNone, 0, "\\_SB.GPIO", 0,
> +                ResourceConsumer,,) { 164 } // WLAN_EN
> +        GpioIo(Exclusive, PullNone, 0, 2, IoRestrictionOutputOnly,
> +                "\\_SB.GPIO",0, ResourceConsumer,,) { 154 }
> +      })
> +      Return (RBUF)
> +    }
> +  }
> +}
> +
> +// uSDHC2: SDCard Socket
> +Device (SDH2)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Name (_S1D, 0x1)
> +  Name (_S2D, 0x1)
> +  Name (_S3D, 0x1)
> +  Name (_S4D, 0x1)
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    // Despite the SDCard is a removal device, UWF requires the
> +    // boot device to be non-removable. This is required for the
> +    // Windows SDCard boot scenario with UWF enabled.
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC3: eMMC
> +Device (SDH3)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Name (_S1D, 0x1)
> +  Name (_S2D, 0x1)
> +  Name (_S3D, 0x1)
> +  Name (_S4D, 0x1)
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (MMC0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    // eMMC is non-removable
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
> new file mode 100644
> index 000000000000..2eb9fe41f127
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
> @@ -0,0 +1,43 @@
> +/** @file
> +*
> +*  iMX6 Quad SPI Controller
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (SPI2)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x2)
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
> +
> +      // CS0 (PAD_EIM_RW) GPIO2_IO26
> +      GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +              ResourceConsumer,, ) { 58 }
> +      // CS1 (PAD_EIM_LBA) GPIO2_IO27
> +      GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +              ResourceConsumer,, ) { 59 }
> +
> +      // MISO: PAD_EIM_OE_B (GPIO2_IO25) Alt2
> +      // MOSI: PAD_EIM_CS1_B (GPIO2_IO24) Alt2
> +      // SCLK: PAD_EIM_CS0_B (GPIO2_IO23) Alt2
> +      MsftFunctionConfig (Exclusive, PullDown, IMX_ALT2, "\\_SB.GPIO", 0,
> +                          ResourceConsumer, ) { 57, 56, 55 } })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
> new file mode 100644
> index 000000000000..c64c4664c442
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
> @@ -0,0 +1,198 @@
> +/** @file
> +*
> +*  iMX6 Quad UART Controllers
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (UAR1)
> +{
> +  Name (_HID, "NXP0106")
> +  Name (_UID, 0x1)
> +  Name (_DDN, "UART1")
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02020000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
> +
> +      // UART1_TX_DATA - CSI0_DAT10 - GPIO5_IO28 - 156
> +      // UART1_RX_DATA - CSI0_DAT11 - GPIO5_IO29 - 157
> +      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT3, "\\_SB.GPIO", 0,
> +                          ResourceConsumer, ) { 156, 157 }
> +
> +      // DMA channel 2, SDMA_REQ_UART1_RX for UART1 RX DMA
> +      FixedDMA (SDMA_REQ_UART1_RX, 2, Width8Bit, )
> +      // DMA channel 1, SDMA_REQ_UART1_TX for UART1 TX DMA
> +      FixedDMA (SDMA_REQ_UART1_TX, 1, Width8Bit, )
> +
> +      UARTSerialBus (
> +        115200,
> +        DataBitsEight,
> +        StopBitsOne,
> +        0,                // LinesInUse
> +        LittleEndian,
> +        ParityTypeNone,
> +        FlowControlNone,
> +        0,
> +        0,
> +        "\\_SB.CPU0",
> +        0,
> +        ResourceConsumer,
> +        ,)
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (UAR2)
> +{
> +  Name (_HID, "NXP0107")
> +  Name (_UID, 0x2)
> +  Name (_DDN, "UART2")
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021E8000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 59 }
> +
> +      // DMA channel 4, SDMA_REQ_UART2_RX for UART2 RX DMA
> +      FixedDMA (SDMA_REQ_UART2_RX, 4, Width8Bit, )
> +      // DMA channel 3, SDMA_REQ_UART2_TX for UART2 TX DMA
> +      FixedDMA (SDMA_REQ_UART2_TX, 3, Width8Bit, )
> +
> +      // UART2_TX_DATA - SD4_DAT7 - GPIO2_IO15 - 47
> +      // UART2_RX_DATA - SD4_DAT4 - GPIO2_IO12 - 44
> +      // UART2_CTS_B - SD4_DAT6 - GPIO2_IO14 - 46
> +      // UART2_RTSB is not pinned out because it is connected to USB
> +      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT2, "\\_SB.GPIO", 0,
> +                          ResourceConsumer, ) { 44, 46, 47 }
> +
> +      UARTSerialBus (
> +        115200,
> +        DataBitsEight,
> +        StopBitsOne,
> +        0xC0,                // LinesInUse
> +        LittleEndian,
> +        ParityTypeNone,
> +        FlowControlNone,
> +        0,
> +        0,
> +        "\\_SB.CPU0",
> +        0,
> +        ResourceConsumer,
> +        ,)
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (UAR3)
> +{
> +  Name (_HID, "NXP0107")
> +  Name (_UID, 0x3)
> +  Name (_DDN, "UART3")
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021EC000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 60 }
> +
> +      // DMA channel 6, SDMA_REQ_UART3_RX for UART3 RX DMA
> +      FixedDMA (SDMA_REQ_UART3_RX, 6, Width8Bit, )
> +      // DMA channel 5, SDMA_REQ_UART3_TX for UART3 TX DMA
> +      FixedDMA (SDMA_REQ_UART3_TX, 5, Width8Bit, )
> +
> +      // UART3_TX - EIM_D24 - GPIO3_IO24 - 88
> +      // UART3_RX - EIM_D25 - GPIO3_IO25 - 89
> +      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT2, "\\_SB.GPIO", 0,
> +                          ResourceConsumer, ) { 88, 89 }
> +
> +      UARTSerialBus (
> +        115200,
> +        DataBitsEight,
> +        StopBitsOne,
> +        0,                // LinesInUse
> +        LittleEndian,
> +        ParityTypeNone,
> +        FlowControlNone,
> +        0,
> +        0,
> +        "\\_SB.CPU0",
> +        0,
> +        ResourceConsumer,
> +        ,)
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +// Connected to bluetooth module
> +Device (UAR4)
> +{
> +  Name (_HID, "NXP0107")
> +  Name (_UID, 0x4)
> +  Name (_DDN, "UART4")
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021F0000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 61 }
> +
> +      // DMA channel 8, SDMA_REQ_UART4_RX for UART4 RX DMA
> +      FixedDMA (SDMA_REQ_UART4_RX, 8, Width8Bit, )
> +      // DMA channel 7, SDMA_REQ_UART4_TX for UART4 TX DMA
> +      FixedDMA (SDMA_REQ_UART4_TX, 7, Width8Bit, )
> +
> +      // UART4_TX_DATA - CSI0_DAT12 - GPIO5_IO30 - 158
> +      // UART4_RX_DATA - CSI0_DAT13 - GPIO5_IO31 - 159
> +      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT3, "\\_SB.GPIO", 0,
> +                          ResourceConsumer, ) { 158, 159 }
> +
> +      // UART4_RTS_B - CSI0_DAT16 - GPIO6_IO02 - 162
> +      // UART4_CTS_B - CSI0_DAT17 - GPIO6_IO03 - 163
> +      MsftFunctionConfig (Exclusive, PullUp, IMX_ALT3, "\\_SB.GPIO", 0,
> +                          ResourceConsumer, ) { 162, 163 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (UAR5)
> +{
> +  Name (_HID, "NXP0107")
> +  Name (_UID, 0x5)
> +  Name (_DDN, "UART5")
> +  Method (_STA) {
> +    Return (0)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021F4000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 62 }
> +
> +      // DMA channel 10, SDMA_REQ_UART5_RX for UART5 RX DMA
> +      FixedDMA (SDMA_REQ_UART5_RX, 10, Width8Bit, )
> +      // DMA channel 9, SDMA_REQ_UART5_TX for UART5 TX DMA
> +      FixedDMA (SDMA_REQ_UART5_TX, 9, Width8Bit, )
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
> new file mode 100644
> index 000000000000..65a0782d2705
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
> @@ -0,0 +1,343 @@
> +/** @file
> +*
> +*  iMX6 Quad EHCI USB Controllers
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (URS0)
> +{
> +  Name (_HID, "PNP0C90")
> +  Name (_UID, 0x0)
> +
> +  // URS requires device to at least be wake-able from D2 state
> +  // WDF also requires that _DSW (enable & disable wake ability) to be present
> +  Name (_S0W, 0x3)
> +  Name (_PRW, Package() { 0, 0 })
> +  Method (_DSW, 0x3, NotSerialized) {
> +  }
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // Controller register address space. URS driver would add 0x0100
> +      // offset for host mode
> +      MEMORY32FIXED (ReadWrite, 0x02184000, 0x200, )
> +
> +      // USB_OTG_ID pin, needs to be declared as *Wake as this device is
> +      // expected to be wakable. The USB PHY is capable to detect
> +      // USB ID changes but the interrupt cannot be acknowledge
> +      // and the behaviour is undefined based on NXP feedback. So
> +      // the the only way to reliably detect USB ID changed is to
> +      // either to share interrupts or assign a GPIO to detect.
> +      // The URS driver does not properly handle level sensitive
> +      // interrupts which can lead to an interrupt storm. Therefore we use
> +      // an edge sensitive GPIO interrupt.
> +      //
> +      // USB_OTG_ID connected to GPIO_1 (GPIO1_IO01). Use 1ms debounce.
> +      GpioInt (Edge, ActiveBoth, SharedAndWake, PullDefault, 100, "\\_SB.GPIO",) { 1 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Name (OTGR, ResourceTemplate() {
> +    GpioIO (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPIO", 0,
> +            ResourceConsumer,,) {
> +      1
> +    }
> +  })
> +
> +  Scope (\_SB_.GPIO) {
> +    OperationRegion (OTGP, GeneralPurposeIO, Zero, One)
> +  }
> +
> +  Field (\_SB_.GPIO.OTGP, ByteAcc, NoLock, Preserve) {
> +    Connection (\_SB_.URS0.OTGR),
> +    OTGF, 1
> +  }
> +
> +  // Device Specific Method takes 4 args:
> +  //  Arg0 : Buffer containing a UUID [16 bytes]
> +  //  Arg1 : Integer containing the Revision ID
> +  //  Arg2 : Integer containing the Function Index
> +  //  Arg3 : Package that contains function-specific arguments (Unused?)
> +  Method (_DSM, 0x4, NotSerialized) {
> +    Name (RET, 0x0); // Declare return variable
> +    Name (PVAL, 0x0); // Declare pin value variable
> +
> +    // Check UUID
> +    switch (ToBuffer (Arg0)) {
> +    // URS UUID
> +    case (ToUUID ("14EB0A6A-79ED-4B37-A8C7-84604B55C5C3")) {
> +        // Function index
> +        switch (Arg2) {
> +
> +        // Function 0: Return supported functions, based on revision
> +        // Return value and revision ID lack documentation
> +        case (0) {
> +            switch (Arg1) {
> +            // Revision 0: function {1,2} supported
> +            case (0) {
> +                Return (0x03);
> +              }
> +              default {
> +                Return (0x0);
> +              }
> +            }
> +          }
> +
> +        // Function 1: Read USB_OTG_ID pin value
> +        //
> +        // Return value
> +        // 0 = UrsHardwareEventIdFloat (Function)
> +        // 1 = UrsHardwareEventIdGround (Host)
> +        case (1) {
> +            Store (OTGF, PVAL);                  // Read value of OTG_ID Pin
> +            Store (LEqual (PVAL, 0), RET);       // Complement value
> +            Return (RET);
> +          }
> +
> +        // Function 2: Read USB_OTG_ID pin value
> +        //
> +        // Return value
> +        // 0 = UrsHardwareEventIdFloat (Function)
> +        // 1 = UrsHardwareEventIdGround (Host)
> +        case (2) {
> +            Store (OTGF, PVAL);                  // Read value of OTG_ID Pin
> +            Store (LEqual (PVAL, 0), RET);       // Complement value
> +            Return (RET);
> +          }
> +
> +        // Unknown function index
> +          default {
> +            Return (0x0);
> +          }
> +        } // Function index
> +      }
> +
> +    // Unknown UUID
> +      default {
> +        Return (0x0);
> +      }
> +    } // Check UUID
> +  } // _DSM
> +
> +  Device (USB0) {
> +    // The host controller device node needs to have an address of '0'
> +    Name (_ADR, 0x0)
> +    Name (_UID, 0x0)
> +    Name (_S0W, 0x0) // D0 is the lowest supported state to wake itself up
> +    Method (_STA) {
> +      Return (0xf)
> +    }
> +    Method (_CRS, 0x0, NotSerialized) {
> +      Name (RBUF, ResourceTemplate () {
> +        Interrupt (ResourceConsumer, Level, ActiveHigh, SharedAndWake) { 75 }
> +      })
> +      Return (RBUF)
> +    }
> +
> +    OperationRegion (OTGM, SystemMemory, 0x02184100, 0x100)
> +    Field (OTGM, WordAcc, NoLock, Preserve) {
> +      Offset (0x84),  // skip to register 84h
> +      PTSC, 32,       // port status control
> +      Offset (0xA8),  // skip to register A8h
> +      DSBM, 32,       // UOG_USBMOD
> +    }
> +
> +    Name (REG, 0x0);    // Declare register read variable
> +    Method (_UBF, 0x0, NotSerialized) {
> +      // Reset handled by driver so no reset required here
> +      Store (0x03, DSBM);         // set host mode & little endian
> +      Store (PTSC, REG);          // read PORTSC status
> +      Store (OR (REG, 0x2), PTSC); // clear current PORTSC status
> +    }
> +  }
> +
> +  Device (UFN0) {
> +    // The function controller device node needs to have an address of '1'
> +    Name (_ADR, 0x1)
> +
> +    Method (_CRS, 0x0, NotSerialized) {
> +      Name (RBUF, ResourceTemplate () {
> +        Interrupt (ResourceConsumer, Level, ActiveHigh, SharedAndWake) { 75 }
> +      })
> +      Return (RBUF)
> +    }
> +
> +    OperationRegion (OTGM, SystemMemory, 0x02184100, 0x100)
> +    Field (OTGM, WordAcc, NoLock, Preserve) {
> +      Offset (0x84),  // skip to register 84h
> +      PTSC, 32,       // port status control
> +      Offset (0xA8),  // skip to register A8h
> +      DSBM, 32,       // UOG_USBMOD
> +    }
> +
> +    Name (REG, 0x0);    // Declare register read variable
> +    Method (_UBF, 0x0, NotSerialized) {
> +      // Reset handled by driver so no reset required here
> +      Store (0x02, DSBM);         // set device mode & little endian
> +      Store (PTSC, REG);          // read PORTSC status
> +      Store (OR (REG, 0x2), PTSC); // clear current PORTSC status
> +    }
> +
> +    // Device Specific Method takes 4 args:
> +    //  Arg0 : Buffer containing a UUID [16 bytes]
> +    //  Arg1 : Integer containing the Revision ID
> +    //  Arg2 : Integer containing the Function Index
> +    //  Arg3 : Package that contains function-specific arguments
> +    Method (_DSM, 0x4, NotSerialized) {
> +      switch (ToBuffer (Arg0)) {
> +      // UFX Chipidea interface identifier
> +      case (ToUUID ("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511")) {
> +          // Function selector
> +          switch (Arg2) {
> +
> +          // Function 0: Query support
> +          //   Bit  Description
> +          //   ---  -------------------------------
> +          //     0  Get property
> +          //     1  Get properties (Function 1)
> +          //     2  Set USB device state
> +          case (0) {
> +              switch (Arg1) {
> +              // Revision 0: functions {0,1} supported
> +              case (0) {
> +                  Return (Buffer() { 0x03 });
> +                }
> +                default {
> +                  Return (Buffer() { 0x01 });
> +                }
> +              }
> +            }
> +
> +          // Function 1: Return device capabilities bitmap
> +          //   Bit  Description
> +          //   ---  -------------------------------
> +          //     0  Attach detach
> +          //     1  Software charging
> +          case (1) {
> +              Return (0x01);
> +            }
> +
> +          // Function 2: Get port type
> +          //     0x00  Unknown port
> +          //     0x01  Standard downstream
> +          //     0x02  Charging downstream
> +          //     0x03  Dedicated charging
> +          case (2) {
> +              Return (0x01);
> +            }
> +
> +          // Function 3: Set device state
> +          case (3) {
> +              Return (Buffer() { 0x0 });
> +            }
> +
> +          // Unknown function
> +            default {
> +              Return (Buffer() { 0x0 });
> +            }
> +          }
> +        }
> +
> +      // UFX interface identifier
> +      case (ToUUID ("FE56CFEB-49D5-4378-A8A2-2978DBE54AD2")) {
> +          // Function selector
> +          switch (Arg2) {
> +          // Function 1: Return number of supported USB PHYSICAL endpoints
> +          // Up to 8 bidirectional endpoints
> +          case (1) {
> +              Return (8);
> +            }
> +            default {
> +              Return (Buffer() { 0x0 });
> +            }
> +          }
> +        }
> +
> +      //
> +      // Unknown UUID
> +      //
> +        default {
> +          Return (0x0);
> +        }
> +      } // UUID
> +    } // _DSM
> +  }
> +}
> +
> +Device (USB1)
> +{
> +  Name (_HID, "NXP010C")
> +  Name (_CID, "PNP0D20")
> +  Name (_UID, 0x1)
> +  Name (_S0W, 0x0)
> +
> +  // USB Host controller registers
> +  OperationRegion (USBH, SystemMemory, 0x02184000, 0x1000)
> +  Field (USBH, DWordAcc, NoLock, Preserve) {
> +    Offset (0x00000344),
> +    USTS, 32,             // USB_UH1_USBSTS
> +    Offset (0x00000348),
> +    INTR, 32,             // USB_UH1_USBINTR
> +    Offset (0x00000384),  // skip to register 0x384
> +    PSC1, 32,             // USB_UH1_PORTSC1
> +    Offset (0x00000804),  // skip to register 0x804
> +    NCTL, 32,             // USBNC_USB_UH1_CTRL
> +  }
> +
> +  // USBPHY2 Registers
> +  OperationRegion (PHY2, SystemMemory, 0x020CA000, 0x1000)
> +  Field (PHY2, DWordAcc, NoLock, Preserve) {
> +    Offset (0x0000000),     // skip to register 0
> +    PPWD, 32,               // USBPHY2_PWD
> +    Offset (0x00000030),    // skip to register 0x30
> +    PCTL, 32,               // USBPHY2_CTRL
> +    Offset (0x00000034),    // skip to register 0x34
> +    PCTS, 32,               // USBPHY2_CTRL_SET
> +    Offset (0x00000038),    // skip to register 0x38
> +    PCTC, 32,               // USBPHY2_CTRL_CLR
> +    Offset (0x00000050),    // skip to register 0x50
> +    PDBG, 32,               // USBPHY2_DEBUG
> +    Offset (0x00000054),    // skip to register 0x54
> +    PDBS, 32,               // USBPHY2_DEBUG_SET
> +    Offset (0x00000058),    // skip to register 0x58
> +    PDBC, 32,               // USBPHY2_DEBUG_CLR
> +  }
> +
> +  // Anatop Registers
> +  OperationRegion (ANAT, SystemMemory, 0x020C8000, 0x1000)
> +  Field (ANAT, DWordAcc, NoLock, Preserve) {
> +    Offset (0x0000244),     // skip to register 0x244
> +    LPBS, 32,               // ANADIG_USB2_LOOPBACK_SET
> +    Offset (0x0000248),     // skip to register 0x248
> +    LPBC, 32,               // ANADIG_USB2_LOOPBACK_CLR
> +  }
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02184300, 0x100, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, ExclusiveAndWake) { 72 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Method (_UBF, 0x0, NotSerialized) {
> +  }
> +}
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 27/27] Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files
  2018-09-21  8:26 ` [PATCH edk2-platforms 27/27] Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files Chris Co
@ 2018-12-15 12:28   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-15 12:28 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:26:19AM +0000, Chris Co wrote:
> This adds the dsd and fdf definitions for Solidrun's i.MX 6Quad
> Hummingboard Edge platform.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc | 141 ++++++++++++++++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf | 117 ++++++++++++++++
>  2 files changed, 258 insertions(+)
> 
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
> new file mode 100644
> index 000000000000..5e203bc92447
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
> @@ -0,0 +1,141 @@
> +#
> +# HummingBoard Edge board description
> +# The board is iMX6 Quad with 2GB DRAM
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +
> +################################################################################
> +#
> +# Board [Defines] Section
> +#
> +################################################################################
> +
> +[Defines]
> +  DEFINE BOARD_NAME     = HummingBoardEdge_iMX6Q_2GB
> +  DEFINE IMX_FAMILY     = IMX6DQ
> +  DEFINE IMX_CHIP_TYPE  = QUAD
> +  DEFINE DRAM_SIZE      = DRAM_2GB
> +  BOARD_DIR             = Platform/SolidRun/$(BOARD_NAME)
> +  FLASH_DEFINITION      = $(BOARD_DIR)/$(BOARD_NAME).fdf
> +
> +################################################################################
> +#
> +# Platform Description
> +#
> +################################################################################
> +!include Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
> +
> +[LibraryClasses.common]
> +  ArmPlatformLib|$(BOARD_DIR)/Library/iMX6BoardLib/iMX6BoardLib.inf
> +
> +[Components.common]
> +  # Display Support
> +!if $(CONFIG_HEADLESS) == FALSE
> +  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> +  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> +  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
> +  !if $(IMX_FAMILY) == IMX6SX
> +    #
> +    # Use board-specific GOP for SoloX
> +    #
> +    $(BOARD_DIR)/Drivers/GraphicsOutputDxe/GraphicsOutputDxe.inf
> +  !else
> +    Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
> +  !endif
> +!endif
> +
> +  # ACPI Support
> +  MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
> +  MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
> +  $(BOARD_DIR)/AcpiTables/AcpiTables.inf
> +
> +  # SMBIOS Support
> +  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
> +  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
> +
> +################################################################################
> +#
> +# Board PCD Sections
> +#
> +################################################################################
> +
> +########################
> +#
> +# iMX6Pkg PCDs
> +#
> +########################
> +[PcdsFixedAtBuild.common]
> +
> +# SMBIOS Type0 Strings
> +gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"SolidRun"

Could you do a
!ifdef $(FIRMWARE_VENDOR)
  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"$(FIRMWARE_VENDOR)"
!else
  whatever
!endif
?

> +gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision|0x00000001 # FirmwareRevision 0.1

And the same for FIRMWARE_VER?

/
    Leif


> +
> +# SMBIOS Type1 Strings
> +giMX6TokenSpaceGuid.PcdSystemFamily|L"HummingBoard"
> +giMX6TokenSpaceGuid.PcdSystemManufacturer|L"SolidRun"
> +giMX6TokenSpaceGuid.PcdSystemProductName|L"HummingBoard-Edge i4Pro"
> +giMX6TokenSpaceGuid.PcdSystemSkuNumber|L"MSMX6QDW00D02GE008E00CH"
> +giMX6TokenSpaceGuid.PcdSystemVersionNumber|L"1.4"
> +giMX6TokenSpaceGuid.PcdSystemUuid|{0xfa,0x00,0xe9,0x0f,0x97,0x4a,0x40,0x6f,0xaf,0x0f,0x4a,0xd4,0x66,0x50,0xbe,0x5a}
> +
> +# SMBIOS Type2 Strings
> +giMX6TokenSpaceGuid.PcdBoardAssetTag|L"0"
> +giMX6TokenSpaceGuid.PcdBoardLocationInChassis|L"Open Board"
> +giMX6TokenSpaceGuid.PcdBoardManufacturer|L"SolidRun"
> +giMX6TokenSpaceGuid.PcdBoardProductName|L"HummingBoard-Edge i4Pro"
> +giMX6TokenSpaceGuid.PcdBoardVersionNumber|L"1.4"
> +
> +# SMBIOS Type3 Strings
> +giMX6TokenSpaceGuid.PcdChassisAssetTag|L"0"
> +giMX6TokenSpaceGuid.PcdChassisManufacturer|L"SolidRun"
> +giMX6TokenSpaceGuid.PcdChassisVersionNumber|L"1.4"
> +
> +# SMBIOS Type4 Strings
> +giMX6TokenSpaceGuid.PcdProcessorAssetTag|L"0"
> +giMX6TokenSpaceGuid.PcdProcessorManufacturer|L"NXP"
> +giMX6TokenSpaceGuid.PcdProcessorPartNumber|L"i.MX 6Quad"
> +giMX6TokenSpaceGuid.PcdProcessorSocketDesignation|L"FCPBGA"
> +giMX6TokenSpaceGuid.PcdProcessorVersionNumber|L"1.0"
> +
> +# SMBIOS Type16
> +giMX6TokenSpaceGuid.PcdPhysicalMemoryMaximumCapacity|0x200000 # 2GB
> +
> +# SMBIOS Type17
> +giMX6TokenSpaceGuid.PcdMemoryBankLocation|L"Bank 0"
> +giMX6TokenSpaceGuid.PcdMemoryDeviceLocation|L"On SoM"
> +
> +#
> +# USB EHCI Controller (USB_UH1)
> +#
> +giMX6TokenSpaceGuid.PcdEHCIBase|0x02184200
> +
> +#
> +# Enable uSDHC2 and uSDHC3 Controllers.
> +# On HummingBoardEdge, SDCard slot is attached to uSDHC2
> +# with CD wired to SD2_CD_B, eMMC is attached to uSDHC3
> +#
> +giMXPlatformTokenSpaceGuid.PcdSdhc2Enable|TRUE
> +giMXPlatformTokenSpaceGuid.PcdSdhc2CardDetectSignal|0xFFFF # Use uSDHC internal CD circuit
> +giMXPlatformTokenSpaceGuid.PcdSdhc3Enable|TRUE
> +
> +#
> +# UART initialization required
> +#
> +giMXPlatformTokenSpaceGuid.PcdSerialRegisterBase|0x02020000   # UART1
> +giMXPlatformTokenSpaceGuid.PcdKdUartInstance|1                # UART1
> +
> +#
> +# GPIO reset pin (PERST)
> +#
> +giMX6TokenSpaceGuid.PcdPcieResetGpio|TRUE
> +giMX6TokenSpaceGuid.PcdPcieResetGpioBankNumber|2
> +giMX6TokenSpaceGuid.PcdPcieResetGpioIoNumber|11
> diff --git a/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
> new file mode 100644
> index 000000000000..f40ee824e1e3
> --- /dev/null
> +++ b/Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
> @@ -0,0 +1,117 @@
> +#
> +#  iMX6 Quad Hummingboard FLASH layout
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +
> +################################################################################
> +#
> +# FD Section
> +# The [FD] Section is made up of the definition statements and a
> +# description of what goes into  the Flash Device Image.  Each FD section
> +# defines one flash "device" image.  A flash device image may be one of
> +# the following: Removable media bootable image (like a boot floppy
> +# image,) an Option ROM image (that would be "flashed" into an add-in
> +# card,) a System "Flash"  image (that would be burned into a system's
> +# flash) or an Update ("Capsule") image that will be used to update and
> +# existing system flash.
> +#
> +################################################################################
> +
> +[FD.iMXBoard_EFI]
> +!if $(IMX_FAMILY) == IMX6SX
> +BaseAddress   = 0x82004000|gArmTokenSpaceGuid.PcdFdBaseAddress  #The base address of UEFI image
> +!else
> +BaseAddress   = 0x10820000|gArmTokenSpaceGuid.PcdFdBaseAddress  #The base address of UEFI image
> +!endif
> +Size          = 0x001D0000|gArmTokenSpaceGuid.PcdFdSize         #The size in bytes of UEFI image
> +ErasePolarity = 1
> +BlockSize     = 0x1
> +NumBlocks     = 0x001D0000
> +
> +################################################################################
> +#
> +# Following are lists of FD Region layout which correspond to the locations of different
> +# images within the flash device.
> +#
> +# Regions must be defined in ascending order and may not overlap.
> +#
> +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
> +# the pipe "|" character, followed by the size of the region, also in hex with the leading
> +# "0x" characters. Like:
> +# Offset|Size
> +# PcdOffsetCName|PcdSizeCName
> +# RegionType <FV, DATA, or FILE>
> +#
> +################################################################################
> +0x00000000|0x001D0000    # 1792Kb for the Pei phase boot
> +
> +gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
> +FV = FVMAIN_COMPACT
> +
> +################################################################################
> +#
> +# FV Section
> +#
> +# [FV] section is used to define what components or modules are placed within a flash
> +# device file.  This section also defines order the components and modules are positioned
> +# within the image.  The [FV] section consists of define statements, set statements and
> +# module statements.
> +#
> +################################################################################
> +[FV.FvMain]
> +BlockSize          = 0x1
> +NumBlocks          = 0         # This FV gets compressed so make it just big enough
> +FvAlignment        = 8         # FV alignment and FV attributes setting.
> +ERASE_POLARITY     = 1
> +MEMORY_MAPPED      = TRUE
> +STICKY_WRITE       = TRUE
> +LOCK_CAP           = TRUE
> +LOCK_STATUS        = TRUE
> +WRITE_DISABLED_CAP = TRUE
> +WRITE_ENABLED_CAP  = TRUE
> +WRITE_STATUS       = TRUE
> +WRITE_LOCK_CAP     = TRUE
> +WRITE_LOCK_STATUS  = TRUE
> +READ_DISABLED_CAP  = TRUE
> +READ_ENABLED_CAP   = TRUE
> +READ_STATUS        = TRUE
> +READ_LOCK_CAP      = TRUE
> +READ_LOCK_STATUS   = TRUE
> +
> +  #
> +  # ACPI
> +  #
> +  INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
> +  INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
> +  INF RuleOverride=ACPITABLE $(BOARD_DIR)/AcpiTables/AcpiTables.inf
> +
> +!if $(CONFIG_HEADLESS) == FALSE
> +  INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> +  INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> +  INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
> +  !if $(IMX_FAMILY) == IMX6SX
> +    #
> +    # Use board-specific GOP for SoloX
> +    #
> +    INF $(BOARD_DIR)/Drivers/GraphicsOutputDxe/GraphicsOutputDxe.inf
> +  !else
> +    INF Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
> +  !endif
> +!endif
> +
> +  #
> +  # SMBIOS Support
> +  #
> +  INF Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
> +  INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
> +
> +!include Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 08/27] Silicon/NXP: Add Virtual RTC support for i.MX platform
  2018-09-21  8:25 ` [PATCH edk2-platforms 08/27] Silicon/NXP: Add Virtual RTC support for i.MX platform Chris Co
@ 2018-12-15 13:26   ` Leif Lindholm
  0 siblings, 0 replies; 75+ messages in thread
From: Leif Lindholm @ 2018-12-15 13:26 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

On Fri, Sep 21, 2018 at 08:25:59AM +0000, Chris Co wrote:
> This adds a virtual RTC library that implements EFI RTC runtime services
> based on the ARM performance counter.  It should only be used for relative
> time measurement, such as for Windows Boot Manager.

Is this for use only before ExitBootservices, or does use of this mean
the performance counters will conflict with use during OS runtime?
Please add some detail to commit message.

> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c   | 227 ++++++++++++++++++++
>  Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf |  37 ++++
>  2 files changed, 264 insertions(+)
> 
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
> new file mode 100644
> index 000000000000..771c1d7a8f9c
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
> @@ -0,0 +1,227 @@
> +/** @file
> +*
> +*  Implement EFI RealTimeClock runtime services based on ARM Performance Counter.
> +*
> +*  Currently this driver does not support time setting, alarms, or runtime calls.
> +*  This special library is NOT meant to replace a HW RTC implementation to
> +*  measure date/time. Use this library ONLY to measure relative time between
> +*  two EFI_GET_TIME readings.
> +*  The performance counter will wrap-around eventually after a long time, make
> +*  sure to consider this limitation if you are depending on this library for
> +*  relative time measurement. e.g. For the ARM 64-bit counter with 19.2MHz
> +*  frequency, the counter will wrap-around after approximately 30465 year.
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/RealTimeClockLib.h>
> +#include <Library/TimerLib.h>
> +
> +#define LOG_FMT_HELPER(FMT, ...) \
> +    "VirtualRealTimeClock:" FMT "%a\n", __VA_ARGS__
> +
> +#define LOG_TRACE(...) \
> +    DEBUG((DEBUG_BLKIO, LOG_FMT_HELPER(__VA_ARGS__, "")))
> +
> +/**
> +  Returns the current time and date information, and the time-keeping capabilities
> +  of the virtual RTC.
> +
> +  For simplicity, this LibGetTime does not report Years/Months, instead it will
> +  only report current Day, Hours, Minutes and Seconds starting from the beginning
> +  of CPU up-time. Otherwise, a more complex logic will be required to account
> +  for leap years and days/month differences.
> +
> +  @param  Time                  A pointer to storage to receive a snapshot of
> +                                the current time.
> +  @param  Capabilities          An optional pointer to a buffer to receive the
> +                                real time clock device's capabilities.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER Time is NULL.
> +  @retval EFI_DEVICE_ERROR      The time could not be retrieved due to hardware error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibGetTime (
> +  OUT EFI_TIME *Time,
> +  OUT EFI_TIME_CAPABILITIES *Capabilities
> +  )
> +{
> +  UINT64 ElapsedSeconds;
> +  UINT64 TimerFreq;
> +
> +  if (Time == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Depend on ARM ARCH Timer (i.e. performance counter) to report date/time
> +  // relative to the start of CPU timer counting where date and time will always
> +  // be relative to the date/time 1/1/1900 00H:00M:00S
> +  if (PcdGet32 (PcdArmArchTimerFreqInHz) > 0) {
> +    TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz);
> +  } else {
> +    TimerFreq = GetPerformanceCounterProperties (NULL, NULL);
> +  }

OK, here is where I get confused. The comment says we're using Arch
timers, but surely iMX6Pkg/Library/TimerLib isn't a reimplementation
of ArmPkg/Library/ArmArchTimerLib?

Also, using iMX6Pkg/Library/TimerLib, this all folds down to setting
TimerFreq to the value of PcdGet32 (PcdArmArchTimerFreqInHz) regardless.

> +
> +  ASSERT (TimerFreq > 0);
> +  if (TimerFreq == 0) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  if (Capabilities) {
> +    Capabilities->Accuracy = 0;
> +    Capabilities->Resolution = TimerFreq;
> +    Capabilities->SetsToZero = FALSE;
> +  }
> +
> +  ElapsedSeconds = GetPerformanceCounter () / TimerFreq;
> +
> +  // Don't report Year/Month since Leap Year logic is not implemented. This should
> +  // be fine since the sole purpose of this special implementation is to be
> +  // used for relative time measurement. e.g. Windows Boot Manager.
> +  Time->Year = 0;
> +  Time->Month = 0;

This is ... not exactly spec compliant, is it?

/
    Leif

> +
> +  CONST UINT64 SECONDS_PER_DAY = 24 * 60 * 60;
> +  Time->Day = (ElapsedSeconds / SECONDS_PER_DAY);
> +  ElapsedSeconds %= SECONDS_PER_DAY;
> +
> +  CONST UINT64 SECONDS_PER_HOUR = 60 * 60;
> +  Time->Hour = (ElapsedSeconds / SECONDS_PER_HOUR);
> +  ElapsedSeconds %= SECONDS_PER_HOUR;
> +
> +  CONST UINT64 SECONDS_PER_MINUTE = 60;
> +  Time->Minute = (ElapsedSeconds / SECONDS_PER_MINUTE);
> +  ElapsedSeconds %= SECONDS_PER_MINUTE;
> +
> +  Time->Second = ElapsedSeconds;
> +  Time->Nanosecond = 0;
> +  Time->TimeZone = 0;
> +  Time->Daylight = 0;
> +
> +  LOG_TRACE (
> +    "Time Elapsed Since Power-On: Day%d %dh:%dm:%ds",
> +    (UINT32)Time->Day,
> +    (UINT32)Time->Hour,
> +    (UINT32)Time->Minute,
> +    (UINT32)Time->Second);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Sets the current local time and date information.
> +
> +  @param  Time                  A pointer to the current time.
> +
> +  @retval EFI_UNSUPPORTED      This operation is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibSetTime (
> +  IN EFI_TIME *Time
> +  )
> +{
> +  // The virtual clock is read-only.
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Returns the current wakeup alarm clock setting.
> +
> +  @param  Enabled               Indicates if the alarm is currently enabled or
> +                                disabled.
> +  @param  Pending               Indicates if the alarm signal is pending and
> +                                requires acknowledgement.
> +  @param  Time                  The current alarm setting.
> +
> +  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibGetWakeupTime (
> +  OUT BOOLEAN *Enabled,
> +  OUT BOOLEAN *Pending,
> +  OUT EFI_TIME *Time
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Sets the system wakeup alarm clock time.
> +
> +  @param  Enabled               Enable or disable the wakeup alarm.
> +  @param  Time                  If Enable is TRUE, the time to set the wakeup alarm for.
> +
> +  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibSetWakeupTime (
> +  IN BOOLEAN Enabled,
> +  OUT EFI_TIME *Time
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  This is the declaration of an EFI image entry point. This can be the entry point
> +  to an application written to this specification, an EFI boot service driver,
> +  or an EFI runtime driver.
> +
> +  @param  ImageHandle           Handle that identifies the loaded image.
> +  @param  SystemTable           System Table for this image.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibRtcInitialize (
> +  IN EFI_HANDLE ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  // ARM ARCH Timer is already initialized in the SEC/PEI phase.
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Fixup internal data so that EFI can be call in virtual mode.
> +  Call the passed in Child Notify event and convert any pointers in
> +  lib to virtual mode.
> +
> +  @param[in]    Event   The Event that is being processed
> +  @param[in]    Context Event Context
> +**/
> +VOID
> +EFIAPI
> +LibRtcVirtualNotifyEvent (
> +  IN EFI_EVENT Event,
> +  IN VOID *Context
> +  )
> +{
> +  // Not supporting OS calling RTC functions in virtual mode.
> +  return;
> +}
> diff --git a/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
> new file mode 100644
> index 000000000000..54aacde8c741
> --- /dev/null
> +++ b/Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +#
> +#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = VirtualRealTimeClockLib
> +  FILE_GUID                      = 1E27D461-78F3-4F7D-B1C2-F72384F13A6E
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = RealTimeClockLib
> +
> +[Sources.common]
> +  VirtualRealTimeClockLib.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  IoLib
> +  TimerLib
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core
  2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
                   ` (26 preceding siblings ...)
  2018-09-21  8:26 ` [PATCH edk2-platforms 27/27] Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files Chris Co
@ 2018-12-15 13:32 ` Leif Lindholm
  2018-12-19 18:28   ` Chris Co
  27 siblings, 1 reply; 75+ messages in thread
From: Leif Lindholm @ 2018-12-15 13:32 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Chris,

Sorry for dragging this out, but it's been a crazy year.
I think I've now provided feedback for all but the SdMmc bits.

For the next revision, please break out SdMmc support (including and put it last
in the series). I still don't like the idea of adding a third driver
stack to the project, and am likely to have ideas of major
restructuring, but if we can isolate that from the rest, reviewing the
remainder should be reasonably quick next time around.

My last day "in the office" before Christmas is 21 December, and then
I'll be out until 7 January. So basically, if you can get a new set
out early nexy week, I may have a chance to look at it, and if not -
take your time :)

Regards,

Leif

On Fri, Sep 21, 2018 at 08:25:52AM +0000, Chris Co wrote:
> REF: https://github.com/christopherco/edk2-platforms/tree/winiot_hmb_v1
> 
> v0:
> * https://lists.01.org/pipermail/edk2-devel/2018-July/027213.html
> * https://lists.01.org/pipermail/edk2-devel/2018-July/027266.html
> * https://lists.01.org/pipermail/edk2-devel/2018-July/027333.html
> * https://lists.01.org/pipermail/edk2-devel/2018-July/027409.html
> 
> The patch set supports the bring up of Windows 10 IoT Core on
> Solidrun's Hummingboard Edge board running NXP's i.MX 6Quad SoC.
> 
> This patch set is a preliminary submission, with the goal to get further review
> feedback from maintainers since the v0 version had too many initial issues to
> conduct a full review.
> 
> Changes in this patch set from v0:
> * Merged the 4 previous patch sets into one.
> * All code should now follow the edk2 coding style.
> * SMBIOS driver refactored to use PCDs. Fixed UUID generation to use MAC address.
> * Updated ACPI HIDs to proper NXP IDs where applicable.
> * Removed unnecessary (and spec-violating) _DSD methods from our ACPI tables.
> * General code cleanup and refactoring.
> * Add Silicon package support for i.MX 6Solo/DualLite, 6SoloX, 6DualPlus/QuadPlus
> families in iMX6Pkg.
> 
> Known issues remaining from previous review:
> * Silicon/NXP/iMXPlatformPkg: SdhcDxe fixed initialization needs to be moved to
> a PlatformDxe init and use NonDiscoverableDeviceRegistrationLib.
> * Platform/Microsoft: Left in SdMmcDxe code. Alternatives are still under
> evaluation.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> 
> Christopher Co (27):
>   Platform/Microsoft: Add OpteeClientPkg dec
>   Platform/Microsoft: Add SdMmc Dxe Driver
>   Platform/Microsoft: Add MsPkg
>   Silicon/NXP: Add iMXPlatformPkg dec
>   Silicon/NXP: Add UART library support for i.MX platforms
>   Silicon/NXP: Add I2C library support for i.MX platforms
>   Silicon/NXP: Add i.MX display library support
>   Silicon/NXP: Add Virtual RTC support for i.MX platform
>   Silicon/NXP: Add headers for SoC-specific i.MX packages to use
>   Silicon/NXP: Add iMX6Pkg dec
>   Silicon/NXP: Add i.MX6 SoC header files
>   Silicon/NXP: Add i.MX6 I/O MUX library
>   Silicon/NXP: Add support for iMX SDHC
>   Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
>   Silicon/NXP: Add i.MX6 GPT Timer library
>   Silicon/NXP: Add i.MX6 Timer DXE driver
>   Silicon/NXP: Add i.MX6 USB Phy Library
>   Silicon/NXP: Add i.MX6 Clock Library
>   Silicon/NXP: Add i.MX6 ACPI tables
>   Silicon/NXP: Add i.MX6 Board init library
>   Silicon/NXP: Add i.MX6 PCIe DXE driver
>   Silicon/NXP: Add i.MX6 GOP driver
>   Silicon/NXP: Add i.MX6 Smbios Driver
>   Silicon/NXP: Add i.MX6 common dsc and fdf files
>   Platform/Solidrun: Add Hummingboard Peripheral Initialization
>   Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables
>   Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files
> 
>  Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c                                          |  548 +++++
>  Platform/Microsoft/Drivers/SdMmcDxe/Debug.c                                            |  363 +++
>  Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c                                         | 1775 ++++++++++++++
>  Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h                                         |  231 ++
>  Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c                                           |  609 +++++
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c                                            |  886 +++++++
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h                                            |  529 +++++
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf                                       |   49 +
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h                                          |  505 ++++
>  Platform/Microsoft/Include/Protocol/RpmbIo.h                                           |  268 +++
>  Platform/Microsoft/Include/Protocol/Sdhc.h                                             |  197 ++
>  Platform/Microsoft/MsPkg.dec                                                           |   39 +
>  Platform/Microsoft/MsPkg.dsc                                                           |   31 +
>  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec                                   |   49 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf                 |   55 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl                       |   38 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl                 |   71 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl            |   33 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl                   |   54 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl                   |   32 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl                   |  234 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl                  |  144 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl                   |   43 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl                  |  198 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl                   |  343 +++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc            |  141 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf            |  117 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c      |  634 +++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h      |  705 ++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf     |   91 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc                                               |  408 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc                                               |  142 ++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h                                           |  106 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl                                           |  106 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl                                            |   74 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl                                           |   55 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl                                            |   67 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl                                           |  298 +++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl                                       |  106 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl                                            |   85 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl                                           |  133 ++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl                                            |  103 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl                                           |   33 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc                                               |   60 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc                                               |  120 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc                                               |   92 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc                                               |   95 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc                                               |   53 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c                                             |  423 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h                                             |  277 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c                                               |   69 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h                                               |   28 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c                                           |  455 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h                                           |  175 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c                                 |  399 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h                                 |  331 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c                                  |  458 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h                                  |  195 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c                                              |   96 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h                                              |   33 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c                                            |  475 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h                                            |   20 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf                                          |   70 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c                                              |  761 ++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h                                              |  529 +++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c                                             |   88 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h                                             |   32 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h                                               |  236 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c                                              |   93 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h                                              |   67 +
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c                                | 1139 +++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h                                |  145 ++
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf                              |   66 +
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c                      | 1774 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h                      |   44 +
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf                    |   84 +
>  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c                                           |  278 +++
>  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf                                      |   55 +
>  Silicon/NXP/iMX6Pkg/Include/common_epit.h                                              |  118 +
>  Silicon/NXP/iMX6Pkg/Include/common_gpt.h                                               |  271 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6.h                                                     |   39 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h                                             |   55 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h                                               |  105 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h                                            |  181 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h                                           |  176 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h                                            |  190 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h                                                |  202 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h                                            | 2466 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h                                            | 1875 +++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h                                             | 2270 ++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h                                                |   24 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h                                               |   20 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h                                                  |  332 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h                                                 |  335 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h                                                 |  301 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h                                                  | 1730 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_common.h                                              | 1350 +++++++++++
>  Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c                                        |  246 ++
>  Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf                                      |   45 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S                             |   89 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c                                |  110 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c                                  |   88 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c                           |  107 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c                                 | 1876 +++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf                            |   46 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h                         |  221 ++
>  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c                                   |  151 ++
>  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf                              |   41 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c                                 |  328 +++
>  Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf                            |   43 +
>  Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc                                                  |  897 +++++++
>  Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc                                                  |  287 +++
>  Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc                                                  |  148 ++
>  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec                                                        |  143 ++
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c                                   | 1246 ++++++++++
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h                                   |   81 +
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf                                 |   70 +
>  Silicon/NXP/iMXPlatformPkg/Include/Platform.h                                          |   67 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h                                        |  114 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h                                           |   92 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h                                         |  162 ++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h                                          |   24 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h                                           |  207 ++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h                                          |  277 +++
>  Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c               |  243 ++
>  Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf             |   41 +
>  Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c   |  227 ++
>  Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf |   37 +
>  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c                       |  152 ++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf                     |   31 +
>  Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c                               |  487 ++++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf                             |   35 +
>  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec                                          |  118 +
>  133 files changed, 40660 insertions(+)
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Debug.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h
>  create mode 100644 Platform/Microsoft/Include/Protocol/RpmbIo.h
>  create mode 100644 Platform/Microsoft/Include/Protocol/Sdhc.h
>  create mode 100644 Platform/Microsoft/MsPkg.dec
>  create mode 100644 Platform/Microsoft/MsPkg.dsc
>  create mode 100644 Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/common_epit.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/common_gpt.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_common.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/Platform.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
> 
> -- 
> 2.16.2.gvfs.1.33.gf5370f1
> 


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
  2018-09-21  8:26 ` [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables Chris Co
  2018-12-14 19:53   ` Leif Lindholm
@ 2018-12-17 11:14   ` Ard Biesheuvel
  2019-01-08 21:43     ` Chris Co
  1 sibling, 1 reply; 75+ messages in thread
From: Ard Biesheuvel @ 2018-12-17 11:14 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Leif Lindholm, Michael D Kinney

On Fri, 21 Sep 2018 at 10:26, Chris Co <Christopher.Co@microsoft.com> wrote:
>
> This adds baseline ACPI table support for booting Windows on
> NXP i.MX6 SoCs.  Platforms may override these tables as necessary.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc         | 408 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc         | 142 +++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h     | 106 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl     | 106 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl      |  74 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl     |  55 +++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl      |  67 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl     | 298 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl | 106 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl      |  85 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl     | 133 +++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl      | 103 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl     |  33 ++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc         |  60 +++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc         | 120 ++++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc         |  92 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc         |  95 +++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc         |  53 +++
>  18 files changed, 2136 insertions(+)
>
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
> new file mode 100644
> index 000000000000..82c2420a2b7e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
> @@ -0,0 +1,408 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include "../Include/Platform.h"
> +#include "../Include/iMX6.h"
> +

Please don't use relative includes. Instead, make sure all packages
you depend on are included in the .inf, and make sure the .dec files
of those packages accurately describe the paths of all include files
they expose.

> +#pragma pack(push, iMX6Csrt, 1)
> +
> +// Timer Resource Group
> +// Each timer consumes 4K of address space.
> +#define TIMER_ADDRES_SIZE 0x1000
> +#define TIMER_CAP_ALWAYS_ON     0x00000001 // Timer is always ON.
> +#define TIMER_CAP_UP_COUNTER    0x00000002 // Up counter vs. down counter (0)
> +#define TIMER_CAP_READABLE      0x00000004 // Counter has a software interface.
> +#define TIMER_CAP_PERIODIC      0x00000008 // Can generate periodic interrupts.
> +#define TIMER_CAP_DRIVES_IRQ    0x00000010 // Timer interrupt drives a physical IRQ.
> +#define TIMER_CAP_ONE_SHOT      0x00000020 // Counter can generate one-shot interrupts
> +
> +// Timer source clock codes
> +typedef enum {
> +  GPT_CLOCK_NONE        = 0,
> +  GPT_CLOCK_PERIPHERAL  = 1,
> +  GPT_CLOCK_HI_FREQ     = 2,
> +  GPT_CLOCK_EXT         = 3,
> +  GPT_CLOCK_LOW_FREQ    = 4,
> +#if defined(CPU_IMX6DQ) || defined (CPU_IMX6DQP)
> +  GPT_CLOCK_OSC_DIV_8   = 5,
> +  GPT_CLOCK_OSC         = 7,
> +#elif (defined(CPU_IMX6SDL) || defined(CPU_IMX6SX))
> +  GPT_CLOCK_OSC         = 5,
> +#else
> +#error iMX6 CPU Type Not Defined (Preprocessor Flag)
> +#endif
> +} GPT_SOURCE_CLOCK;
> +
> +// EPIT timer source clock codes
> +typedef enum {
> +  EPIT_CLOCK_NONE        = 0,
> +  EPIT_CLOCK_PERIPHERAL  = 1,
> +  EPIT_CLOCK_HI_FREQ     = 2,
> +  EPIT_CLOCK_LOW_FREQ    = 3,
> +} EPIT_SOURCE_CLOCK;
> +
> +// Timer descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
> +  UINT32 Capabilities;
> +  UINT32 Width;
> +  UINT32 Source;
> +  UINT32 Frequency;
> +  UINT32 FrequencyScale;
> +  UINT32 BaseAddress;
> +  UINT32 Size;
> +  UINT32 Interrupt;
> +  UINT32 ChipType;
> +} RD_TIMER;
> +
> +// Resource Group Shared Info
> +typedef struct {
> +  UINT16 RevMajor;
> +  UINT16 RevMinor;
> +  UINT32 ChipType;
> +} RG_PLATFORM_INFORMATION;
> +
> +// Timer group descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
> +  RG_PLATFORM_INFORMATION PlatformInfo;
> +#if defined(CPU_IMX6SDL)
> +  RD_TIMER Timers[3];
> +#else
> +  RD_TIMER Timers[4];
> +#endif
> +} RG_TIMER;
> +
> +// PL310 L2 Cache Controller Resource Group
> +#define CSRT_PL310_MINIMUM_VERSION   1
> +#define CSRT_PL310_VERSION_2         2
> +#define CSRT_PL310_RAW_PROTOCOL      0
> +#define CSRT_PL310_SMC_PROTOCOL      1
> +
> +// We use PSCI_CPU_ON to turn on the L2 cache, with special value
> +// 0x00100000 for the Core ID. PSCI sees this core ID and knows
> +// this is an L2 cache operation, then looks at R2 for the
> +// operation to perform.
> +#define PSCI_FID_CPU_ON                        0x84000003
> +#define L2CACHE_SMC_R1                         0x00100000
> +#define L2CACHE_OP_ENABLE                      1
> +#define L2CACHE_OP_DISABLE                     2
> +#define L2CACHE_OP_ENABLE_WRITEBACK            3
> +#define L2CACHE_OP_DISABLE_WRITEBACK           4
> +#define L2CACHE_OP_ENABLE_WFLZ                 5
> +

Who defined this protocol? Where is the opposite side implemented?

Overloading architected PSCI calls to manage platform specific pieces
is really a no-go.

> +typedef struct {
> +  UINT32 Immediate;
> +  UINT32 R0;
> +  UINT32 R1;
> +  UINT32 R2;
> +  UINT32 R3;
> +  UINT32 R12;
> +} CSRT_SMC_INVOCATION_BLOCK;
> +
> +// L2 cache descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
> +  UINT32 Version;
> +  UINT32 ManagementProtocol;
> +  UINT64 Address;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeEnable;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeDisable;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeEnableWriteback;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeDisableWriteback;
> +  CSRT_SMC_INVOCATION_BLOCK InvokeEnableWFLZ;
> +} RD_L2_CACHE;
> +
> +// PL310 L2 cache controller descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
> +  RD_L2_CACHE L2Cache;
> +} RG_L2_CACHE;
> +
> +// SmartDMA (SDMA) Controller Resource Group
> +enum IMX_SDMA_CORE_CLOCK_RATIO {
> +  IMX_SDMA_CORE_CLOCK_TWICE_CORE_FREQ = 0,
> +  IMX_SDMA_CORE_CLOCK_EQUALS_CORE_FREQ = 1
> +};
> +
> +// SDMA controller descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
> +  UINT32 ChipType; // IMX_CHIP_TYPE
> +  UINT64 RegistersBaseAddress;
> +  UINT64 IoMuxGPR0Address;
> +  UINT32 Interrupt;
> +  UINT32 SdmaCoreClockRatio; // IMX_SDMA_CORE_CLOCK_RATIO
> +} RD_SDMA;
> +
> +// SDMA controller group descriptor
> +typedef struct {
> +  EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER Header;
> +  RD_SDMA Sdma;
> +} RG_SDMA;
> +
> +
> +// CSRT structure for this platform
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER CsrtHeader; // Standard ACPI Header
> +  RG_TIMER TimerResourceGroup;            // Timer Resource Group
> +#ifndef CONFIG_L2CACHE_OFF
> +  RG_L2_CACHE L2CacheResourceGroup;       // PL310 L2 Cache Resource Group
> +#endif
> +  RG_SDMA SdmaResourceGroup;              // SDMA Resource Group
> +} EFI_ACPI_CSRT_TABLE;
> +
> +#pragma pack (pop, iMX6Csrt)
> +
> +EFI_ACPI_CSRT_TABLE Csrt = {

Please make this STATIC

> +  // CSRT Header
> +  {
> +    EFI_ACPI_5_0_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE,  // Signature "CSRT"
> +    sizeof (EFI_ACPI_DESCRIPTION_HEADER) +              // Length
> +    sizeof (RG_TIMER)
> +#ifndef CONFIG_L2CACHE_OFF
> +    + sizeof (RG_L2_CACHE)
> +#endif
> +    + sizeof (RG_SDMA),
> +    EFI_ACPI_5_0_CSRT_REVISION,                         // Revision
> +    0x00,                                               // Checksum calculated at runtime.
> +    EFI_ACPI_OEM_ID,                                    // OEMID is a 6 bytes long field.
> +    EFI_ACPI_OEM_TABLE_ID,                              // OEM table identification(8 bytes long).
> +    EFI_ACPI_OEM_REVISION,                              // OEM revision number.
> +    EFI_ACPI_CREATOR_ID,                                // ASL compiler vendor ID.
> +    EFI_ACPI_CREATOR_REVISION,                          // ASL compiler revision number.
> +  },
> +
> +  // TimerResourceGroup
> +  {
> +    // Timer group header
> +    {
> +      sizeof (RG_TIMER),              // Resource Group Length
> +      EFI_ACPI_VENDOR_ID,             // VendorId
> +      0,                              // SubvendorId
> +      0x0101,                         // DeviceId
> +      0,                              // SubdeviceId
> +      0,                              // Revision
> +      0,                              // Reserved
> +      sizeof (RG_PLATFORM_INFORMATION) // Platform Information shared info
> +    },
> +
> +    // Platform Information
> +    {
> +      0x0001,                        // RevMajor
> +      0x0000,                        // RevMinor
> +      0,                             // IMX_CHIP_TYPE (not used)
> +    },
> +
> +    // Timers
> +    {
> +      // Counter (GPT)
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          3,                              // ResourceId
> +        },
> +        TIMER_CAP_READABLE | TIMER_CAP_UP_COUNTER, // Capabilities
> +        32,                                 // Timer width (bits)
> +        GPT_CLOCK_OSC,                      // Source is 111b for QD, 101b for SDL
> +        SOC_OSC_FREQUENCY_REF_HZ,           // Frequency 24 MHz
> +        24,                                 // divider to make 1 MHz
> +        CSP_BASE_REG_PA_GPT,                // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        0,                                  // N.B. No interrupt on this counter
> +      },
> +
> +      // Timer0 (EPIT1)
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          4,                              // ResourceId
> +        },
> +        TIMER_CAP_ONE_SHOT | TIMER_CAP_PERIODIC | // Capabilities
> +        TIMER_CAP_ALWAYS_ON | TIMER_CAP_DRIVES_IRQ,
> +        32,                                 // Timer width (bits)
> +        EPIT_CLOCK_LOW_FREQ,                // Source
> +        SOC_LOW_FREQ_REF_HZ,                // Frequency
> +        1,                                  // Frequency scale
> +        CSP_BASE_REG_PA_EPIT1,              // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        IRQ_EPIT1,                          // Interrupt
> +      },
> +
> +      // Timer1 (EPIT2)
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          5,                              // ResourceId
> +        },
> +        TIMER_CAP_ONE_SHOT | TIMER_CAP_PERIODIC | // Capabilities
> +        TIMER_CAP_ALWAYS_ON | TIMER_CAP_DRIVES_IRQ,
> +        32,                                 // Timer width (bits)
> +        EPIT_CLOCK_LOW_FREQ,                // Source
> +        SOC_LOW_FREQ_REF_HZ,                // Frequency
> +        1,                                  // Frequency scale
> +        CSP_BASE_REG_PA_EPIT2,              // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        IRQ_EPIT2,                          // Interrupt
> +      },
> +
> +#if defined(CPU_IMX6DQ)
> +      // SNVS LP Real Time Counter
> +      {
> +        {
> +          sizeof (RD_TIMER),              // Resource Descriptor Length
> +          EFI_ACPI_CSRT_RD_TYPE_TIMER,    // Resource Type
> +          EFI_ACPI_CSRT_RD_SUBTYPE_TIMER, // Resource Subtype
> +          6,                              // ResourceId
> +        },
> +        TIMER_CAP_UP_COUNTER |              // Capabilities
> +        TIMER_CAP_READABLE |
> +        TIMER_CAP_ALWAYS_ON,
> +        47,                                 // Timer width (bits)
> +        0,                                  // Source (NA)
> +        SOC_LOW_FREQ_REF_HZ,                // Frequency
> +        1,                                  // Frequency scale
> +        IMX_SNVS_BASE,                      // 32 bit Physical address
> +        TIMER_ADDRES_SIZE,                  // Size of timer address space
> +        IMX_SNVS_IRQ,                       // Interrupt
> +      },
> +#endif
> +    }
> +  },
> +
> +#ifndef CONFIG_L2CACHE_OFF
> +  // L2CacheResourceGroup
> +  {
> +    // L2 cache group header
> +    {
> +      sizeof (RG_L2_CACHE),           // Resource Group Length
> +      SIGNATURE_32 ('A', 'R', 'M', 'H'), // VendorId
> +      SIGNATURE_32 ('A', 'R', 'M', 'H'), // SubvendorId
> +      0x0310,                         // DeviceId
> +      0,                              // SubdeviceId
> +      0,                              // Revision
> +      0,                              // Reserved
> +      0                               // No shared info
> +    },
> +
> +    // PL310 L2 cache controller
> +    {
> +      {
> +        sizeof (RD_L2_CACHE),           // Resource Descriptor Length
> +        EFI_ACPI_CSRT_RD_TYPE_CACHE,    // Resource Type
> +        EFI_ACPI_CSRT_RD_SUBTYPE_CACHE, // Resource Subtype
> +        0,                              // UID
> +      },
> +      CSRT_PL310_VERSION_2,               // Version
> +      CSRT_PL310_SMC_PROTOCOL,            // Management Protocol
> +      CSP_BASE_REG_PA_PL310,              // 64 bit Physical address
> +      // InvokeEnable
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_ENABLE,              // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeDisable
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_DISABLE,             // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeEnableWriteback
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_ENABLE_WRITEBACK,    // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeDisableWriteback
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_DISABLE_WRITEBACK,   // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +
> +      // InvokeEnableWFLZ
> +      {
> +        0,                              // Immediate
> +        PSCI_FID_CPU_ON,                // R0
> +        L2CACHE_SMC_R1,                 // R1
> +        L2CACHE_OP_ENABLE_WFLZ,         // R2
> +        0,                              // R3
> +        0,                              // R12
> +      },
> +    },
> +  },
> +#endif
> +
> +  // SdmaResourceGroup
> +  {
> +    // SDMA group header
> +    {
> +      sizeof (RG_SDMA),               // Resource Group Length
> +      EFI_ACPI_VENDOR_ID,             // VendorId
> +      0,                              // SubvendorId
> +      0x0111,                         // DeviceId
> +      0,                              // SubdeviceId
> +      0,                              // Revision
> +      0,                              // Reserved
> +      0                               // No shared info
> +    },
> +
> +    // SDMA controller resource
> +    {
> +      {
> +        sizeof (RD_SDMA),                           // Resource Descriptor Length
> +        EFI_ACPI_CSRT_RD_TYPE_DMA,                  // Resource Type
> +        EFI_ACPI_CSRT_RD_SUBTYPE_DMA_CONTROLLER,    // Resource Subtype
> +        0,                                          // UID
> +      },
> +      0,                                    // IMX_CHIP_TYPE (not used)
> +      CSP_BASE_REG_PA_SDMA,                 // SDMA registers base physical address
> +      IOMUXC_GPR_BASE_ADDRESS,              // IoMuxGPR0 physical address
> +      IRQ_SDMA,                             // IRQ number
> +      IMX_SDMA_CORE_CLOCK_TWICE_CORE_FREQ,  // DMA/SDMA Core Clock Ratio:
> +    },
> +  }
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  // Reference the table being generated to prevent the optimizer from removing the
> +  // data structure from the executable
> +  return (VOID *)&Csrt;
> +}

Please use a rodata reference, not a code reference (there are
numerous examples in edk2-platforms)

A code reference forces 4 KB alignment on AARCH64 with some compilers,
and even if this is 32-bit code only (at the moment), I prefer to have
rodata references across the board.

> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
> new file mode 100644
> index 000000000000..65ce03d470ee
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
> @@ -0,0 +1,142 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Platform.h>
> +
> +#include "iMX6.h"
> +
> +// DBG2 Definitions
> +#pragma pack (1)
> +
> +typedef enum {
> +  DBG2_TYPE_SERIAL = 0x8000,
> +  DBG2_TYPE_1394,
> +  DBG2_TYPE_USB,
> +  DBG2_TYPE_NET
> +} DBG2_PORT_TYPE;
> +
> +#define EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION 0x00000000
> +#define UART_NAME_SPACE_STRING_LENGTH               sizeof("\\_SB.UAR1")
> +#define UART_IMX6_UART_ADDRESS_SIZE       0x000000BC
> +
> +#if FixedPcdGet32(PcdKdUartInstance) == 1
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART1
> +#define KD_UART_ACPI_PATH "\\_SB.UAR1"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 2
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART2
> +#define KD_UART_ACPI_PATH "\\_SB.UAR2"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 3
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART3
> +#define KD_UART_ACPI_PATH "\\_SB.UAR3"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 4
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART4
> +#define KD_UART_ACPI_PATH "\\_SB.UAR4"
> +#elif FixedPcdGet32(PcdKdUartInstance) == 5
> +#define KD_UART_BASE_ADDR CSP_BASE_REG_PA_UART5
> +#define KD_UART_ACPI_PATH "\\_SB.UAR5"
> +#else
> +#error "Invalid PcdKdUartInstance. Must be 1, 2, 3, 4, or 5"
> +#endif
> +
> +// ACPI 5.0 DBG2 structure
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER   Header;
> +  UINT32                        OffsetDbgDeviceInfo;
> +  UINT32                        NumberDbgdeviceInfo;
> +} EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER;
> +
> +typedef struct {
> +  UINT8 Revision;
> +  UINT16 Length;
> +  UINT8 NumberofGenericAddressRegisters;
> +  UINT16 NameSpaceStringLength;
> +  UINT16 NameSpaceStringOffset;
> +  UINT16 OemDataLength;
> +  UINT16 OemDataOffset;
> +  UINT16 PortType;
> +  UINT16 PortSubtype;
> +  UINT16 Reserved;
> +  UINT16 BaseAddressRegisterOffset;
> +  UINT16 AddressSizeOffset;
> +} DEBUG_DEVICE_INFO;
> +
> +typedef struct {
> +  DEBUG_DEVICE_INFO DeviceInfo;
> +  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> +  UINT32 AddressSize;
> +  char NameSpaceString[UART_NAME_SPACE_STRING_LENGTH];
> +} DEBUG_DEVICE_INFO_UART;
> +
> +typedef struct {
> +  EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER Header;
> +  DEBUG_DEVICE_INFO_UART Uart;
> +} EFI_ACPI_5_0_DEBUG_PORT_2_TABLE;
> +
> +#pragma pack ()
> +
> +// Debug Port 2 table
> +EFI_ACPI_5_0_DEBUG_PORT_2_TABLE Dbg2 = {

STATIC

> +  {
> +    // Header
> +    {
> +      EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_SIGNATURE,     // Signature "DBG2"
> +      sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE),      // Length
> +      EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION,          // Revision
> +      EFI_ACPI_5_0_UNDEFINED,                        // Checksum - updated at runtime
> +      EFI_ACPI_OEM_ID,                               // OEM ID[6]
> +      EFI_ACPI_OEM_TABLE_ID,                         // OEM Table ID
> +      EFI_ACPI_OEM_REVISION,                         // OEM Revision
> +      EFI_ACPI_CREATOR_ID,                           // Creator ID
> +      EFI_ACPI_CREATOR_REVISION                      // Creator Revision
> +    },
> +    sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER), // OffsetDbgDeviceinfo
> +    1,                                               // NumberDbgDeviceInfo
> +  },
> +  {
> +    // Uart
> +    {
> +      // DeviceInfo
> +      EFI_ACPI_RESERVED_BYTE,                                 // Revision
> +      sizeof (DEBUG_DEVICE_INFO_UART),                        // Length
> +      1,                                                      // NumberofGenericAddressRegisters
> +      UART_NAME_SPACE_STRING_LENGTH,                          // NameSpaceStringLength
> +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, NameSpaceString),    // NameSpaceStringOffset
> +      0,                                                      // OemDataLength
> +      EFI_ACPI_RESERVED_WORD,                                 // OemDataOffset
> +      DBG2_TYPE_SERIAL,                                       // PortType
> +      DBG_PORT_SUBTYPE_IMX6,                                  // PortSubtype 000Ch

Is this subtype defined in a published version of the SPCR/DBG2 specs?

> +      EFI_ACPI_RESERVED_WORD,                                 // Reserved
> +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, BaseAddressRegister), // BaseAddressRegisterOffset
> +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, AddressSize),        // AddressSizeOffset
> +    },
> +    {
> +      // BaseAddressRegister
> +      EFI_ACPI_5_0_SYSTEM_MEMORY,                             // AddressSpaceId
> +      0x20,                                                   // RegisterBitWidth = 32
> +      0,                                                      // RegisterBitOffset = 0
> +      0x20,                                                   // AccessSize = 32
> +      KD_UART_BASE_ADDR,                                      // Address
> +    },
> +    UART_IMX6_UART_ADDRESS_SIZE,                                // AddressSize
> +    KD_UART_ACPI_PATH,                                          // NameSpaceString
> +  },
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (void *) &Dbg2;
> +}

rodata reference please. I will stop commenting on this for the
remainder of the patch.

> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> new file mode 100644
> index 000000000000..4e4a3522e842
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> @@ -0,0 +1,106 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// IMX alternate settings codes
> +#define IMX_ALT0 0x0
> +#define IMX_ALT1 0x1
> +#define IMX_ALT2 0x2
> +#define IMX_ALT3 0x3
> +#define IMX_ALT4 0x4
> +#define IMX_ALT5 0x5
> +#define IMX_ALT6 0x6
> +#define IMX_ALT7 0x7
> +
> +// IMX SDMA request lines.
> +// These are logical values, the mapping to the SOC
> +// actual DMA request lines are done in the HAL extension.
> +#define SDMA_REQ_VPU 0
> +#define SDMA_REQ_IPU2 1
> +#define SDMA_REQ_IPU1 2
> +#define SDMA_REQ_HDMI_AUDIO 3
> +#define SDMA_REQ_ECSPI1_RX 4
> +#define SDMA_REQ_ECSPI1_TX 5
> +#define SDMA_REQ_ECSPI2_RX 6
> +#define SDMA_REQ_ECSPI2_TX 7
> +#define SDMA_REQ_ECSPI3_RX 8
> +#define SDMA_REQ_ECSPI3_TX 9
> +#define SDMA_REQ_ECSPI4_RX 10
> +#define SDMA_REQ_ECSPI4_TX 11
> +#define SDMA_REQ_ECSPI5_RX 12
> +#define SDMA_REQ_ECSPI5_TX 13
> +#define SDMA_REQ_I2C1_RX 14
> +#define SDMA_REQ_I2C1_TX 15
> +#define SDMA_REQ_I2C2_RX 16
> +#define SDMA_REQ_I2C2_TX 17
> +#define SDMA_REQ_I2C3_RX 18
> +#define SDMA_REQ_I2C3_TX 19
> +#define SDMA_REQ_UART1_RX 20
> +#define SDMA_REQ_UART1_TX 21
> +#define SDMA_REQ_UART2_RX 22
> +#define SDMA_REQ_UART2_TX 23
> +#define SDMA_REQ_UART3_RX 24
> +#define SDMA_REQ_UART3_TX 25
> +#define SDMA_REQ_UART4_RX 26
> +#define SDMA_REQ_UART4_TX 27
> +#define SDMA_REQ_UART5_RX 28
> +#define SDMA_REQ_UART5_TX 29
> +#define SDMA_REQ_SPDIF_RX 30
> +#define SDMA_REQ_SPDIF_TX 31
> +#define SDMA_REQ_EPIT1 32
> +#define SDMA_REQ_EPIT2 33
> +#define SDMA_REQ_GPT 34
> +#define SDMA_REQ_ASRC_RXA 35
> +#define SDMA_REQ_ASRC_RXB 36
> +#define SDMA_REQ_ASRC_RXC 37
> +#define SDMA_REQ_ASRC_TXA 38
> +#define SDMA_REQ_ASRC_TXB 39
> +#define SDMA_REQ_ASRC_TXC 40
> +#define SDMA_REQ_ESAI_RX 41
> +#define SDMA_REQ_ESAI_TX 42
> +#define SDMA_REQ_ASRC_TXA_2_ESAI_TX 43
> +#define SDMA_REQ_ASRC_TXB_2_ESAI_TX 44
> +#define SDMA_REQ_ASRC_TXC_2_ESAI_TX 45
> +#define SDMA_REQ_SSI1_RX1 46
> +#define SDMA_REQ_SSI1_TX1 47
> +#define SDMA_REQ_SSI1_RX0 48
> +#define SDMA_REQ_SSI1_TX0 49
> +#define SDMA_REQ_SSI2_RX1 50
> +#define SDMA_REQ_SSI2_TX1 51
> +#define SDMA_REQ_SSI2_RX0 52
> +#define SDMA_REQ_SSI2_TX0 53
> +#define SDMA_REQ_SSI3_RX1 54
> +#define SDMA_REQ_SSI3_TX1 55
> +#define SDMA_REQ_SSI3_RX0 56
> +#define SDMA_REQ_SSI3_TX0 57
> +#define SDMA_REQ_EXT1 58
> +#define SDMA_REQ_EXT2 59
> +#define SDMA_REQ_UART6_RX 60
> +#define SDMA_REQ_UART6_TX 61
> +#define SDMA_REQ_ADC1 62
> +#define SDMA_REQ_ADC2 63
> +#define SDMA_REQ_I2C4_RX 64
> +#define SDMA_REQ_I2C4_TX 65
> +#define SDMA_REQ_CSI1 66
> +#define SDMA_REQ_CSI2 67
> +#define SDMA_REQ_PXP 68
> +#define SDMA_REQ_LCDIF1 69
> +#define SDMA_REQ_LCDIF2 70
> +#define SDMA_REQ_QSPI1_RX 71
> +#define SDMA_REQ_QSPI1_TX 72
> +#define SDMA_REQ_QSPI2_RX 73
> +#define SDMA_REQ_QSPI2_TX 74
> +#define SDMA_REQ_SAI1_TX 75
> +#define SDMA_REQ_SAI1_RX 76
> +#define SDMA_REQ_SAI2_TX 77
> +#define SDMA_REQ_SAI2_RX 78
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> new file mode 100644
> index 000000000000..eded7cdae7d0
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> @@ -0,0 +1,106 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (ENET)
> +{
> +  Name (_HID, "NXP010D")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xF)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // ENET MAC Core Base address
> +      MEMORY32FIXED (ReadWrite, 0x02188000, 0x4000, )
> +
> +      // ENET MAC 0 Core IRQ
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 150 }
> +
> +      // ENET MAC 0 1588 Timer interrupt
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 151 }
> +
> +      // Errata ERR006687: workaround for GPIO interrupt to connect Enet interrupt
> +      // to the GPC
> +      GpioInt (Level, ActiveHigh, Shared, PullDefault, 0, "\\_SB.GPIO",) { 6 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Name (MAC, Buffer (6) {})
> +  CreateDWordField (MAC, 0x00, MACL)
> +  CreateWordField (MAC, 0x04, MACH)
> +
> +  // Device Specific Method takes 4 args:
> +  //  Arg0 : Buffer containing a UUID [16 bytes]
> +  //  Arg1 : Integer containing the Revision ID
> +  //  Arg2 : Integer containing the Function Index
> +  //  Arg3 : Package that contains function-specific arguments
> +  Method (_DSM, 0x4, NotSerialized) {
> +    switch (ToBuffer (Arg0)) {
> +    // iMX Enet interface identifier
> +    case (ToUUID ("4EBBCB9D-4087-4791-80BD-8F8C08024206")) {
> +        // Function selector
> +        switch (Arg2) {
> +        // Function 0: Query support
> +        //   Bit  Description
> +        //   ---  -------------------------------
> +        //     0  Get property (Function 0)
> +        //     1  Enet PHY address on MDIO bus (Function 1)
> +        //     2  Get Mac Address (Function 2)
> +        //     3  Get MDIO BAse Address (Function 3)
> +        case (0) {
> +            // Revision selector
> +            switch (Arg1) {
> +            case (0) {
> +                // Functions {0,1,2} supported
> +                Return (Buffer() { 0x07 });
> +              }
> +            default {
> +                Return (Buffer() { 0x00 });
> +              }
> +            }
> +          }
> +
> +        // Function 1: Return Enet PHY address on MDIO bus.
> +        case (1) {
> +            Return (0x00);
> +          }
> +
> +        // Function 2: Return Mac Address
> +        case (2) {
> +            if (LEqual (SIGN, 0x474C424C)) {
> +              if (LEqual (REVN, 1)) {
> +                if (Lequal (MC0V, 1)) {
> +                  Store (MC0L, MACL);
> +                  Store (MC0H, MACH);
> +                  Return (MAC)
> +                }
> +              }
> +            }
> +            Return (Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
> +          }
> +
> +        default {
> +            Return (Buffer() { 0x00 });
> +          }
> +        }
> +      }
> +    default {
> +        Return (Buffer() { 0x00 });
> +      }
> +    }
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> new file mode 100644
> index 000000000000..eec71864210e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> @@ -0,0 +1,74 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (VPU0)
> +{
> +  Name (_HID, "NXP0109")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0x0)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02040000, 0x3C000, )
> +
> +      // JPEG codec interrupt request
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 35 }
> +
> +      // VPU interrupt request
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 44 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +// Description: Graphics Processing Unit (GPU)
> +Device (GPU0)
> +{
> +  Name (_HID, "VERI2000")
> +  Name (_CID, "VERI2000")
> +  Name (_UID, 0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // GPU 3D (GC2000)
> +      MEMORY32FIXED (ReadWrite, 0x00130000, 0x4000, )
> +
> +      // GPU 2D (GC320)
> +      MEMORY32FIXED (ReadWrite, 0x00134000, 0x4000, )
> +
> +      // IPU Base
> +      MEMORY32FIXED (ReadWrite, 0x02600000, 0x400000, )
> +
> +      // HDMI PHY
> +      MEMORY32FIXED (ReadWrite, 0x00120000, 0x9000, )
> +
> +      // GC2000
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 41 }
> +
> +      // GC320
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
> +
> +      // IPU1 sync interrupt request
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 38 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> new file mode 100644
> index 000000000000..d9a5d2f8500a
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> @@ -0,0 +1,55 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (GPIO)
> +{
> +  Name (_HID, "NXP0103")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // GPIO1-7
> +      MEMORY32FIXED (ReadWrite, 0x0209C000, 0x1C000, )
> +
> +      // IOMUXC
> +      MEMORY32FIXED (ReadWrite, 0x020E0000, 0x4000, )
> +
> +      // GPIO1 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 98, 99 }
> +
> +      // GPIO2 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 100, 101 }
> +
> +      // GPIO3 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 102, 103 }
> +
> +      // GPIO4 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 104, 105 }
> +
> +      // GPIO5 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 106, 107 }
> +
> +      // GPIO6 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 108, 109 }
> +
> +      // GPIO7 0-15, 16-31
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 110, 111 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> new file mode 100644
> index 000000000000..af9f17890b97
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> @@ -0,0 +1,67 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (I2C1)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (I2C2)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A4000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 69 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (I2C3)
> +{
> +  Name (_HID, "NXP0104")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> new file mode 100644
> index 000000000000..1e0627f93000
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> @@ -0,0 +1,298 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (PCI0)
> +{
> +  Name (_HID, "PNP0A08")
> +  Name (_UID, 0)
> +  Name (_STR, Unicode ("PCIe 0 Device"))
> +  Name (_BBN, 0)
> +  Name (_SEG, 0)
> +

Please include a _CCA property for all DMA capable device objects -
this is mandatory for ACPI on ARM, and even if Linux today does not
support ACPI on 32-bit, I'd like to ensure that this code could work
on Linux if we ever do support it.

> +  // PCIE_PL memory map
> +  OperationRegion (PLGC, SystemMemory, 0x01FFC700, 0x220)
> +  Field (PLGC, DWordAcc, NoLock, Preserve) {
> +    Offset (0x2C),  // Skip to register 0x01FFC72C
> +    DBG1, 32,       // PCIE_PL_DEBUG1
> +  }
> +
> +  // IOMUXC memory map
> +  OperationRegion (IMXC, SystemMemory, 0x020E0000, 0x4000)
> +  Field (IMXC, DWordAcc, NoLock, Preserve) {
> +    Offset (0x04),  // Skip to register 0x020E0004
> +    GPR1, 32,       // IOMUXC_GPR1
> +  }
> +
> +  // PCIe is only available if PCIe PHY reference clock is enabled and link is up
> +  Method (_STA) {
> +    Name (LNK, 0x0);
> +    Name (GPR, 0x0);
> +    Store (GPR1, GPR);  // read IOMUXC_GPR1 register
> +
> +    // Check if the PCIe PHY reference clock is enabled
> +    If (LNotEqual (And (GPR, 0x00010000), 0x00010000)) {
> +      Return (0x0)
> +    }
> +
> +    Store (DBG1, LNK);  // read PCIE_PL_DEBUG1 register
> +
> +    // Check if link is already up and is not in training
> +    //  Bit4  : [36]: xmlh_link_up LTSSM reports PHY link up
> +    //  Bit29  : [61]: xmlh_link_in_training LTSSM performing link training
> +    If (LAnd (And (DBG1, 0x00000010), Lequal (And (DBG1, 0x20000000), 0x00))) {
> +      Return (0xF)
> +    } else {
> +      Return (0x0)
> +    }
> +  }
> +
> +  // Declare the resources assigned to this root complex.
> +  Method (_CRS, 0, Serialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      WordBusNumber (
> +        ResourceProducer, // Specify bus ranged is passed to child devices
> +        MinFixed,         // Specify min address is fixed
> +        MaxFixed,         // Specify max address is fixed
> +        PosDecode,        // Positive decode of bus number
> +        0,                // AddressGranularity 2 power of 0
> +        0,                // AddressMinimum - Minimum Bus Number
> +        1,                // AddressMaximum - Maximum Bus Number
> +        0,                // AddressTranslation - Set to 0
> +        2)                // RangeLength - Number of Busses
> +
> +      // PCI memory space
> +      Memory32Fixed (ReadWrite, 0x01100000, 0x00E00000, )
> +    })
> +    Return (RBUF)
> +  }
> +
> +  // Declare the PCI Routing Table.
> +  Name (_PRT, Package() {
> +    // Routing for device 0, all functions.
> +    // Note: ARM doesn't support LNK nodes, so the third param
> +    // is 0 and the fourth param is the SPI number of the interrupt
> +    // line.

ARM supports LNK nodes just fine, so I suppose it is Windows on ARM
that does not support them? Otherwise, just drop the comment - LNK
nodes don't really buy us anything here anyway, so the current
description works just fine.

> +    Package() {0x0000FFFF, 0, 0, 155}, // INTA
> +    Package() {0x0000FFFF, 1, 0, 154}, // INTB
> +    Package() {0x0000FFFF, 2, 0, 153}, // INTC
> +    Package() {0x0000FFFF, 3, 0, 152}, // INTD/MSI
> +  })
> +
> +  Name (SUPP, 0) // PCI _OSC Support Field value
> +  Name (CTRL, 0) // PCI _OSC Control Field value
> +
> +  // Declare an _OSC (OS Control Hand-off) method which takes 4 arguments.
> +  //
> +  // Arguments:
> +  //   Arg0  A Buffer containing a UUID
> +  //   Arg1  An Integer containing a Revision ID of the buffer format
> +  //   Arg2  An Integer containing a count of entries in Arg3
> +  //   Arg3  A Buffer containing a list of DWORD capabilities
> +  // Return Value:
> +  //   A Buffer containing a list of capabilities
> +  Method (_OSC, 4) {
> +
> +    // Create DWord-addressable fields from the Capabilities Buffer
> +    // Create CDW1 outside the test as it's used in the else clause.
> +    // The first DWORD in the _OSC Capabilities Buffer contains bits
> +    // that are generic to _OSC
> +    // PCI Firmware Specification - 4.5.1.
> +    //
> +    // ACPI - 6.2.10
> +    // CDW return value information
> +    // Bit 0 - Reserved (not used)
> +    // Bit 1 - _OSC failure. Platform Firmware was unable to process the request or query
> +    // Bit 2 - Unrecognized UUID
> +    // Bit 3 - Unrecognized Revision
> +    // Bit 4 - Capabilities Masked
> +    // All others reserved
> +
> +    CreateDWordField (Arg3, 0, CDW1)
> +    If (LEqual (Arg0, ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
> +      CreateDWordField (Arg3, 4, CDW2)
> +      CreateDWordField (Arg3, 8, CDW3)
> +
> +      // Save Capabilities DWord 2 & 3
> +      // The second DWORD in the _OSC Capabilities Buffer is the Support Field
> +      // The third DWORD in the _OSC Capabilities Buffer is the Control Field
> +      // PCI Firmware Specification - 4.5.1.
> +      // Supported feature should be set in the control field
> +      //
> +      // Support field
> +      // Bit 0 - Extended PCI Config operation regions supported
> +      // Bit 1 - Active State Power Management supported
> +      // Bit 2 - Clock Power Management Capability supported
> +      // Bit 3 - PCI Segment Groups supported
> +      // Bit 4 - MSI supported
> +      // Bit 5 - Optimized Buffer Flush and Fill supported
> +      // Bit 6 - ASPM Optionality supported
> +      //
> +      // Control field
> +      // Bit 0 - PCI Express Native Hot Plug control
> +      // Bit 1 - SHPC Native Hot Plug control
> +      // Bit 2 - PCI Express Native Power Management Events control
> +      // Bit 3 - PCI Express Advanced Error Reporting control
> +      // Bit 4 - PCI Express Capability Structure control
> +      // Bit 5 - Latency Tolerance Reporting control
> +
> +      Store (CDW2, SUPP)
> +      Store (CDW3, CTRL)
> +
> +      // Only allow native hot plug control if OS supports:
> +      //  ASPM
> +      //  Clock PM
> +      //  MSI/MSI-X
> +      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
> +        And (CTRL, 0x1E, CTRL)
> +      }
> +
> +      // Spec does not mention if standard hot plug is supported
> +      // so unmask the bit
> +      And (CTRL, 0x1D, CTRL)
> +
> +      // Check for unknown revision.
> +      If (LNotEqual (Arg1, One)) {
> +        Or (CDW1, 0x08, CDW1)
> +      }
> +
> +      // Check if capabilities bits were masked.
> +      If (LNotEqual (CDW3, CTRL)) {
> +        Or (CDW1, 0x10, CDW1)
> +      }
> +
> +      // Update DWORD3 in the buffer.
> +      Store (CTRL, CDW3)
> +      Return (Arg3)
> +    } else {
> +      // Unrecognized UUID
> +      Or (CDW1, 4, CDW1)
> +      Return (Arg3)
> +    }
> +  }
> +
> +  // Declare a _DSM method for various functions called by the OS.
> +  // See the APCI spec, Section 9.14.1,
> +  // and the PCI FW spec, Section 4.6.
> +  // See also:
> +  // http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/PCI-rsc.doc
> +  Method (_DSM, 0x4, Serialized) {
> +    // Match against the _DSM PCI UUID. PCI firmware spec - 4.6.1
> +    //     Arg0 - UUID
> +    //     Arg1 - Revision ID
> +    //     Arg2 - Function Index
> +    //     Arg3 - Empty Package
> +    //
> +    // Revision 1 & 2
> +    //     Function 1 - PCI Express Slot Information
> +    //     Function 2 - PCI Express Slot Number
> +    //     Function 3 - Vendor-specific Token ID
> +    //     Function 4 - PCI Bus Capabilities
> +    //     Function 5 - Ignore PCI Boot Configuration
> +    // Revision 2 only
> +    //     Function 6 - LTR Maximum Latency
> +    //     Function 7 - Express device under OS
> +    If (LEqual (Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
> +
> +      switch (ToInteger (Arg2)) {
> +      // Function 0: Return supported functions as a bit-field
> +      // with one bit for each supported function.
> +      // Bit 0 must always be set, as that represents
> +      // function 0 (which is what is being called here).
> +      // Support for different functions may depend on
> +      // the revision ID of the interface, passed as Arg1.
> +
> +      // Function 0: Get supported functions
> +      case (0) {
> +          // Functions 0,1,5 are supported.
> +          if (LEqual (Arg1, 1)) {
> +            return (Buffer() { 0x23 })
> +          }
> +
> +          // Functions 0,1,5,7 are supported.
> +          if (LEqual (Arg1, 2)) {
> +            return (Buffer() { 0xA3 })
> +          }
> +
> +          // Functions 0,1,5,7 are supported for
> +          // future revision. Expect backward compatibility
> +          return (Buffer() { 0xA3 })
> +        }
> +
> +      // Function 1: PCI Express Slot Information
> +      // PCI firmware spec - 4.6.1
> +      case (1) {
> +          // Package item 1:
> +          //    0: Failure
> +          //    1: Success
> +          // Package item 2:
> +          //  Integer 1:Bit Position
> +          //        0 Supports x1
> +          //        1 Supports x2
> +          //        2 Supports x4
> +          //        3 Supports x8
> +          //        4 Supports x12
> +          //        5 Supports x16
> +          //  Integer 2:
> +          //        0h Unknown
> +          //        1h PCI Express Card Slot
> +          //        2h PCI Express Server I/O Module Slot
> +          //        3h PCI Express ExpressCard* Slot
> +          //        4h PCI Express Mini Card Slot
> +          //        5h PCI Express Wireless Form Factor Slot
> +          //        Others Reserved
> +          //  Integer 3:
> +          //        0 SMBus signal
> +          //        1 WAKE# signal
> +          return ( Package (2) {
> +            0x01, // Status success (1)
> +            Package() {
> +              0, // Supports x1
> +              4, // PCI Express Mini Card Slot
> +              1  // Supported signals (no SMBus, WAKE#)
> +            }
> +          })
> +        }
> +
> +      // Function 5: Ignore PCI Boot Configurations
> +      // PCI firmware spec - 4.6.5
> +      case (5) {
> +          // Always allow OS to rebalance
> +          return (0x01)
> +        }
> +
> +      // Function 7: Naming a PCI or PCI Express Device Under
> +      //             Operating Systems
> +      // PCI firmware spec - 4.6.7
> +      case (7) {
> +          // Verify revision 2
> +          if (LEqual (Arg1, 2)) {
> +            // PCI Express Slot Parsing
> +            Return ( Package (2) {
> +              1,            // Instance of the enumeration
> +              "PCIe Slot 1" // String name which matches the label on the chassis
> +            })
> +          }
> +        }
> +      }
> +    }
> +    return (Buffer() { 0 })
> +  }
> +
> +  // Root Port 0 Device within the Root Complex.
> +  Device (RP0) {
> +    Name (_ADR, 0)  // Device 0, Function 0
> +    Name (_S0W, 4)  // Supports wake
> +  }
> +
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> new file mode 100644
> index 000000000000..0bdc78080d26
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> @@ -0,0 +1,106 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +OperationRegion (GLBL, SystemMemory, 0x10817000, 0x10)
> +Field (GLBL, AnyAcc, Nolock, Preserve)
> +{
> +  Offset (0),       // Miscellaneous Dynamic Registers:
> +  SIGN, 32,         // Global Page Signature 'GLBL'
> +  REVN, 8,          // Revision
> +      , 8,          // Reserved
> +      , 8,          // Reserved
> +      , 8,          // Reserved
> +  M0ID, 8,          // MAC 0 ID
> +  MC0V, 8,          // MAC 0 Valid
> +  MC0L, 32,         // MAC Address 0 Low
> +  MC0H, 16,         // MAC Address 0 High
> +}
> +
> +Device (CPU0)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +Device (CPU1)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +Device (CPU2)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +Device (CPU3)
> +{
> +  Name (_HID, "ACPI0007")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +// Timers HAL extension
> +Device (EPIT)
> +{
> +  Name (_HID, "NXP0101")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +}
> +
> +// Platform Extension Plugin
> +Device (PEP0)
> +{
> +  Name (_HID, "NXP0102")
> +  Name (_UID, 0x0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // CCM request 1
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 119 }
> +
> +      // CCM request 2
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 120 }
> +
> +      // GPC request 1
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 121 }
> +
> +      // UART1
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> new file mode 100644
> index 000000000000..22bab0cff575
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> @@ -0,0 +1,85 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (PWM1)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (PWM2)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02084000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 116 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (PWM3)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02088000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 117 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (PWM4)
> +{
> +  Name (_HID, "NXP010E")
> +  Name (_UID, 0x4)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0208C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 118 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> new file mode 100644
> index 000000000000..fad33d2e9d6c
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> @@ -0,0 +1,133 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// uSDHC1
> +Device (SDH1)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  // Child node to represent the only SD/MMC slot on this SD/MMC bus
> +  // In theory an SDHC can be connected to multiple SD/MMC slots at
> +  // the same time, but only 1 device will be selected and active at
> +  // a time
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC2
> +Device (SDH2)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC3
> +Device (SDH3)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> +
> +// uSDHC4
> +Device (SDH4)
> +{
> +  Name (_HID, "NXP0108")
> +  Name (_UID, 0x4)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0219C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 57 }
> +    })
> +    Return (RBUF)
> +  }
> +
> +  Device (SD0) {
> +    Method (_ADR) {
> +      Return (0)
> +    }
> +
> +    Method (_RMV) {
> +      Return (0)
> +    }
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> new file mode 100644
> index 000000000000..f68a7f306ecc
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> @@ -0,0 +1,103 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (SPI1)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x1)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02008000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 63 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI2)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x2)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI3)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x3)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02010000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 65 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI4)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x4)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02014000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 66 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> +
> +Device (SPI5)
> +{
> +  Name (_HID, "NXP0105")
> +  Name (_UID, 0x5)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      MEMORY32FIXED (ReadWrite, 0x02018000, 0x4000, )
> +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 67 }
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> new file mode 100644
> index 000000000000..83975792bcaf
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> @@ -0,0 +1,33 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +Device (TREE)
> +{
> +  Name (_HID, "NXP010F")
> +  Name (_CID, "TrEECSMP")
> +  Name (_UID, 0)
> +
> +  Method (_STA) {
> +    Return (0xf)
> +  }
> +
> +  Method (_CRS, 0x0, NotSerialized) {
> +    Name (RBUF, ResourceTemplate () {
> +      // OP-TEE Shared memory area.
> +      // Needs to match: PcdTrustZoneSharedMemoryBase, PcdTrustZoneSharedMemorySize
> +      MEMORY32FIXED (ReadWrite, 0x12800000, 0x00200000, )
> +    })
> +    Return (RBUF)
> +  }
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> new file mode 100644
> index 000000000000..58181ee9eda7
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> @@ -0,0 +1,60 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +// Advertise support for PSCI
> +#define FADT_ARM_BOOT_ARCH       0x01
> +
> +char FACP[268] = {
> +  0x46, 0x41, 0x43, 0x50,                         // Signature : 'FACP'
> +  0x0C, 0x01, 0x00, 0x00,                         // Length
> +  0x05,                                           // Revision
> +  0x00,                                           // Checksum
> +  0x4E, 0x58, 0x50, 0x4D, 0x58, 0x36,             // OEMID : 'NXPMX6'
> +  0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, // OEMTABLE : 'EDK2'
> +  0x01, 0x00, 0x00, 0x00,                         // OEM Revision
> +  0x4D, 0x53, 0x46, 0x54,                         // CreatorID : 'MSFT'
> +  0x01, 0x00, 0x00, 0x00,                         // Creator revision
> +  0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x04, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C,
> +  0x00, 0x00, 0x21, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, FADT_ARM_BOOT_ARCH,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (void *) &FACP;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> new file mode 100644
> index 000000000000..1c382306c780
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> @@ -0,0 +1,120 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Library/AcpiLib.h>
> +
> +#include <Platform.h>
> +#include <iMX6.h>
> +
> +#define GICC_BASE                 FixedPcdGet64 (PcdGicInterruptInterfaceBase)
> +#define GICD_BASE                 FixedPcdGet64 (PcdGicDistributorBase)
> +
> +// Virtualization related fields. Not supported on IMX6
> +#define GICH_BASE                 0
> +#define GICV_BASE                 0
> +#define VGIC_MAINT_INT            0
> +#define PMU_INTERRUPT             0
> +
> +#pragma pack(push, 1)
> +typedef struct {
> +  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
> +  EFI_ACPI_6_0_GIC_STRUCTURE GicC[FixedPcdGet32 (PcdCoreCount)];
> +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE GicD;
> +} ACPI_6_0_MADT_STRUCTURE;
> +#pragma pack(pop)
> +
> +ACPI_6_0_MADT_STRUCTURE Madt = {
> +  {
> +    {
> +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, // Signature
> +      sizeof (ACPI_6_0_MADT_STRUCTURE),                       // Length
> +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,  // Revision
> +      0,                                                      // Checksum
> +      EFI_ACPI_OEM_ID,                                        // OemId[6]
> +      EFI_ACPI_OEM_TABLE_ID,                                  // OemTableId
> +      EFI_ACPI_OEM_REVISION,                                  // OemRevision
> +      EFI_ACPI_CREATOR_ID,                                    // CreatorId
> +      EFI_ACPI_CREATOR_REVISION                               // CreatorRevision
> +    },
> +    0,      // LocalApicAddress
> +    0       // Flags
> +  },
> +  {
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (0,                        // GicId
> +                                      0x000,                     // AcpiCpuUid
> +                                      0x000,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +#if FixedPcdGet32(PcdCoreCount) > 1
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (1,                        // GicId
> +                                      0x001,                     // AcpiCpuUid
> +                                      0x001,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +#if FixedPcdGet32(PcdCoreCount) > 2
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (2,                        // GicId
> +                                      0x002,                     // AcpiCpuUid
> +                                      0x002,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (3,                        // GicId
> +                                      0x003,                     // AcpiCpuUid
> +                                      0x003,                     // Mpidr
> +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> +                                      PMU_INTERRUPT,             // PmuIrq
> +                                      GICC_BASE,                 // GicBase
> +                                      GICV_BASE,                 // GicVBase
> +                                      GICH_BASE,                 // GicHBase
> +                                      VGIC_MAINT_INT,            // GsivId
> +                                      0,                         // GicRBase
> +                                      0                          // Efficiency
> +                                     ),
> +#endif
> +#endif
> +  },
> +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (0x0,                   // GicDistHwId
> +                                     GICD_BASE,             // GicDistBase
> +                                     IC_DIST_VECTOR_BASE,   // GicDistVector
> +                                     EFI_ACPI_6_0_GIC_V1    // GicVersion
> +                                    )
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&Madt;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> new file mode 100644
> index 000000000000..3e9d163cb52e
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> @@ -0,0 +1,92 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <Platform.h>
> +
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#include "iMX6.h"
> +#include "../Drivers/PciExpress/iMX6PciExpress.h"
> +
> +#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
> +
> +// Size in bytes a single bus consumes in ECAM space
> +// Configuration size = 4K
> +// Max device = 32
> +// Max function = 8
> +// Max bus size = 4K * 32 * 8
> +#define ECAM_BUS_ADDR_SIZE  (1 << 20)
> +
> +// Provide 2 differenct base PCI space address. The first list would represent
> +// the host config space and the second list would be the device config space.
> +// Windows is expected to be able to parse the information.
> +#define NUM_PCI 2
> +
> +// MCFG structure
> +// PCI Firmware specification Table 4-2
> +#pragma pack(push, 1)
> +
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER Header;
> +  UINT64                      Reserved;
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE AllocationStructure[NUM_PCI];
> +} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;
> +
> +#pragma pack(pop)
> +
> +//
> +// Multiple APIC Description Table
> +//
> +EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg = {
> +  {
> +    EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE),
> +    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
> +    0x00,                           // Checksum will be updated at runtime
> +    EFI_ACPI_OEM_ID,                // OEMID
> +    EFI_ACPI_OEM_TABLE_ID,          // OEM Table ID
> +    EFI_ACPI_OEM_MCFG_REVISION,     // OEM Revision
> +    EFI_ACPI_CREATOR_ID,            // Creator ID
> +    EFI_ACPI_CREATOR_REVISION,      // Creator revision
> +  },
> +  0x00,                             // Reserved
> +
> +  {
> +    // PCIe Host
> +    {
> +      PCIE_HOST_CONFIG_BASE_REG,        // PCIE Host Config Base Address
> +      0x00,                             // PciSegmentGroupNumber (_SEG)
> +      0x00,                             // StartBusNumber
> +      0x00,                             // EndBusNumber
> +      0x00000000                        // Reserved
> +    },
> +
> +    // PCIe Device
> +    {
> +      PCIE_DEVICE_CONFIG_BASE_REG - ECAM_BUS_ADDR_SIZE,  // BaseAddress

OK, so the 'root port' and device ECAM spaces are disjoint, which is
why you need two different entries here. Subtracting
ECAM_BUS_ADDR_SIZE is needed since the bus range starts at 0x1

Could you clarify this in a comment please?


> +      0x00,                              // PciSegmentGroupNumber (_SEG)
> +      0x01,                              // StartBusNumber
> +      0x01,                              // EndBusNumber
> +      0x00000000                         // Reserved
> +    }
> +  }
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&Mcfg;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> new file mode 100644
> index 000000000000..603422a737c4
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> @@ -0,0 +1,95 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include "Platform.h"
> +#include "iMX6.h"
> +
> +// Ensure proper structure formats
> +#pragma pack (1)
> +
> +typedef struct {
> +  EFI_ACPI_DESCRIPTION_HEADER Header;
> +  UINT8 Interface_Type;
> +  UINT8 Reserved1[3];
> +  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> +  UINT8 Interrupt_Type;
> +  UINT8 PCAT_compatible_IRQ;
> +  UINT32 Interrupt;
> +  UINT8 Baud_Rate;
> +  UINT8 Parity;
> +  UINT8 Stop_Bits;
> +  UINT8 Flow_Control;
> +  UINT8 Terminal_Type;
> +  UINT8 Reserved2;
> +  UINT16 PCI_Device_ID;
> +  UINT16 PCI_Vender_ID;
> +  UINT8 PCI_Bus;
> +  UINT8 PCI_Device;
> +  UINT8 PCI_Function;
> +  UINT32 PCI_Flags;
> +  UINT8 PCI_Segment;
> +  UINT32 Reserved3;
> +} EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE;
> +
> +#pragma pack ()
> +
> +EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE SPCR = {
> +  {
> +    EFI_ACPI_5_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE),
> +    0x02,
> +    0x00,                           // Checksum will be updated at runtime
> +    EFI_ACPI_OEM_ID,
> +    EFI_ACPI_OEM_TABLE_ID,
> +    EFI_ACPI_OEM_REVISION,
> +    EFI_ACPI_CREATOR_ID,
> +    EFI_ACPI_CREATOR_REVISION,
> +  },
> +  DBG_PORT_SUBTYPE_IMX6,   // Serial Interface type = Serial Port Subtypes of the DBG2
> +  {0x00, 0x00, 0x00},      // Reserved
> +
> +  // ACPI Generic Address Structure. Set to all zeroes to disable console redirection
> +  {
> +    EFI_ACPI_5_0_SYSTEM_MEMORY,         // AddressSpaceId: SystemMemory
> +    0x20,                               // RegisterBitWidth
> +    0,                                  // RegisterBitOffset
> +    EFI_ACPI_5_0_DWORD,                 // AccessSize
> +    (UINT64)CSP_BASE_REG_PA_UART3       // Address UART3
> +  },
> +  0x08,        // Interrupt Type = Bit[3] ARMH GIC interrupt. 0 means not supported.
> +  0x00,        // IRQ. Not used since Bit[0] of the Interrupt Type field is not set
> +  0x3c,        // Global System Interrupt used by the UART (UART3 interrupt 60)
> +  0x07,        // Baud Rate
> +  0x00,        // No Parity
> +  0x01,        // One Stop Bit
> +  0x00,        // Flow Control: None
> +  0x03,        // Terminal Type: ANSI
> +  0X00,        // Reserved
> +  0xffff,      // 0xFFFF - not a PCI device
> +  0xffff,      // 0xFFFF - not a PCI device
> +  0x00,        // Bus Number. 0 - not a PCI device
> +  0x00,        // Device Number. 0 - not a PCI device
> +  0x00,        // Function. 0 - not a PCI device
> +  0x00000000,  // PCI Flags
> +  0x00,        // PCI Segment
> +  0x00000000,  //Reserved
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&SPCR;
> +}
> diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> new file mode 100644
> index 000000000000..a5abb2bf15d1
> --- /dev/null
> +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> @@ -0,0 +1,53 @@
> +/** @file
> +*
> +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> +*
> +*  This program and the accompanying materials
> +*  are licensed and made available under the terms and conditions of the BSD License
> +*  which accompanies this distribution.  The full text of the license may be found at
> +*  http://opensource.org/licenses/bsd-license.php
> +*
> +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +*
> +**/
> +
> +#include <IndustryStandard/Tpm2Acpi.h>
> +
> +#include <Library/PcdLib.h>
> +
> +#include <Platform.h>
> +#include "iMX6.h"
> +
> +// Definition is missing from MdePkg/Include/IndustryStandard/Tpm2Acpi.h
> +#ifdef EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE
> +#error "EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE is defined elsewhere."
> +#else
> +#define EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE 9
> +#endif
> +
> +EFI_TPM2_ACPI_TABLE Tpm2Table = {
> +  {
> +    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
> +    sizeof (EFI_TPM2_ACPI_TABLE),
> +    EFI_TPM2_ACPI_TABLE_REVISION,
> +    0,                          // Checksum will be updated at runtime
> +    EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
> +    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
> +    EFI_ACPI_OEM_REVISION,      // OEM revision number
> +    EFI_ACPI_CREATOR_ID,        // Creator vendor ID
> +    EFI_ACPI_CREATOR_REVISION,  // Creator revision number
> +  },
> +  0,                            // Flags
> +  FixedPcdGet64 (PcdTpm2AcpiBufferBase),  // Control Area
> +  // StartMethod
> +  EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_TREE,
> +};
> +
> +VOID*
> +ReferenceAcpiTable (
> +  VOID
> +  )
> +{
> +  return (VOID *)&Tpm2Table;
> +}


> --
> 2.16.2.gvfs.1.33.gf5370f1
>


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core
  2018-12-15 13:32 ` [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Leif Lindholm
@ 2018-12-19 18:28   ` Chris Co
  0 siblings, 0 replies; 75+ messages in thread
From: Chris Co @ 2018-12-19 18:28 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Ard Biesheuvel, Michael D Kinney

Hi Leif,

No problem - it's been a crazy year all around so I fully understand. Thank you for making time to review and provide feedback on this patch set.

I am already out of office for the rest of the year so I will make the changes recommended by you and Ard when I get back. And I also have some changes marked to simplify portions of the code and make it more readable/sane.

Have a great holiday season!

Chris
________________________________
From: Leif Lindholm <leif.lindholm@linaro.org>
Sent: Saturday, December 15, 2018 5:32 AM
To: Chris Co
Cc: edk2-devel@lists.01.org; Ard Biesheuvel; Michael D Kinney
Subject: Re: [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core

Hi Chris,

Sorry for dragging this out, but it's been a crazy year.
I think I've now provided feedback for all but the SdMmc bits.

For the next revision, please break out SdMmc support (including and put it last
in the series). I still don't like the idea of adding a third driver
stack to the project, and am likely to have ideas of major
restructuring, but if we can isolate that from the rest, reviewing the
remainder should be reasonably quick next time around.

My last day "in the office" before Christmas is 21 December, and then
I'll be out until 7 January. So basically, if you can get a new set
out early nexy week, I may have a chance to look at it, and if not -
take your time :)

Regards,

Leif

On Fri, Sep 21, 2018 at 08:25:52AM +0000, Chris Co wrote:
> REF: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fchristopherco%2Fedk2-platforms%2Ftree%2Fwiniot_hmb_v1&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7Cfe389e235d9f4b5a3db608d66291b91f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636804775359296793&amp;sdata=ArbTsmK70lP0z2I5DtAMUtjMaoGvxmjo421G0pFHw20%3D&amp;reserved=0
>
> v0:
> * https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fpipermail%2Fedk2-devel%2F2018-July%2F027213.html&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7Cfe389e235d9f4b5a3db608d66291b91f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636804775359296793&amp;sdata=YPaztVWBhe3mimyel5pBFmUQn16PDobNrZDG2Pw9Z4M%3D&amp;reserved=0
> * https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fpipermail%2Fedk2-devel%2F2018-July%2F027266.html&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7Cfe389e235d9f4b5a3db608d66291b91f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636804775359296793&amp;sdata=aNuEw0cnaQTgI9vG1aoaeDKCKeZX0nPZPBxrk5IMZLM%3D&amp;reserved=0
> * https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fpipermail%2Fedk2-devel%2F2018-July%2F027333.html&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7Cfe389e235d9f4b5a3db608d66291b91f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636804775359296793&amp;sdata=KBKCyLHP2AmOifipqCPt2Q6cxByt%2Fw18sb1v63Eh5%2FE%3D&amp;reserved=0
> * https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fpipermail%2Fedk2-devel%2F2018-July%2F027409.html&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7Cfe389e235d9f4b5a3db608d66291b91f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636804775359296793&amp;sdata=chPGxhVlyJmKSOLTn9UNWRdfeya2IdqCIuno2DQlRpk%3D&amp;reserved=0
>
> The patch set supports the bring up of Windows 10 IoT Core on
> Solidrun's Hummingboard Edge board running NXP's i.MX 6Quad SoC.
>
> This patch set is a preliminary submission, with the goal to get further review
> feedback from maintainers since the v0 version had too many initial issues to
> conduct a full review.
>
> Changes in this patch set from v0:
> * Merged the 4 previous patch sets into one.
> * All code should now follow the edk2 coding style.
> * SMBIOS driver refactored to use PCDs. Fixed UUID generation to use MAC address.
> * Updated ACPI HIDs to proper NXP IDs where applicable.
> * Removed unnecessary (and spec-violating) _DSD methods from our ACPI tables.
> * General code cleanup and refactoring.
> * Add Silicon package support for i.MX 6Solo/DualLite, 6SoloX, 6DualPlus/QuadPlus
> families in iMX6Pkg.
>
> Known issues remaining from previous review:
> * Silicon/NXP/iMXPlatformPkg: SdhcDxe fixed initialization needs to be moved to
> a PlatformDxe init and use NonDiscoverableDeviceRegistrationLib.
> * Platform/Microsoft: Left in SdMmcDxe code. Alternatives are still under
> evaluation.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Christopher Co <christopher.co@microsoft.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
>
> Christopher Co (27):
>   Platform/Microsoft: Add OpteeClientPkg dec
>   Platform/Microsoft: Add SdMmc Dxe Driver
>   Platform/Microsoft: Add MsPkg
>   Silicon/NXP: Add iMXPlatformPkg dec
>   Silicon/NXP: Add UART library support for i.MX platforms
>   Silicon/NXP: Add I2C library support for i.MX platforms
>   Silicon/NXP: Add i.MX display library support
>   Silicon/NXP: Add Virtual RTC support for i.MX platform
>   Silicon/NXP: Add headers for SoC-specific i.MX packages to use
>   Silicon/NXP: Add iMX6Pkg dec
>   Silicon/NXP: Add i.MX6 SoC header files
>   Silicon/NXP: Add i.MX6 I/O MUX library
>   Silicon/NXP: Add support for iMX SDHC
>   Silicon/NXP: Add i.MX6 GPT and EPIT timer headers
>   Silicon/NXP: Add i.MX6 GPT Timer library
>   Silicon/NXP: Add i.MX6 Timer DXE driver
>   Silicon/NXP: Add i.MX6 USB Phy Library
>   Silicon/NXP: Add i.MX6 Clock Library
>   Silicon/NXP: Add i.MX6 ACPI tables
>   Silicon/NXP: Add i.MX6 Board init library
>   Silicon/NXP: Add i.MX6 PCIe DXE driver
>   Silicon/NXP: Add i.MX6 GOP driver
>   Silicon/NXP: Add i.MX6 Smbios Driver
>   Silicon/NXP: Add i.MX6 common dsc and fdf files
>   Platform/Solidrun: Add Hummingboard Peripheral Initialization
>   Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables
>   Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files
>
>  Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c                                          |  548 +++++
>  Platform/Microsoft/Drivers/SdMmcDxe/Debug.c                                            |  363 +++
>  Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c                                         | 1775 ++++++++++++++
>  Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h                                         |  231 ++
>  Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c                                           |  609 +++++
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c                                            |  886 +++++++
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h                                            |  529 +++++
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf                                       |   49 +
>  Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h                                          |  505 ++++
>  Platform/Microsoft/Include/Protocol/RpmbIo.h                                           |  268 +++
>  Platform/Microsoft/Include/Protocol/Sdhc.h                                             |  197 ++
>  Platform/Microsoft/MsPkg.dec                                                           |   39 +
>  Platform/Microsoft/MsPkg.dsc                                                           |   31 +
>  Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec                                   |   49 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf                 |   55 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl                       |   38 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl                 |   71 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl            |   33 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl                   |   54 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl                   |   32 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl                   |  234 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl                  |  144 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl                   |   43 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl                  |  198 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl                   |  343 +++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc            |  141 ++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf            |  117 +
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c      |  634 +++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h      |  705 ++++++
>  Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf     |   91 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc                                               |  408 ++++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc                                               |  142 ++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h                                           |  106 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl                                           |  106 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl                                            |   74 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl                                           |   55 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl                                            |   67 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl                                           |  298 +++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl                                       |  106 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl                                            |   85 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl                                           |  133 ++
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl                                            |  103 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl                                           |   33 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc                                               |   60 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc                                               |  120 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc                                               |   92 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc                                               |   95 +
>  Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc                                               |   53 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c                                             |  423 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h                                             |  277 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c                                               |   69 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h                                               |   28 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c                                           |  455 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h                                           |  175 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c                                 |  399 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h                                 |  331 +++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c                                  |  458 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h                                  |  195 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c                                              |   96 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h                                              |   33 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c                                            |  475 ++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h                                            |   20 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf                                          |   70 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c                                              |  761 ++++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h                                              |  529 +++++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c                                             |   88 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h                                             |   32 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h                                               |  236 ++
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c                                              |   93 +
>  Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h                                              |   67 +
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c                                | 1139 +++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h                                |  145 ++
>  Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf                              |   66 +
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c                      | 1774 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h                      |   44 +
>  Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf                    |   84 +
>  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c                                           |  278 +++
>  Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf                                      |   55 +
>  Silicon/NXP/iMX6Pkg/Include/common_epit.h                                              |  118 +
>  Silicon/NXP/iMX6Pkg/Include/common_gpt.h                                               |  271 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6.h                                                     |   39 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h                                             |   55 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h                                               |  105 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h                                            |  181 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h                                           |  176 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h                                            |  190 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h                                                |  202 ++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h                                            | 2466 ++++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h                                            | 1875 +++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h                                             | 2270 ++++++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h                                                |   24 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h                                               |   20 +
>  Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h                                                  |  332 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h                                                 |  335 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h                                                 |  301 +++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h                                                  | 1730 ++++++++++++++
>  Silicon/NXP/iMX6Pkg/Include/iMX6_common.h                                              | 1350 +++++++++++
>  Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c                                        |  246 ++
>  Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf                                      |   45 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S                             |   89 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c                                |  110 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c                                  |   88 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c                           |  107 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c                                 | 1876 +++++++++++++++
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf                            |   46 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h                         |  221 ++
>  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c                                   |  151 ++
>  Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf                              |   41 +
>  Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c                                 |  328 +++
>  Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf                            |   43 +
>  Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc                                                  |  897 +++++++
>  Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc                                                  |  287 +++
>  Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc                                                  |  148 ++
>  Silicon/NXP/iMX6Pkg/iMX6Pkg.dec                                                        |  143 ++
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c                                   | 1246 ++++++++++
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h                                   |   81 +
>  Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf                                 |   70 +
>  Silicon/NXP/iMXPlatformPkg/Include/Platform.h                                          |   67 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h                                        |  114 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h                                           |   92 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h                                         |  162 ++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h                                          |   24 +
>  Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h                                           |  207 ++
>  Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h                                          |  277 +++
>  Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c               |  243 ++
>  Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf             |   41 +
>  Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c   |  227 ++
>  Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf |   37 +
>  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c                       |  152 ++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf                     |   31 +
>  Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c                               |  487 ++++
>  Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf                             |   35 +
>  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec                                          |  118 +
>  133 files changed, 40660 insertions(+)
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/BlockIo.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Debug.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/Protocol.h
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/RpmbIo.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.c
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmc.h
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcDxe.inf
>  create mode 100644 Platform/Microsoft/Drivers/SdMmcDxe/SdMmcHw.h
>  create mode 100644 Platform/Microsoft/Include/Protocol/RpmbIo.h
>  create mode 100644 Platform/Microsoft/Include/Protocol/Sdhc.h
>  create mode 100644 Platform/Microsoft/MsPkg.dec
>  create mode 100644 Platform/Microsoft/MsPkg.dsc
>  create mode 100644 Platform/Microsoft/OpteeClientPkg/OpteeClientPkg.dec
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/AcpiTables.inf
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/DSDT.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Audio.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-AudioCodec.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-I2c.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Pwm.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Rhp.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Sdhc.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Spi.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Uart.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/AcpiTables/Dsdt-Usb.asl
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.dsc
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/HummingBoardEdge_iMX6Q_2GB.fdf
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.c
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardInit.h
>  create mode 100644 Platform/SolidRun/HummingBoardEdge_iMX6Q_2GB/Library/iMX6BoardLib/iMX6BoardLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Csrt.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dbg2.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PciExpress/iMX6PciExpress.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/Timer.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Drivers/TimerDxe/TimerDxe.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/common_epit.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/common_gpt.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6BoardLib.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_DQ.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SDL.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6ClkPwr_SX.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_DQP.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SDL.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6IoMux_SX.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6Timer.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6UsbPhy.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_DQ.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_DQP.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_SDL.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_SX.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Include/iMX6_common.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/TimerLib/TimerLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardHelper.S
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6BoardMem.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6Common.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6BoardLib/iMX6QBoardCoreDef.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhy.c
>  create mode 100644 Silicon/NXP/iMX6Pkg/Library/iMX6UsbPhyLib/iMX6UsbPhyLib.inf
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6CommonDsc.inc
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6CommonFdf.inc
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6ConfigDsc.inc
>  create mode 100644 Silicon/NXP/iMX6Pkg/iMX6Pkg.dec
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/Platform.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXDisplay.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXI2cLib.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXIoMux.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXDisplayLib/iMXDisplayLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.c
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/Library/iMXI2cLib/iMXI2cLib.inf
>  create mode 100644 Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
>
> --
> 2.16.2.gvfs.1.33.gf5370f1
>


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
  2018-12-17 11:14   ` Ard Biesheuvel
@ 2019-01-08 21:43     ` Chris Co
  2019-01-29 14:09       ` Ard Biesheuvel
  0 siblings, 1 reply; 75+ messages in thread
From: Chris Co @ 2019-01-08 21:43 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel@lists.01.org, Leif Lindholm, Michael D Kinney

Hi Ard,

> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Sent: Monday, December 17, 2018 3:14 AM
> To: Chris Co <Christopher.Co@microsoft.com>
> Cc: edk2-devel@lists.01.org; Leif Lindholm <leif.lindholm@linaro.org>; Michael
> D Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
> 
> On Fri, 21 Sep 2018 at 10:26, Chris Co <Christopher.Co@microsoft.com>
> wrote:
> >
> > +// PL310 L2 Cache Controller Resource Group
> > +#define CSRT_PL310_MINIMUM_VERSION   1
> > +#define CSRT_PL310_VERSION_2         2
> > +#define CSRT_PL310_RAW_PROTOCOL      0
> > +#define CSRT_PL310_SMC_PROTOCOL      1
> > +
> > +// We use PSCI_CPU_ON to turn on the L2 cache, with special value
> > +// 0x00100000 for the Core ID. PSCI sees this core ID and knows
> > +// this is an L2 cache operation, then looks at R2 for the
> > +// operation to perform.
> > +#define PSCI_FID_CPU_ON                        0x84000003
> > +#define L2CACHE_SMC_R1                         0x00100000
> > +#define L2CACHE_OP_ENABLE                      1
> > +#define L2CACHE_OP_DISABLE                     2
> > +#define L2CACHE_OP_ENABLE_WRITEBACK            3
> > +#define L2CACHE_OP_DISABLE_WRITEBACK           4
> > +#define L2CACHE_OP_ENABLE_WFLZ                 5
> > +
> 
> Who defined this protocol? Where is the opposite side implemented?
> 
> Overloading architected PSCI calls to manage platform specific pieces
> is really a no-go.
> 

Since my initial patch set submission, we have updated this code to use the standardized protocol instead of overloading PSCI_CPU_ON. It will be in the V2 patch set.

// PL310 L2 Cache Controller Resource Group
#define CSRT_PL310_MINIMUM_VERSION   1
#define CSRT_PL310_VERSION_2         2
#define CSRT_PL310_RAW_PROTOCOL      0
#define CSRT_PL310_SMC_PROTOCOL      1

#define SMC_CALL_VAL(owner, funcid) \
    (0x80000000 | (((owner) & 0x3F) << 24) | ((funcid) & 0xffff))

#define SMC_OWNER_SIP                   2
#define IMX_SMC_PL310_ENABLE            SMC_CALL_VAL(SMC_OWNER_SIP, 1)
#define IMX_SMC_PL310_DISABLE           SMC_CALL_VAL(SMC_OWNER_SIP, 2)
#define IMX_SMC_PL310_ENABLE_WRITEBACK  SMC_CALL_VAL(SMC_OWNER_SIP, 3)
#define IMX_SMC_PL310_DISABLE_WRITEBACK SMC_CALL_VAL(SMC_OWNER_SIP, 4)
#define IMX_SMC_PL310_ENABLE_WFLZ       SMC_CALL_VAL(SMC_OWNER_SIP, 5)

> > +// Debug Port 2 table
> > +EFI_ACPI_5_0_DEBUG_PORT_2_TABLE Dbg2 = {
> 
> STATIC
> 
> > +  {
> > +    // Header
> > +    {
> > +      EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_SIGNATURE,     // Signature
> "DBG2"
> > +      sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE),      // Length
> > +      EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION,          // Revision
> > +      EFI_ACPI_5_0_UNDEFINED,                        // Checksum - updated at
> runtime
> > +      EFI_ACPI_OEM_ID,                               // OEM ID[6]
> > +      EFI_ACPI_OEM_TABLE_ID,                         // OEM Table ID
> > +      EFI_ACPI_OEM_REVISION,                         // OEM Revision
> > +      EFI_ACPI_CREATOR_ID,                           // Creator ID
> > +      EFI_ACPI_CREATOR_REVISION                      // Creator Revision
> > +    },
> > +    sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER), //
> OffsetDbgDeviceinfo
> > +    1,                                               // NumberDbgDeviceInfo
> > +  },
> > +  {
> > +    // Uart
> > +    {
> > +      // DeviceInfo
> > +      EFI_ACPI_RESERVED_BYTE,                                 // Revision
> > +      sizeof (DEBUG_DEVICE_INFO_UART),                        // Length
> > +      1,                                                      // NumberofGenericAddressRegisters
> > +      UART_NAME_SPACE_STRING_LENGTH,                          //
> NameSpaceStringLength
> > +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, NameSpaceString),    //
> NameSpaceStringOffset
> > +      0,                                                      // OemDataLength
> > +      EFI_ACPI_RESERVED_WORD,                                 // OemDataOffset
> > +      DBG2_TYPE_SERIAL,                                       // PortType
> > +      DBG_PORT_SUBTYPE_IMX6,                                  // PortSubtype 000Ch
> 
> Is this subtype defined in a published version of the SPCR/DBG2 specs?
> 

Just checked and the IMX6 subtype is not present in the latest DBG2 spec. I'll work on getting it added. Does the subtype need to be in the published DBG2 spec before the patch can be accepted upstream?

Note: The definition is present in our WDK headers but I'm guessing that is not sufficient...

//
// ACPI debug device port types.  The bottom 15 bits of these values should
// match the BCDE_DEBUGGER_TYPE values that are defined in the header
// minkernel\published\base\bcdtypes.w
//

#define DEBUG_DEVICE_PORT_SERIAL 0x8000
#define DEBUG_DEVICE_PORT_1394 0x8001
#define DEBUG_DEVICE_PORT_USB 0x8002
#define DEBUG_DEVICE_PORT_NET 0x8003
#define DEBUG_DEVICE_PORT_LOCAL 0x8004

#define DEBUG_DEVICE_SERIAL_LEGACY_16550 0x0
#define DEBUG_DEVICE_SERIAL_GEN_16550 0x1
#define DEBUG_DEVICE_SERIAL_SPI_MAX311XE 0x2
#define DEBUG_DEVICE_SERIAL_PL011 0x3
#define DEBUG_DEVICE_SERIAL_Q8X60 0x4
#define DEBUG_DEVICE_SERIAL_NVIDIA 0x5
#define DEBUG_DEVICE_SERIAL_OMAP 0x6
#define DEBUG_DEVICE_SERIAL_UEFI_DBGPORT 0x7
#define DEBUG_DEVICE_SERIAL_APM88XXXX 0x8
#define DEBUG_DEVICE_SERIAL_Q8X74 0x9
#define DEBUG_DEVICE_SERIAL_SAM5250 0xA
#define DEBUG_DEVICE_SERIAL_USIF 0xB
#define DEBUG_DEVICE_SERIAL_IMX6 0xC
#define DEBUG_DEVICE_SERIAL_SBSA32 0xD
#define DEBUG_DEVICE_SERIAL_SBSA 0xE
#define DEBUG_DEVICE_SERIAL_ARM_DCC 0xF
#define DEBUG_DEVICE_SERIAL_BCM2835 0x10
#define DEBUG_DEVICE_SERIAL_SDM845 0x11
#define DEBUG_DEVICE_SERIAL_MM_16550 0x12

Thanks,
Chris

> > +      EFI_ACPI_RESERVED_WORD,                                 // Reserved
> > +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, BaseAddressRegister), //
> BaseAddressRegisterOffset
> > +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, AddressSize),        //
> AddressSizeOffset
> > +    },
> > +    {
> > +      // BaseAddressRegister
> > +      EFI_ACPI_5_0_SYSTEM_MEMORY,                             // AddressSpaceId
> > +      0x20,                                                   // RegisterBitWidth = 32
> > +      0,                                                      // RegisterBitOffset = 0
> > +      0x20,                                                   // AccessSize = 32
> > +      KD_UART_BASE_ADDR,                                      // Address
> > +    },
> > +    UART_IMX6_UART_ADDRESS_SIZE,                                // AddressSize
> > +    KD_UART_ACPI_PATH,                                          // NameSpaceString
> > +  },
> > +};
> > +
> > +VOID*
> > +ReferenceAcpiTable (
> > +  VOID
> > +  )
> > +{
> > +  return (void *) &Dbg2;
> > +}
> 
> rodata reference please. I will stop commenting on this for the
> remainder of the patch.
> 
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> > new file mode 100644
> > index 000000000000..4e4a3522e842
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> > @@ -0,0 +1,106 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +// IMX alternate settings codes
> > +#define IMX_ALT0 0x0
> > +#define IMX_ALT1 0x1
> > +#define IMX_ALT2 0x2
> > +#define IMX_ALT3 0x3
> > +#define IMX_ALT4 0x4
> > +#define IMX_ALT5 0x5
> > +#define IMX_ALT6 0x6
> > +#define IMX_ALT7 0x7
> > +
> > +// IMX SDMA request lines.
> > +// These are logical values, the mapping to the SOC
> > +// actual DMA request lines are done in the HAL extension.
> > +#define SDMA_REQ_VPU 0
> > +#define SDMA_REQ_IPU2 1
> > +#define SDMA_REQ_IPU1 2
> > +#define SDMA_REQ_HDMI_AUDIO 3
> > +#define SDMA_REQ_ECSPI1_RX 4
> > +#define SDMA_REQ_ECSPI1_TX 5
> > +#define SDMA_REQ_ECSPI2_RX 6
> > +#define SDMA_REQ_ECSPI2_TX 7
> > +#define SDMA_REQ_ECSPI3_RX 8
> > +#define SDMA_REQ_ECSPI3_TX 9
> > +#define SDMA_REQ_ECSPI4_RX 10
> > +#define SDMA_REQ_ECSPI4_TX 11
> > +#define SDMA_REQ_ECSPI5_RX 12
> > +#define SDMA_REQ_ECSPI5_TX 13
> > +#define SDMA_REQ_I2C1_RX 14
> > +#define SDMA_REQ_I2C1_TX 15
> > +#define SDMA_REQ_I2C2_RX 16
> > +#define SDMA_REQ_I2C2_TX 17
> > +#define SDMA_REQ_I2C3_RX 18
> > +#define SDMA_REQ_I2C3_TX 19
> > +#define SDMA_REQ_UART1_RX 20
> > +#define SDMA_REQ_UART1_TX 21
> > +#define SDMA_REQ_UART2_RX 22
> > +#define SDMA_REQ_UART2_TX 23
> > +#define SDMA_REQ_UART3_RX 24
> > +#define SDMA_REQ_UART3_TX 25
> > +#define SDMA_REQ_UART4_RX 26
> > +#define SDMA_REQ_UART4_TX 27
> > +#define SDMA_REQ_UART5_RX 28
> > +#define SDMA_REQ_UART5_TX 29
> > +#define SDMA_REQ_SPDIF_RX 30
> > +#define SDMA_REQ_SPDIF_TX 31
> > +#define SDMA_REQ_EPIT1 32
> > +#define SDMA_REQ_EPIT2 33
> > +#define SDMA_REQ_GPT 34
> > +#define SDMA_REQ_ASRC_RXA 35
> > +#define SDMA_REQ_ASRC_RXB 36
> > +#define SDMA_REQ_ASRC_RXC 37
> > +#define SDMA_REQ_ASRC_TXA 38
> > +#define SDMA_REQ_ASRC_TXB 39
> > +#define SDMA_REQ_ASRC_TXC 40
> > +#define SDMA_REQ_ESAI_RX 41
> > +#define SDMA_REQ_ESAI_TX 42
> > +#define SDMA_REQ_ASRC_TXA_2_ESAI_TX 43
> > +#define SDMA_REQ_ASRC_TXB_2_ESAI_TX 44
> > +#define SDMA_REQ_ASRC_TXC_2_ESAI_TX 45
> > +#define SDMA_REQ_SSI1_RX1 46
> > +#define SDMA_REQ_SSI1_TX1 47
> > +#define SDMA_REQ_SSI1_RX0 48
> > +#define SDMA_REQ_SSI1_TX0 49
> > +#define SDMA_REQ_SSI2_RX1 50
> > +#define SDMA_REQ_SSI2_TX1 51
> > +#define SDMA_REQ_SSI2_RX0 52
> > +#define SDMA_REQ_SSI2_TX0 53
> > +#define SDMA_REQ_SSI3_RX1 54
> > +#define SDMA_REQ_SSI3_TX1 55
> > +#define SDMA_REQ_SSI3_RX0 56
> > +#define SDMA_REQ_SSI3_TX0 57
> > +#define SDMA_REQ_EXT1 58
> > +#define SDMA_REQ_EXT2 59
> > +#define SDMA_REQ_UART6_RX 60
> > +#define SDMA_REQ_UART6_TX 61
> > +#define SDMA_REQ_ADC1 62
> > +#define SDMA_REQ_ADC2 63
> > +#define SDMA_REQ_I2C4_RX 64
> > +#define SDMA_REQ_I2C4_TX 65
> > +#define SDMA_REQ_CSI1 66
> > +#define SDMA_REQ_CSI2 67
> > +#define SDMA_REQ_PXP 68
> > +#define SDMA_REQ_LCDIF1 69
> > +#define SDMA_REQ_LCDIF2 70
> > +#define SDMA_REQ_QSPI1_RX 71
> > +#define SDMA_REQ_QSPI1_TX 72
> > +#define SDMA_REQ_QSPI2_RX 73
> > +#define SDMA_REQ_QSPI2_TX 74
> > +#define SDMA_REQ_SAI1_TX 75
> > +#define SDMA_REQ_SAI1_RX 76
> > +#define SDMA_REQ_SAI2_TX 77
> > +#define SDMA_REQ_SAI2_RX 78
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> > new file mode 100644
> > index 000000000000..eded7cdae7d0
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> > @@ -0,0 +1,106 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (ENET)
> > +{
> > +  Name (_HID, "NXP010D")
> > +  Name (_UID, 0x0)
> > +
> > +  Method (_STA) {
> > +    Return (0xF)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      // ENET MAC Core Base address
> > +      MEMORY32FIXED (ReadWrite, 0x02188000, 0x4000, )
> > +
> > +      // ENET MAC 0 Core IRQ
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 150 }
> > +
> > +      // ENET MAC 0 1588 Timer interrupt
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 151 }
> > +
> > +      // Errata ERR006687: workaround for GPIO interrupt to connect Enet
> interrupt
> > +      // to the GPC
> > +      GpioInt (Level, ActiveHigh, Shared, PullDefault, 0, "\\_SB.GPIO",) { 6 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +
> > +  Name (MAC, Buffer (6) {})
> > +  CreateDWordField (MAC, 0x00, MACL)
> > +  CreateWordField (MAC, 0x04, MACH)
> > +
> > +  // Device Specific Method takes 4 args:
> > +  //  Arg0 : Buffer containing a UUID [16 bytes]
> > +  //  Arg1 : Integer containing the Revision ID
> > +  //  Arg2 : Integer containing the Function Index
> > +  //  Arg3 : Package that contains function-specific arguments
> > +  Method (_DSM, 0x4, NotSerialized) {
> > +    switch (ToBuffer (Arg0)) {
> > +    // iMX Enet interface identifier
> > +    case (ToUUID ("4EBBCB9D-4087-4791-80BD-8F8C08024206")) {
> > +        // Function selector
> > +        switch (Arg2) {
> > +        // Function 0: Query support
> > +        //   Bit  Description
> > +        //   ---  -------------------------------
> > +        //     0  Get property (Function 0)
> > +        //     1  Enet PHY address on MDIO bus (Function 1)
> > +        //     2  Get Mac Address (Function 2)
> > +        //     3  Get MDIO BAse Address (Function 3)
> > +        case (0) {
> > +            // Revision selector
> > +            switch (Arg1) {
> > +            case (0) {
> > +                // Functions {0,1,2} supported
> > +                Return (Buffer() { 0x07 });
> > +              }
> > +            default {
> > +                Return (Buffer() { 0x00 });
> > +              }
> > +            }
> > +          }
> > +
> > +        // Function 1: Return Enet PHY address on MDIO bus.
> > +        case (1) {
> > +            Return (0x00);
> > +          }
> > +
> > +        // Function 2: Return Mac Address
> > +        case (2) {
> > +            if (LEqual (SIGN, 0x474C424C)) {
> > +              if (LEqual (REVN, 1)) {
> > +                if (Lequal (MC0V, 1)) {
> > +                  Store (MC0L, MACL);
> > +                  Store (MC0H, MACH);
> > +                  Return (MAC)
> > +                }
> > +              }
> > +            }
> > +            Return (Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
> > +          }
> > +
> > +        default {
> > +            Return (Buffer() { 0x00 });
> > +          }
> > +        }
> > +      }
> > +    default {
> > +        Return (Buffer() { 0x00 });
> > +      }
> > +    }
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> > new file mode 100644
> > index 000000000000..eec71864210e
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> > @@ -0,0 +1,74 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (VPU0)
> > +{
> > +  Name (_HID, "NXP0109")
> > +  Name (_UID, 0x0)
> > +
> > +  Method (_STA) {
> > +    Return (0x0)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02040000, 0x3C000, )
> > +
> > +      // JPEG codec interrupt request
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 35 }
> > +
> > +      // VPU interrupt request
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 44 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +// Description: Graphics Processing Unit (GPU)
> > +Device (GPU0)
> > +{
> > +  Name (_HID, "VERI2000")
> > +  Name (_CID, "VERI2000")
> > +  Name (_UID, 0)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      // GPU 3D (GC2000)
> > +      MEMORY32FIXED (ReadWrite, 0x00130000, 0x4000, )
> > +
> > +      // GPU 2D (GC320)
> > +      MEMORY32FIXED (ReadWrite, 0x00134000, 0x4000, )
> > +
> > +      // IPU Base
> > +      MEMORY32FIXED (ReadWrite, 0x02600000, 0x400000, )
> > +
> > +      // HDMI PHY
> > +      MEMORY32FIXED (ReadWrite, 0x00120000, 0x9000, )
> > +
> > +      // GC2000
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 41 }
> > +
> > +      // GC320
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
> > +
> > +      // IPU1 sync interrupt request
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 38 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> > new file mode 100644
> > index 000000000000..d9a5d2f8500a
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> > @@ -0,0 +1,55 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (GPIO)
> > +{
> > +  Name (_HID, "NXP0103")
> > +  Name (_UID, 0x0)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      // GPIO1-7
> > +      MEMORY32FIXED (ReadWrite, 0x0209C000, 0x1C000, )
> > +
> > +      // IOMUXC
> > +      MEMORY32FIXED (ReadWrite, 0x020E0000, 0x4000, )
> > +
> > +      // GPIO1 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 98, 99 }
> > +
> > +      // GPIO2 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 100, 101 }
> > +
> > +      // GPIO3 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 102, 103 }
> > +
> > +      // GPIO4 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 104, 105 }
> > +
> > +      // GPIO5 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 106, 107 }
> > +
> > +      // GPIO6 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 108, 109 }
> > +
> > +      // GPIO7 0-15, 16-31
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 110, 111 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> > new file mode 100644
> > index 000000000000..af9f17890b97
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> > @@ -0,0 +1,67 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (I2C1)
> > +{
> > +  Name (_HID, "NXP0104")
> > +  Name (_UID, 0x1)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (I2C2)
> > +{
> > +  Name (_HID, "NXP0104")
> > +  Name (_UID, 0x2)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x021A4000, 0x14, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 69 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (I2C3)
> > +{
> > +  Name (_HID, "NXP0104")
> > +  Name (_UID, 0x3)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> > new file mode 100644
> > index 000000000000..1e0627f93000
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> > @@ -0,0 +1,298 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (PCI0)
> > +{
> > +  Name (_HID, "PNP0A08")
> > +  Name (_UID, 0)
> > +  Name (_STR, Unicode ("PCIe 0 Device"))
> > +  Name (_BBN, 0)
> > +  Name (_SEG, 0)
> > +
> 
> Please include a _CCA property for all DMA capable device objects -
> this is mandatory for ACPI on ARM, and even if Linux today does not
> support ACPI on 32-bit, I'd like to ensure that this code could work
> on Linux if we ever do support it.
> 
> > +  // PCIE_PL memory map
> > +  OperationRegion (PLGC, SystemMemory, 0x01FFC700, 0x220)
> > +  Field (PLGC, DWordAcc, NoLock, Preserve) {
> > +    Offset (0x2C),  // Skip to register 0x01FFC72C
> > +    DBG1, 32,       // PCIE_PL_DEBUG1
> > +  }
> > +
> > +  // IOMUXC memory map
> > +  OperationRegion (IMXC, SystemMemory, 0x020E0000, 0x4000)
> > +  Field (IMXC, DWordAcc, NoLock, Preserve) {
> > +    Offset (0x04),  // Skip to register 0x020E0004
> > +    GPR1, 32,       // IOMUXC_GPR1
> > +  }
> > +
> > +  // PCIe is only available if PCIe PHY reference clock is enabled and link is up
> > +  Method (_STA) {
> > +    Name (LNK, 0x0);
> > +    Name (GPR, 0x0);
> > +    Store (GPR1, GPR);  // read IOMUXC_GPR1 register
> > +
> > +    // Check if the PCIe PHY reference clock is enabled
> > +    If (LNotEqual (And (GPR, 0x00010000), 0x00010000)) {
> > +      Return (0x0)
> > +    }
> > +
> > +    Store (DBG1, LNK);  // read PCIE_PL_DEBUG1 register
> > +
> > +    // Check if link is already up and is not in training
> > +    //  Bit4  : [36]: xmlh_link_up LTSSM reports PHY link up
> > +    //  Bit29  : [61]: xmlh_link_in_training LTSSM performing link training
> > +    If (LAnd (And (DBG1, 0x00000010), Lequal (And (DBG1, 0x20000000),
> 0x00))) {
> > +      Return (0xF)
> > +    } else {
> > +      Return (0x0)
> > +    }
> > +  }
> > +
> > +  // Declare the resources assigned to this root complex.
> > +  Method (_CRS, 0, Serialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      WordBusNumber (
> > +        ResourceProducer, // Specify bus ranged is passed to child devices
> > +        MinFixed,         // Specify min address is fixed
> > +        MaxFixed,         // Specify max address is fixed
> > +        PosDecode,        // Positive decode of bus number
> > +        0,                // AddressGranularity 2 power of 0
> > +        0,                // AddressMinimum - Minimum Bus Number
> > +        1,                // AddressMaximum - Maximum Bus Number
> > +        0,                // AddressTranslation - Set to 0
> > +        2)                // RangeLength - Number of Busses
> > +
> > +      // PCI memory space
> > +      Memory32Fixed (ReadWrite, 0x01100000, 0x00E00000, )
> > +    })
> > +    Return (RBUF)
> > +  }
> > +
> > +  // Declare the PCI Routing Table.
> > +  Name (_PRT, Package() {
> > +    // Routing for device 0, all functions.
> > +    // Note: ARM doesn't support LNK nodes, so the third param
> > +    // is 0 and the fourth param is the SPI number of the interrupt
> > +    // line.
> 
> ARM supports LNK nodes just fine, so I suppose it is Windows on ARM
> that does not support them? Otherwise, just drop the comment - LNK
> nodes don't really buy us anything here anyway, so the current
> description works just fine.
> 
> > +    Package() {0x0000FFFF, 0, 0, 155}, // INTA
> > +    Package() {0x0000FFFF, 1, 0, 154}, // INTB
> > +    Package() {0x0000FFFF, 2, 0, 153}, // INTC
> > +    Package() {0x0000FFFF, 3, 0, 152}, // INTD/MSI
> > +  })
> > +
> > +  Name (SUPP, 0) // PCI _OSC Support Field value
> > +  Name (CTRL, 0) // PCI _OSC Control Field value
> > +
> > +  // Declare an _OSC (OS Control Hand-off) method which takes 4 arguments.
> > +  //
> > +  // Arguments:
> > +  //   Arg0  A Buffer containing a UUID
> > +  //   Arg1  An Integer containing a Revision ID of the buffer format
> > +  //   Arg2  An Integer containing a count of entries in Arg3
> > +  //   Arg3  A Buffer containing a list of DWORD capabilities
> > +  // Return Value:
> > +  //   A Buffer containing a list of capabilities
> > +  Method (_OSC, 4) {
> > +
> > +    // Create DWord-addressable fields from the Capabilities Buffer
> > +    // Create CDW1 outside the test as it's used in the else clause.
> > +    // The first DWORD in the _OSC Capabilities Buffer contains bits
> > +    // that are generic to _OSC
> > +    // PCI Firmware Specification - 4.5.1.
> > +    //
> > +    // ACPI - 6.2.10
> > +    // CDW return value information
> > +    // Bit 0 - Reserved (not used)
> > +    // Bit 1 - _OSC failure. Platform Firmware was unable to process the
> request or query
> > +    // Bit 2 - Unrecognized UUID
> > +    // Bit 3 - Unrecognized Revision
> > +    // Bit 4 - Capabilities Masked
> > +    // All others reserved
> > +
> > +    CreateDWordField (Arg3, 0, CDW1)
> > +    If (LEqual (Arg0, ToUUID ("33DB4D5B-1FF7-401C-9657-
> 7441C03DD766"))) {
> > +      CreateDWordField (Arg3, 4, CDW2)
> > +      CreateDWordField (Arg3, 8, CDW3)
> > +
> > +      // Save Capabilities DWord 2 & 3
> > +      // The second DWORD in the _OSC Capabilities Buffer is the Support Field
> > +      // The third DWORD in the _OSC Capabilities Buffer is the Control Field
> > +      // PCI Firmware Specification - 4.5.1.
> > +      // Supported feature should be set in the control field
> > +      //
> > +      // Support field
> > +      // Bit 0 - Extended PCI Config operation regions supported
> > +      // Bit 1 - Active State Power Management supported
> > +      // Bit 2 - Clock Power Management Capability supported
> > +      // Bit 3 - PCI Segment Groups supported
> > +      // Bit 4 - MSI supported
> > +      // Bit 5 - Optimized Buffer Flush and Fill supported
> > +      // Bit 6 - ASPM Optionality supported
> > +      //
> > +      // Control field
> > +      // Bit 0 - PCI Express Native Hot Plug control
> > +      // Bit 1 - SHPC Native Hot Plug control
> > +      // Bit 2 - PCI Express Native Power Management Events control
> > +      // Bit 3 - PCI Express Advanced Error Reporting control
> > +      // Bit 4 - PCI Express Capability Structure control
> > +      // Bit 5 - Latency Tolerance Reporting control
> > +
> > +      Store (CDW2, SUPP)
> > +      Store (CDW3, CTRL)
> > +
> > +      // Only allow native hot plug control if OS supports:
> > +      //  ASPM
> > +      //  Clock PM
> > +      //  MSI/MSI-X
> > +      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
> > +        And (CTRL, 0x1E, CTRL)
> > +      }
> > +
> > +      // Spec does not mention if standard hot plug is supported
> > +      // so unmask the bit
> > +      And (CTRL, 0x1D, CTRL)
> > +
> > +      // Check for unknown revision.
> > +      If (LNotEqual (Arg1, One)) {
> > +        Or (CDW1, 0x08, CDW1)
> > +      }
> > +
> > +      // Check if capabilities bits were masked.
> > +      If (LNotEqual (CDW3, CTRL)) {
> > +        Or (CDW1, 0x10, CDW1)
> > +      }
> > +
> > +      // Update DWORD3 in the buffer.
> > +      Store (CTRL, CDW3)
> > +      Return (Arg3)
> > +    } else {
> > +      // Unrecognized UUID
> > +      Or (CDW1, 4, CDW1)
> > +      Return (Arg3)
> > +    }
> > +  }
> > +
> > +  // Declare a _DSM method for various functions called by the OS.
> > +  // See the APCI spec, Section 9.14.1,
> > +  // and the PCI FW spec, Section 4.6.
> > +  // See also:
> > +  //
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdownlo
> ad.microsoft.com%2Fdownload%2F9%2Fc%2F5%2F9c5b2167-8017-4bae-
> 9fde-d599bac8184a%2FPCI-
> rsc.doc&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57e132
> 26930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db47%7
> C1%7C0%7C636806420682778903&amp;sdata=%2F%2BvAI1gg5FsEDjrSQ1Ro
> mHI0AKVOmiBai79tP0qTAOg%3D&amp;reserved=0
> > +  Method (_DSM, 0x4, Serialized) {
> > +    // Match against the _DSM PCI UUID. PCI firmware spec - 4.6.1
> > +    //     Arg0 - UUID
> > +    //     Arg1 - Revision ID
> > +    //     Arg2 - Function Index
> > +    //     Arg3 - Empty Package
> > +    //
> > +    // Revision 1 & 2
> > +    //     Function 1 - PCI Express Slot Information
> > +    //     Function 2 - PCI Express Slot Number
> > +    //     Function 3 - Vendor-specific Token ID
> > +    //     Function 4 - PCI Bus Capabilities
> > +    //     Function 5 - Ignore PCI Boot Configuration
> > +    // Revision 2 only
> > +    //     Function 6 - LTR Maximum Latency
> > +    //     Function 7 - Express device under OS
> > +    If (LEqual (Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-
> EA4D19C3434D"))) {
> > +
> > +      switch (ToInteger (Arg2)) {
> > +      // Function 0: Return supported functions as a bit-field
> > +      // with one bit for each supported function.
> > +      // Bit 0 must always be set, as that represents
> > +      // function 0 (which is what is being called here).
> > +      // Support for different functions may depend on
> > +      // the revision ID of the interface, passed as Arg1.
> > +
> > +      // Function 0: Get supported functions
> > +      case (0) {
> > +          // Functions 0,1,5 are supported.
> > +          if (LEqual (Arg1, 1)) {
> > +            return (Buffer() { 0x23 })
> > +          }
> > +
> > +          // Functions 0,1,5,7 are supported.
> > +          if (LEqual (Arg1, 2)) {
> > +            return (Buffer() { 0xA3 })
> > +          }
> > +
> > +          // Functions 0,1,5,7 are supported for
> > +          // future revision. Expect backward compatibility
> > +          return (Buffer() { 0xA3 })
> > +        }
> > +
> > +      // Function 1: PCI Express Slot Information
> > +      // PCI firmware spec - 4.6.1
> > +      case (1) {
> > +          // Package item 1:
> > +          //    0: Failure
> > +          //    1: Success
> > +          // Package item 2:
> > +          //  Integer 1:Bit Position
> > +          //        0 Supports x1
> > +          //        1 Supports x2
> > +          //        2 Supports x4
> > +          //        3 Supports x8
> > +          //        4 Supports x12
> > +          //        5 Supports x16
> > +          //  Integer 2:
> > +          //        0h Unknown
> > +          //        1h PCI Express Card Slot
> > +          //        2h PCI Express Server I/O Module Slot
> > +          //        3h PCI Express ExpressCard* Slot
> > +          //        4h PCI Express Mini Card Slot
> > +          //        5h PCI Express Wireless Form Factor Slot
> > +          //        Others Reserved
> > +          //  Integer 3:
> > +          //        0 SMBus signal
> > +          //        1 WAKE# signal
> > +          return ( Package (2) {
> > +            0x01, // Status success (1)
> > +            Package() {
> > +              0, // Supports x1
> > +              4, // PCI Express Mini Card Slot
> > +              1  // Supported signals (no SMBus, WAKE#)
> > +            }
> > +          })
> > +        }
> > +
> > +      // Function 5: Ignore PCI Boot Configurations
> > +      // PCI firmware spec - 4.6.5
> > +      case (5) {
> > +          // Always allow OS to rebalance
> > +          return (0x01)
> > +        }
> > +
> > +      // Function 7: Naming a PCI or PCI Express Device Under
> > +      //             Operating Systems
> > +      // PCI firmware spec - 4.6.7
> > +      case (7) {
> > +          // Verify revision 2
> > +          if (LEqual (Arg1, 2)) {
> > +            // PCI Express Slot Parsing
> > +            Return ( Package (2) {
> > +              1,            // Instance of the enumeration
> > +              "PCIe Slot 1" // String name which matches the label on the chassis
> > +            })
> > +          }
> > +        }
> > +      }
> > +    }
> > +    return (Buffer() { 0 })
> > +  }
> > +
> > +  // Root Port 0 Device within the Root Complex.
> > +  Device (RP0) {
> > +    Name (_ADR, 0)  // Device 0, Function 0
> > +    Name (_S0W, 4)  // Supports wake
> > +  }
> > +
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> > new file mode 100644
> > index 000000000000..0bdc78080d26
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> > @@ -0,0 +1,106 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +OperationRegion (GLBL, SystemMemory, 0x10817000, 0x10)
> > +Field (GLBL, AnyAcc, Nolock, Preserve)
> > +{
> > +  Offset (0),       // Miscellaneous Dynamic Registers:
> > +  SIGN, 32,         // Global Page Signature 'GLBL'
> > +  REVN, 8,          // Revision
> > +      , 8,          // Reserved
> > +      , 8,          // Reserved
> > +      , 8,          // Reserved
> > +  M0ID, 8,          // MAC 0 ID
> > +  MC0V, 8,          // MAC 0 Valid
> > +  MC0L, 32,         // MAC Address 0 Low
> > +  MC0H, 16,         // MAC Address 0 High
> > +}
> > +
> > +Device (CPU0)
> > +{
> > +  Name (_HID, "ACPI0007")
> > +  Name (_UID, 0x0)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +}
> > +
> > +Device (CPU1)
> > +{
> > +  Name (_HID, "ACPI0007")
> > +  Name (_UID, 0x1)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +}
> > +
> > +Device (CPU2)
> > +{
> > +  Name (_HID, "ACPI0007")
> > +  Name (_UID, 0x2)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +}
> > +
> > +Device (CPU3)
> > +{
> > +  Name (_HID, "ACPI0007")
> > +  Name (_UID, 0x3)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +}
> > +
> > +// Timers HAL extension
> > +Device (EPIT)
> > +{
> > +  Name (_HID, "NXP0101")
> > +  Name (_UID, 0x0)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +}
> > +
> > +// Platform Extension Plugin
> > +Device (PEP0)
> > +{
> > +  Name (_HID, "NXP0102")
> > +  Name (_UID, 0x0)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      // CCM request 1
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 119 }
> > +
> > +      // CCM request 2
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 120 }
> > +
> > +      // GPC request 1
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 121 }
> > +
> > +      // UART1
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> > new file mode 100644
> > index 000000000000..22bab0cff575
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> > @@ -0,0 +1,85 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (PWM1)
> > +{
> > +  Name (_HID, "NXP010E")
> > +  Name (_UID, 0x1)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (PWM2)
> > +{
> > +  Name (_HID, "NXP010E")
> > +  Name (_UID, 0x2)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02084000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 116 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (PWM3)
> > +{
> > +  Name (_HID, "NXP010E")
> > +  Name (_UID, 0x3)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02088000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 117 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (PWM4)
> > +{
> > +  Name (_HID, "NXP010E")
> > +  Name (_UID, 0x4)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x0208C000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 118 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> > new file mode 100644
> > index 000000000000..fad33d2e9d6c
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> > @@ -0,0 +1,133 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +// uSDHC1
> > +Device (SDH1)
> > +{
> > +  Name (_HID, "NXP0108")
> > +  Name (_UID, 0x1)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +
> > +  // Child node to represent the only SD/MMC slot on this SD/MMC bus
> > +  // In theory an SDHC can be connected to multiple SD/MMC slots at
> > +  // the same time, but only 1 device will be selected and active at
> > +  // a time
> > +  Device (SD0) {
> > +    Method (_ADR) {
> > +      Return (0)
> > +    }
> > +
> > +    Method (_RMV) {
> > +      Return (0)
> > +    }
> > +  }
> > +}
> > +
> > +// uSDHC2
> > +Device (SDH2)
> > +{
> > +  Name (_HID, "NXP0108")
> > +  Name (_UID, 0x2)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +
> > +  Device (SD0) {
> > +    Method (_ADR) {
> > +      Return (0)
> > +    }
> > +
> > +    Method (_RMV) {
> > +      Return (0)
> > +    }
> > +  }
> > +}
> > +
> > +// uSDHC3
> > +Device (SDH3)
> > +{
> > +  Name (_HID, "NXP0108")
> > +  Name (_UID, 0x3)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +
> > +  Device (SD0) {
> > +    Method (_ADR) {
> > +      Return (0)
> > +    }
> > +
> > +    Method (_RMV) {
> > +      Return (0)
> > +    }
> > +  }
> > +}
> > +
> > +// uSDHC4
> > +Device (SDH4)
> > +{
> > +  Name (_HID, "NXP0108")
> > +  Name (_UID, 0x4)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x0219C000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 57 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +
> > +  Device (SD0) {
> > +    Method (_ADR) {
> > +      Return (0)
> > +    }
> > +
> > +    Method (_RMV) {
> > +      Return (0)
> > +    }
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> > new file mode 100644
> > index 000000000000..f68a7f306ecc
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> > @@ -0,0 +1,103 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (SPI1)
> > +{
> > +  Name (_HID, "NXP0105")
> > +  Name (_UID, 0x1)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02008000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 63 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (SPI2)
> > +{
> > +  Name (_HID, "NXP0105")
> > +  Name (_UID, 0x2)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (SPI3)
> > +{
> > +  Name (_HID, "NXP0105")
> > +  Name (_UID, 0x3)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02010000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 65 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (SPI4)
> > +{
> > +  Name (_HID, "NXP0105")
> > +  Name (_UID, 0x4)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02014000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 66 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > +
> > +Device (SPI5)
> > +{
> > +  Name (_HID, "NXP0105")
> > +  Name (_UID, 0x5)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      MEMORY32FIXED (ReadWrite, 0x02018000, 0x4000, )
> > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 67 }
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> > new file mode 100644
> > index 000000000000..83975792bcaf
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> > @@ -0,0 +1,33 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +Device (TREE)
> > +{
> > +  Name (_HID, "NXP010F")
> > +  Name (_CID, "TrEECSMP")
> > +  Name (_UID, 0)
> > +
> > +  Method (_STA) {
> > +    Return (0xf)
> > +  }
> > +
> > +  Method (_CRS, 0x0, NotSerialized) {
> > +    Name (RBUF, ResourceTemplate () {
> > +      // OP-TEE Shared memory area.
> > +      // Needs to match: PcdTrustZoneSharedMemoryBase,
> PcdTrustZoneSharedMemorySize
> > +      MEMORY32FIXED (ReadWrite, 0x12800000, 0x00200000, )
> > +    })
> > +    Return (RBUF)
> > +  }
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> > new file mode 100644
> > index 000000000000..58181ee9eda7
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> > @@ -0,0 +1,60 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +// Advertise support for PSCI
> > +#define FADT_ARM_BOOT_ARCH       0x01
> > +
> > +char FACP[268] = {
> > +  0x46, 0x41, 0x43, 0x50,                         // Signature : 'FACP'
> > +  0x0C, 0x01, 0x00, 0x00,                         // Length
> > +  0x05,                                           // Revision
> > +  0x00,                                           // Checksum
> > +  0x4E, 0x58, 0x50, 0x4D, 0x58, 0x36,             // OEMID : 'NXPMX6'
> > +  0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, // OEMTABLE : 'EDK2'
> > +  0x01, 0x00, 0x00, 0x00,                         // OEM Revision
> > +  0x4D, 0x53, 0x46, 0x54,                         // CreatorID : 'MSFT'
> > +  0x01, 0x00, 0x00, 0x00,                         // Creator revision
> > +  0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x04, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C,
> > +  0x00, 0x00, 0x21, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> FADT_ARM_BOOT_ARCH,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> > +};
> > +
> > +VOID*
> > +ReferenceAcpiTable (
> > +  VOID
> > +  )
> > +{
> > +  return (void *) &FACP;
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> > new file mode 100644
> > index 000000000000..1c382306c780
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> > @@ -0,0 +1,120 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#include <Library/AcpiLib.h>
> > +
> > +#include <Platform.h>
> > +#include <iMX6.h>
> > +
> > +#define GICC_BASE                 FixedPcdGet64 (PcdGicInterruptInterfaceBase)
> > +#define GICD_BASE                 FixedPcdGet64 (PcdGicDistributorBase)
> > +
> > +// Virtualization related fields. Not supported on IMX6
> > +#define GICH_BASE                 0
> > +#define GICV_BASE                 0
> > +#define VGIC_MAINT_INT            0
> > +#define PMU_INTERRUPT             0
> > +
> > +#pragma pack(push, 1)
> > +typedef struct {
> > +  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
> > +  EFI_ACPI_6_0_GIC_STRUCTURE GicC[FixedPcdGet32 (PcdCoreCount)];
> > +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE GicD;
> > +} ACPI_6_0_MADT_STRUCTURE;
> > +#pragma pack(pop)
> > +
> > +ACPI_6_0_MADT_STRUCTURE Madt = {
> > +  {
> > +    {
> > +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, //
> Signature
> > +      sizeof (ACPI_6_0_MADT_STRUCTURE),                       // Length
> > +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,  //
> Revision
> > +      0,                                                      // Checksum
> > +      EFI_ACPI_OEM_ID,                                        // OemId[6]
> > +      EFI_ACPI_OEM_TABLE_ID,                                  // OemTableId
> > +      EFI_ACPI_OEM_REVISION,                                  // OemRevision
> > +      EFI_ACPI_CREATOR_ID,                                    // CreatorId
> > +      EFI_ACPI_CREATOR_REVISION                               // CreatorRevision
> > +    },
> > +    0,      // LocalApicAddress
> > +    0       // Flags
> > +  },
> > +  {
> > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (0,                        // GicId
> > +                                      0x000,                     // AcpiCpuUid
> > +                                      0x000,                     // Mpidr
> > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > +                                      PMU_INTERRUPT,             // PmuIrq
> > +                                      GICC_BASE,                 // GicBase
> > +                                      GICV_BASE,                 // GicVBase
> > +                                      GICH_BASE,                 // GicHBase
> > +                                      VGIC_MAINT_INT,            // GsivId
> > +                                      0,                         // GicRBase
> > +                                      0                          // Efficiency
> > +                                     ),
> > +#if FixedPcdGet32(PcdCoreCount) > 1
> > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (1,                        // GicId
> > +                                      0x001,                     // AcpiCpuUid
> > +                                      0x001,                     // Mpidr
> > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > +                                      PMU_INTERRUPT,             // PmuIrq
> > +                                      GICC_BASE,                 // GicBase
> > +                                      GICV_BASE,                 // GicVBase
> > +                                      GICH_BASE,                 // GicHBase
> > +                                      VGIC_MAINT_INT,            // GsivId
> > +                                      0,                         // GicRBase
> > +                                      0                          // Efficiency
> > +                                     ),
> > +#if FixedPcdGet32(PcdCoreCount) > 2
> > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (2,                        // GicId
> > +                                      0x002,                     // AcpiCpuUid
> > +                                      0x002,                     // Mpidr
> > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > +                                      PMU_INTERRUPT,             // PmuIrq
> > +                                      GICC_BASE,                 // GicBase
> > +                                      GICV_BASE,                 // GicVBase
> > +                                      GICH_BASE,                 // GicHBase
> > +                                      VGIC_MAINT_INT,            // GsivId
> > +                                      0,                         // GicRBase
> > +                                      0                          // Efficiency
> > +                                     ),
> > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (3,                        // GicId
> > +                                      0x003,                     // AcpiCpuUid
> > +                                      0x003,                     // Mpidr
> > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > +                                      PMU_INTERRUPT,             // PmuIrq
> > +                                      GICC_BASE,                 // GicBase
> > +                                      GICV_BASE,                 // GicVBase
> > +                                      GICH_BASE,                 // GicHBase
> > +                                      VGIC_MAINT_INT,            // GsivId
> > +                                      0,                         // GicRBase
> > +                                      0                          // Efficiency
> > +                                     ),
> > +#endif
> > +#endif
> > +  },
> > +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (0x0,                   // GicDistHwId
> > +                                     GICD_BASE,             // GicDistBase
> > +                                     IC_DIST_VECTOR_BASE,   // GicDistVector
> > +                                     EFI_ACPI_6_0_GIC_V1    // GicVersion
> > +                                    )
> > +};
> > +
> > +VOID*
> > +ReferenceAcpiTable (
> > +  VOID
> > +  )
> > +{
> > +  return (VOID *)&Madt;
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> > new file mode 100644
> > index 000000000000..3e9d163cb52e
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> > @@ -0,0 +1,92 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#include <Platform.h>
> > +
> > +#include
> <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> > +
> > +#include "iMX6.h"
> > +#include "../Drivers/PciExpress/iMX6PciExpress.h"
> > +
> > +#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
> > +
> > +// Size in bytes a single bus consumes in ECAM space
> > +// Configuration size = 4K
> > +// Max device = 32
> > +// Max function = 8
> > +// Max bus size = 4K * 32 * 8
> > +#define ECAM_BUS_ADDR_SIZE  (1 << 20)
> > +
> > +// Provide 2 differenct base PCI space address. The first list would represent
> > +// the host config space and the second list would be the device config space.
> > +// Windows is expected to be able to parse the information.
> > +#define NUM_PCI 2
> > +
> > +// MCFG structure
> > +// PCI Firmware specification Table 4-2
> > +#pragma pack(push, 1)
> > +
> > +typedef struct {
> > +  EFI_ACPI_DESCRIPTION_HEADER Header;
> > +  UINT64                      Reserved;
> > +
> EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_AD
> DRESS_ALLOCATION_STRUCTURE AllocationStructure[NUM_PCI];
> > +}
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTIO
> N_TABLE;
> > +
> > +#pragma pack(pop)
> > +
> > +//
> > +// Multiple APIC Description Table
> > +//
> >
> +EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTIO
> N_TABLE Mcfg = {
> > +  {
> > +
> EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_B
> ASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> > +    sizeof
> (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTIO
> N_TABLE),
> > +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVIS
> ION,
> > +    0x00,                           // Checksum will be updated at runtime
> > +    EFI_ACPI_OEM_ID,                // OEMID
> > +    EFI_ACPI_OEM_TABLE_ID,          // OEM Table ID
> > +    EFI_ACPI_OEM_MCFG_REVISION,     // OEM Revision
> > +    EFI_ACPI_CREATOR_ID,            // Creator ID
> > +    EFI_ACPI_CREATOR_REVISION,      // Creator revision
> > +  },
> > +  0x00,                             // Reserved
> > +
> > +  {
> > +    // PCIe Host
> > +    {
> > +      PCIE_HOST_CONFIG_BASE_REG,        // PCIE Host Config Base Address
> > +      0x00,                             // PciSegmentGroupNumber (_SEG)
> > +      0x00,                             // StartBusNumber
> > +      0x00,                             // EndBusNumber
> > +      0x00000000                        // Reserved
> > +    },
> > +
> > +    // PCIe Device
> > +    {
> > +      PCIE_DEVICE_CONFIG_BASE_REG - ECAM_BUS_ADDR_SIZE,  //
> BaseAddress
> 
> OK, so the 'root port' and device ECAM spaces are disjoint, which is
> why you need two different entries here. Subtracting
> ECAM_BUS_ADDR_SIZE is needed since the bus range starts at 0x1
> 
> Could you clarify this in a comment please?
> 
> 
> > +      0x00,                              // PciSegmentGroupNumber (_SEG)
> > +      0x01,                              // StartBusNumber
> > +      0x01,                              // EndBusNumber
> > +      0x00000000                         // Reserved
> > +    }
> > +  }
> > +};
> > +
> > +VOID*
> > +ReferenceAcpiTable (
> > +  VOID
> > +  )
> > +{
> > +  return (VOID *)&Mcfg;
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> > new file mode 100644
> > index 000000000000..603422a737c4
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> > @@ -0,0 +1,95 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682788911&amp;sdata=X8SsmiEyzcOlu%2BLhD
> EV%2Bvfh3NkYNT9LE%2FNZxheiBPEo%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#include "Platform.h"
> > +#include "iMX6.h"
> > +
> > +// Ensure proper structure formats
> > +#pragma pack (1)
> > +
> > +typedef struct {
> > +  EFI_ACPI_DESCRIPTION_HEADER Header;
> > +  UINT8 Interface_Type;
> > +  UINT8 Reserved1[3];
> > +  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> > +  UINT8 Interrupt_Type;
> > +  UINT8 PCAT_compatible_IRQ;
> > +  UINT32 Interrupt;
> > +  UINT8 Baud_Rate;
> > +  UINT8 Parity;
> > +  UINT8 Stop_Bits;
> > +  UINT8 Flow_Control;
> > +  UINT8 Terminal_Type;
> > +  UINT8 Reserved2;
> > +  UINT16 PCI_Device_ID;
> > +  UINT16 PCI_Vender_ID;
> > +  UINT8 PCI_Bus;
> > +  UINT8 PCI_Device;
> > +  UINT8 PCI_Function;
> > +  UINT32 PCI_Flags;
> > +  UINT8 PCI_Segment;
> > +  UINT32 Reserved3;
> > +} EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE;
> > +
> > +#pragma pack ()
> > +
> > +EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE SPCR = {
> > +  {
> > +
> EFI_ACPI_5_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> > +    sizeof (EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE),
> > +    0x02,
> > +    0x00,                           // Checksum will be updated at runtime
> > +    EFI_ACPI_OEM_ID,
> > +    EFI_ACPI_OEM_TABLE_ID,
> > +    EFI_ACPI_OEM_REVISION,
> > +    EFI_ACPI_CREATOR_ID,
> > +    EFI_ACPI_CREATOR_REVISION,
> > +  },
> > +  DBG_PORT_SUBTYPE_IMX6,   // Serial Interface type = Serial Port Subtypes
> of the DBG2
> > +  {0x00, 0x00, 0x00},      // Reserved
> > +
> > +  // ACPI Generic Address Structure. Set to all zeroes to disable console
> redirection
> > +  {
> > +    EFI_ACPI_5_0_SYSTEM_MEMORY,         // AddressSpaceId:
> SystemMemory
> > +    0x20,                               // RegisterBitWidth
> > +    0,                                  // RegisterBitOffset
> > +    EFI_ACPI_5_0_DWORD,                 // AccessSize
> > +    (UINT64)CSP_BASE_REG_PA_UART3       // Address UART3
> > +  },
> > +  0x08,        // Interrupt Type = Bit[3] ARMH GIC interrupt. 0 means not
> supported.
> > +  0x00,        // IRQ. Not used since Bit[0] of the Interrupt Type field is not set
> > +  0x3c,        // Global System Interrupt used by the UART (UART3 interrupt 60)
> > +  0x07,        // Baud Rate
> > +  0x00,        // No Parity
> > +  0x01,        // One Stop Bit
> > +  0x00,        // Flow Control: None
> > +  0x03,        // Terminal Type: ANSI
> > +  0X00,        // Reserved
> > +  0xffff,      // 0xFFFF - not a PCI device
> > +  0xffff,      // 0xFFFF - not a PCI device
> > +  0x00,        // Bus Number. 0 - not a PCI device
> > +  0x00,        // Device Number. 0 - not a PCI device
> > +  0x00,        // Function. 0 - not a PCI device
> > +  0x00000000,  // PCI Flags
> > +  0x00,        // PCI Segment
> > +  0x00000000,  //Reserved
> > +};
> > +
> > +VOID*
> > +ReferenceAcpiTable (
> > +  VOID
> > +  )
> > +{
> > +  return (VOID *)&SPCR;
> > +}
> > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> > new file mode 100644
> > index 000000000000..a5abb2bf15d1
> > --- /dev/null
> > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> > @@ -0,0 +1,53 @@
> > +/** @file
> > +*
> > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > +*
> > +*  This program and the accompanying materials
> > +*  are licensed and made available under the terms and conditions of the BSD
> License
> > +*  which accompanies this distribution.  The full text of the license may be
> found at
> > +*
> https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> 47%7C1%7C0%7C636806420682788911&amp;sdata=X8SsmiEyzcOlu%2BLhD
> EV%2Bvfh3NkYNT9LE%2FNZxheiBPEo%3D&amp;reserved=0
> > +*
> > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> > +*
> > +**/
> > +
> > +#include <IndustryStandard/Tpm2Acpi.h>
> > +
> > +#include <Library/PcdLib.h>
> > +
> > +#include <Platform.h>
> > +#include "iMX6.h"
> > +
> > +// Definition is missing from MdePkg/Include/IndustryStandard/Tpm2Acpi.h
> > +#ifdef
> EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_IN
> TERFACE_WITH_TREE
> > +#error
> "EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_I
> NTERFACE_WITH_TREE is defined elsewhere."
> > +#else
> > +#define
> EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_IN
> TERFACE_WITH_TREE 9
> > +#endif
> > +
> > +EFI_TPM2_ACPI_TABLE Tpm2Table = {
> > +  {
> > +
> EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
> > +    sizeof (EFI_TPM2_ACPI_TABLE),
> > +    EFI_TPM2_ACPI_TABLE_REVISION,
> > +    0,                          // Checksum will be updated at runtime
> > +    EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
> > +    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
> > +    EFI_ACPI_OEM_REVISION,      // OEM revision number
> > +    EFI_ACPI_CREATOR_ID,        // Creator vendor ID
> > +    EFI_ACPI_CREATOR_REVISION,  // Creator revision number
> > +  },
> > +  0,                            // Flags
> > +  FixedPcdGet64 (PcdTpm2AcpiBufferBase),  // Control Area
> > +  // StartMethod
> > +
> EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_IN
> TERFACE_WITH_TREE,
> > +};
> > +
> > +VOID*
> > +ReferenceAcpiTable (
> > +  VOID
> > +  )
> > +{
> > +  return (VOID *)&Tpm2Table;
> > +}
> 
> 
> > --
> > 2.16.2.gvfs.1.33.gf5370f1
> >

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
  2019-01-08 21:43     ` Chris Co
@ 2019-01-29 14:09       ` Ard Biesheuvel
  0 siblings, 0 replies; 75+ messages in thread
From: Ard Biesheuvel @ 2019-01-29 14:09 UTC (permalink / raw)
  To: Chris Co; +Cc: edk2-devel@lists.01.org, Leif Lindholm, Michael D Kinney

On Tue, 8 Jan 2019 at 22:43, Chris Co <Christopher.Co@microsoft.com> wrote:
>
> Hi Ard,
>
> > -----Original Message-----
> > From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Sent: Monday, December 17, 2018 3:14 AM
> > To: Chris Co <Christopher.Co@microsoft.com>
> > Cc: edk2-devel@lists.01.org; Leif Lindholm <leif.lindholm@linaro.org>; Michael
> > D Kinney <michael.d.kinney@intel.com>
> > Subject: Re: [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables
> >
> > On Fri, 21 Sep 2018 at 10:26, Chris Co <Christopher.Co@microsoft.com>
> > wrote:
> > >
> > > +// PL310 L2 Cache Controller Resource Group
> > > +#define CSRT_PL310_MINIMUM_VERSION   1
> > > +#define CSRT_PL310_VERSION_2         2
> > > +#define CSRT_PL310_RAW_PROTOCOL      0
> > > +#define CSRT_PL310_SMC_PROTOCOL      1
> > > +
> > > +// We use PSCI_CPU_ON to turn on the L2 cache, with special value
> > > +// 0x00100000 for the Core ID. PSCI sees this core ID and knows
> > > +// this is an L2 cache operation, then looks at R2 for the
> > > +// operation to perform.
> > > +#define PSCI_FID_CPU_ON                        0x84000003
> > > +#define L2CACHE_SMC_R1                         0x00100000
> > > +#define L2CACHE_OP_ENABLE                      1
> > > +#define L2CACHE_OP_DISABLE                     2
> > > +#define L2CACHE_OP_ENABLE_WRITEBACK            3
> > > +#define L2CACHE_OP_DISABLE_WRITEBACK           4
> > > +#define L2CACHE_OP_ENABLE_WFLZ                 5
> > > +
> >
> > Who defined this protocol? Where is the opposite side implemented?
> >
> > Overloading architected PSCI calls to manage platform specific pieces
> > is really a no-go.
> >
>
> Since my initial patch set submission, we have updated this code to use the standardized protocol instead of overloading PSCI_CPU_ON. It will be in the V2 patch set.
>
> // PL310 L2 Cache Controller Resource Group
> #define CSRT_PL310_MINIMUM_VERSION   1
> #define CSRT_PL310_VERSION_2         2
> #define CSRT_PL310_RAW_PROTOCOL      0
> #define CSRT_PL310_SMC_PROTOCOL      1
>
> #define SMC_CALL_VAL(owner, funcid) \
>     (0x80000000 | (((owner) & 0x3F) << 24) | ((funcid) & 0xffff))
>
> #define SMC_OWNER_SIP                   2
> #define IMX_SMC_PL310_ENABLE            SMC_CALL_VAL(SMC_OWNER_SIP, 1)
> #define IMX_SMC_PL310_DISABLE           SMC_CALL_VAL(SMC_OWNER_SIP, 2)
> #define IMX_SMC_PL310_ENABLE_WRITEBACK  SMC_CALL_VAL(SMC_OWNER_SIP, 3)
> #define IMX_SMC_PL310_DISABLE_WRITEBACK SMC_CALL_VAL(SMC_OWNER_SIP, 4)
> #define IMX_SMC_PL310_ENABLE_WFLZ       SMC_CALL_VAL(SMC_OWNER_SIP, 5)
>

Excellent!

> > > +// Debug Port 2 table
> > > +EFI_ACPI_5_0_DEBUG_PORT_2_TABLE Dbg2 = {
> >
> > STATIC
> >
> > > +  {
> > > +    // Header
> > > +    {
> > > +      EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_SIGNATURE,     // Signature
> > "DBG2"
> > > +      sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE),      // Length
> > > +      EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION,          // Revision
> > > +      EFI_ACPI_5_0_UNDEFINED,                        // Checksum - updated at
> > runtime
> > > +      EFI_ACPI_OEM_ID,                               // OEM ID[6]
> > > +      EFI_ACPI_OEM_TABLE_ID,                         // OEM Table ID
> > > +      EFI_ACPI_OEM_REVISION,                         // OEM Revision
> > > +      EFI_ACPI_CREATOR_ID,                           // Creator ID
> > > +      EFI_ACPI_CREATOR_REVISION                      // Creator Revision
> > > +    },
> > > +    sizeof (EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_HEADER), //
> > OffsetDbgDeviceinfo
> > > +    1,                                               // NumberDbgDeviceInfo
> > > +  },
> > > +  {
> > > +    // Uart
> > > +    {
> > > +      // DeviceInfo
> > > +      EFI_ACPI_RESERVED_BYTE,                                 // Revision
> > > +      sizeof (DEBUG_DEVICE_INFO_UART),                        // Length
> > > +      1,                                                      // NumberofGenericAddressRegisters
> > > +      UART_NAME_SPACE_STRING_LENGTH,                          //
> > NameSpaceStringLength
> > > +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, NameSpaceString),    //
> > NameSpaceStringOffset
> > > +      0,                                                      // OemDataLength
> > > +      EFI_ACPI_RESERVED_WORD,                                 // OemDataOffset
> > > +      DBG2_TYPE_SERIAL,                                       // PortType
> > > +      DBG_PORT_SUBTYPE_IMX6,                                  // PortSubtype 000Ch
> >
> > Is this subtype defined in a published version of the SPCR/DBG2 specs?
> >
>
> Just checked and the IMX6 subtype is not present in the latest DBG2 spec. I'll work on getting it added. Does the subtype need to be in the published DBG2 spec before the patch can be accepted upstream?
>

Preferably, yes.

> Note: The definition is present in our WDK headers but I'm guessing that is not sufficient...
>
> //
> // ACPI debug device port types.  The bottom 15 bits of these values should
> // match the BCDE_DEBUGGER_TYPE values that are defined in the header
> // minkernel\published\base\bcdtypes.w
> //
>
> #define DEBUG_DEVICE_PORT_SERIAL 0x8000
> #define DEBUG_DEVICE_PORT_1394 0x8001
> #define DEBUG_DEVICE_PORT_USB 0x8002
> #define DEBUG_DEVICE_PORT_NET 0x8003
> #define DEBUG_DEVICE_PORT_LOCAL 0x8004
>
> #define DEBUG_DEVICE_SERIAL_LEGACY_16550 0x0
> #define DEBUG_DEVICE_SERIAL_GEN_16550 0x1
> #define DEBUG_DEVICE_SERIAL_SPI_MAX311XE 0x2
> #define DEBUG_DEVICE_SERIAL_PL011 0x3
> #define DEBUG_DEVICE_SERIAL_Q8X60 0x4
> #define DEBUG_DEVICE_SERIAL_NVIDIA 0x5
> #define DEBUG_DEVICE_SERIAL_OMAP 0x6
> #define DEBUG_DEVICE_SERIAL_UEFI_DBGPORT 0x7
> #define DEBUG_DEVICE_SERIAL_APM88XXXX 0x8
> #define DEBUG_DEVICE_SERIAL_Q8X74 0x9
> #define DEBUG_DEVICE_SERIAL_SAM5250 0xA
> #define DEBUG_DEVICE_SERIAL_USIF 0xB
> #define DEBUG_DEVICE_SERIAL_IMX6 0xC
> #define DEBUG_DEVICE_SERIAL_SBSA32 0xD
> #define DEBUG_DEVICE_SERIAL_SBSA 0xE
> #define DEBUG_DEVICE_SERIAL_ARM_DCC 0xF
> #define DEBUG_DEVICE_SERIAL_BCM2835 0x10
> #define DEBUG_DEVICE_SERIAL_SDM845 0x11
> #define DEBUG_DEVICE_SERIAL_MM_16550 0x12
>


> > > +      EFI_ACPI_RESERVED_WORD,                                 // Reserved
> > > +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, BaseAddressRegister), //
> > BaseAddressRegisterOffset
> > > +      OFFSET_OF (DEBUG_DEVICE_INFO_UART, AddressSize),        //
> > AddressSizeOffset
> > > +    },
> > > +    {
> > > +      // BaseAddressRegister
> > > +      EFI_ACPI_5_0_SYSTEM_MEMORY,                             // AddressSpaceId
> > > +      0x20,                                                   // RegisterBitWidth = 32
> > > +      0,                                                      // RegisterBitOffset = 0
> > > +      0x20,                                                   // AccessSize = 32
> > > +      KD_UART_BASE_ADDR,                                      // Address
> > > +    },
> > > +    UART_IMX6_UART_ADDRESS_SIZE,                                // AddressSize
> > > +    KD_UART_ACPI_PATH,                                          // NameSpaceString
> > > +  },
> > > +};
> > > +
> > > +VOID*
> > > +ReferenceAcpiTable (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return (void *) &Dbg2;
> > > +}
> >
> > rodata reference please. I will stop commenting on this for the
> > remainder of the patch.
> >
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> > > new file mode 100644
> > > index 000000000000..4e4a3522e842
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Common.h
> > > @@ -0,0 +1,106 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +// IMX alternate settings codes
> > > +#define IMX_ALT0 0x0
> > > +#define IMX_ALT1 0x1
> > > +#define IMX_ALT2 0x2
> > > +#define IMX_ALT3 0x3
> > > +#define IMX_ALT4 0x4
> > > +#define IMX_ALT5 0x5
> > > +#define IMX_ALT6 0x6
> > > +#define IMX_ALT7 0x7
> > > +
> > > +// IMX SDMA request lines.
> > > +// These are logical values, the mapping to the SOC
> > > +// actual DMA request lines are done in the HAL extension.
> > > +#define SDMA_REQ_VPU 0
> > > +#define SDMA_REQ_IPU2 1
> > > +#define SDMA_REQ_IPU1 2
> > > +#define SDMA_REQ_HDMI_AUDIO 3
> > > +#define SDMA_REQ_ECSPI1_RX 4
> > > +#define SDMA_REQ_ECSPI1_TX 5
> > > +#define SDMA_REQ_ECSPI2_RX 6
> > > +#define SDMA_REQ_ECSPI2_TX 7
> > > +#define SDMA_REQ_ECSPI3_RX 8
> > > +#define SDMA_REQ_ECSPI3_TX 9
> > > +#define SDMA_REQ_ECSPI4_RX 10
> > > +#define SDMA_REQ_ECSPI4_TX 11
> > > +#define SDMA_REQ_ECSPI5_RX 12
> > > +#define SDMA_REQ_ECSPI5_TX 13
> > > +#define SDMA_REQ_I2C1_RX 14
> > > +#define SDMA_REQ_I2C1_TX 15
> > > +#define SDMA_REQ_I2C2_RX 16
> > > +#define SDMA_REQ_I2C2_TX 17
> > > +#define SDMA_REQ_I2C3_RX 18
> > > +#define SDMA_REQ_I2C3_TX 19
> > > +#define SDMA_REQ_UART1_RX 20
> > > +#define SDMA_REQ_UART1_TX 21
> > > +#define SDMA_REQ_UART2_RX 22
> > > +#define SDMA_REQ_UART2_TX 23
> > > +#define SDMA_REQ_UART3_RX 24
> > > +#define SDMA_REQ_UART3_TX 25
> > > +#define SDMA_REQ_UART4_RX 26
> > > +#define SDMA_REQ_UART4_TX 27
> > > +#define SDMA_REQ_UART5_RX 28
> > > +#define SDMA_REQ_UART5_TX 29
> > > +#define SDMA_REQ_SPDIF_RX 30
> > > +#define SDMA_REQ_SPDIF_TX 31
> > > +#define SDMA_REQ_EPIT1 32
> > > +#define SDMA_REQ_EPIT2 33
> > > +#define SDMA_REQ_GPT 34
> > > +#define SDMA_REQ_ASRC_RXA 35
> > > +#define SDMA_REQ_ASRC_RXB 36
> > > +#define SDMA_REQ_ASRC_RXC 37
> > > +#define SDMA_REQ_ASRC_TXA 38
> > > +#define SDMA_REQ_ASRC_TXB 39
> > > +#define SDMA_REQ_ASRC_TXC 40
> > > +#define SDMA_REQ_ESAI_RX 41
> > > +#define SDMA_REQ_ESAI_TX 42
> > > +#define SDMA_REQ_ASRC_TXA_2_ESAI_TX 43
> > > +#define SDMA_REQ_ASRC_TXB_2_ESAI_TX 44
> > > +#define SDMA_REQ_ASRC_TXC_2_ESAI_TX 45
> > > +#define SDMA_REQ_SSI1_RX1 46
> > > +#define SDMA_REQ_SSI1_TX1 47
> > > +#define SDMA_REQ_SSI1_RX0 48
> > > +#define SDMA_REQ_SSI1_TX0 49
> > > +#define SDMA_REQ_SSI2_RX1 50
> > > +#define SDMA_REQ_SSI2_TX1 51
> > > +#define SDMA_REQ_SSI2_RX0 52
> > > +#define SDMA_REQ_SSI2_TX0 53
> > > +#define SDMA_REQ_SSI3_RX1 54
> > > +#define SDMA_REQ_SSI3_TX1 55
> > > +#define SDMA_REQ_SSI3_RX0 56
> > > +#define SDMA_REQ_SSI3_TX0 57
> > > +#define SDMA_REQ_EXT1 58
> > > +#define SDMA_REQ_EXT2 59
> > > +#define SDMA_REQ_UART6_RX 60
> > > +#define SDMA_REQ_UART6_TX 61
> > > +#define SDMA_REQ_ADC1 62
> > > +#define SDMA_REQ_ADC2 63
> > > +#define SDMA_REQ_I2C4_RX 64
> > > +#define SDMA_REQ_I2C4_TX 65
> > > +#define SDMA_REQ_CSI1 66
> > > +#define SDMA_REQ_CSI2 67
> > > +#define SDMA_REQ_PXP 68
> > > +#define SDMA_REQ_LCDIF1 69
> > > +#define SDMA_REQ_LCDIF2 70
> > > +#define SDMA_REQ_QSPI1_RX 71
> > > +#define SDMA_REQ_QSPI1_TX 72
> > > +#define SDMA_REQ_QSPI2_RX 73
> > > +#define SDMA_REQ_QSPI2_TX 74
> > > +#define SDMA_REQ_SAI1_TX 75
> > > +#define SDMA_REQ_SAI1_RX 76
> > > +#define SDMA_REQ_SAI2_TX 77
> > > +#define SDMA_REQ_SAI2_RX 78
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> > > new file mode 100644
> > > index 000000000000..eded7cdae7d0
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Enet.asl
> > > @@ -0,0 +1,106 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (ENET)
> > > +{
> > > +  Name (_HID, "NXP010D")
> > > +  Name (_UID, 0x0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xF)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      // ENET MAC Core Base address
> > > +      MEMORY32FIXED (ReadWrite, 0x02188000, 0x4000, )
> > > +
> > > +      // ENET MAC 0 Core IRQ
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 150 }
> > > +
> > > +      // ENET MAC 0 1588 Timer interrupt
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 151 }
> > > +
> > > +      // Errata ERR006687: workaround for GPIO interrupt to connect Enet
> > interrupt
> > > +      // to the GPC
> > > +      GpioInt (Level, ActiveHigh, Shared, PullDefault, 0, "\\_SB.GPIO",) { 6 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +
> > > +  Name (MAC, Buffer (6) {})
> > > +  CreateDWordField (MAC, 0x00, MACL)
> > > +  CreateWordField (MAC, 0x04, MACH)
> > > +
> > > +  // Device Specific Method takes 4 args:
> > > +  //  Arg0 : Buffer containing a UUID [16 bytes]
> > > +  //  Arg1 : Integer containing the Revision ID
> > > +  //  Arg2 : Integer containing the Function Index
> > > +  //  Arg3 : Package that contains function-specific arguments
> > > +  Method (_DSM, 0x4, NotSerialized) {
> > > +    switch (ToBuffer (Arg0)) {
> > > +    // iMX Enet interface identifier
> > > +    case (ToUUID ("4EBBCB9D-4087-4791-80BD-8F8C08024206")) {
> > > +        // Function selector
> > > +        switch (Arg2) {
> > > +        // Function 0: Query support
> > > +        //   Bit  Description
> > > +        //   ---  -------------------------------
> > > +        //     0  Get property (Function 0)
> > > +        //     1  Enet PHY address on MDIO bus (Function 1)
> > > +        //     2  Get Mac Address (Function 2)
> > > +        //     3  Get MDIO BAse Address (Function 3)
> > > +        case (0) {
> > > +            // Revision selector
> > > +            switch (Arg1) {
> > > +            case (0) {
> > > +                // Functions {0,1,2} supported
> > > +                Return (Buffer() { 0x07 });
> > > +              }
> > > +            default {
> > > +                Return (Buffer() { 0x00 });
> > > +              }
> > > +            }
> > > +          }
> > > +
> > > +        // Function 1: Return Enet PHY address on MDIO bus.
> > > +        case (1) {
> > > +            Return (0x00);
> > > +          }
> > > +
> > > +        // Function 2: Return Mac Address
> > > +        case (2) {
> > > +            if (LEqual (SIGN, 0x474C424C)) {
> > > +              if (LEqual (REVN, 1)) {
> > > +                if (Lequal (MC0V, 1)) {
> > > +                  Store (MC0L, MACL);
> > > +                  Store (MC0H, MACH);
> > > +                  Return (MAC)
> > > +                }
> > > +              }
> > > +            }
> > > +            Return (Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
> > > +          }
> > > +
> > > +        default {
> > > +            Return (Buffer() { 0x00 });
> > > +          }
> > > +        }
> > > +      }
> > > +    default {
> > > +        Return (Buffer() { 0x00 });
> > > +      }
> > > +    }
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> > > new file mode 100644
> > > index 000000000000..eec71864210e
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gfx.asl
> > > @@ -0,0 +1,74 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (VPU0)
> > > +{
> > > +  Name (_HID, "NXP0109")
> > > +  Name (_UID, 0x0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0x0)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02040000, 0x3C000, )
> > > +
> > > +      // JPEG codec interrupt request
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 35 }
> > > +
> > > +      // VPU interrupt request
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 44 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +// Description: Graphics Processing Unit (GPU)
> > > +Device (GPU0)
> > > +{
> > > +  Name (_HID, "VERI2000")
> > > +  Name (_CID, "VERI2000")
> > > +  Name (_UID, 0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      // GPU 3D (GC2000)
> > > +      MEMORY32FIXED (ReadWrite, 0x00130000, 0x4000, )
> > > +
> > > +      // GPU 2D (GC320)
> > > +      MEMORY32FIXED (ReadWrite, 0x00134000, 0x4000, )
> > > +
> > > +      // IPU Base
> > > +      MEMORY32FIXED (ReadWrite, 0x02600000, 0x400000, )
> > > +
> > > +      // HDMI PHY
> > > +      MEMORY32FIXED (ReadWrite, 0x00120000, 0x9000, )
> > > +
> > > +      // GC2000
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 41 }
> > > +
> > > +      // GC320
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
> > > +
> > > +      // IPU1 sync interrupt request
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 38 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> > > new file mode 100644
> > > index 000000000000..d9a5d2f8500a
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Gpio.asl
> > > @@ -0,0 +1,55 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (GPIO)
> > > +{
> > > +  Name (_HID, "NXP0103")
> > > +  Name (_UID, 0x0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      // GPIO1-7
> > > +      MEMORY32FIXED (ReadWrite, 0x0209C000, 0x1C000, )
> > > +
> > > +      // IOMUXC
> > > +      MEMORY32FIXED (ReadWrite, 0x020E0000, 0x4000, )
> > > +
> > > +      // GPIO1 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 98, 99 }
> > > +
> > > +      // GPIO2 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 100, 101 }
> > > +
> > > +      // GPIO3 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 102, 103 }
> > > +
> > > +      // GPIO4 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 104, 105 }
> > > +
> > > +      // GPIO5 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 106, 107 }
> > > +
> > > +      // GPIO6 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 108, 109 }
> > > +
> > > +      // GPIO7 0-15, 16-31
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 110, 111 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> > > new file mode 100644
> > > index 000000000000..af9f17890b97
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-I2c.asl
> > > @@ -0,0 +1,67 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (I2C1)
> > > +{
> > > +  Name (_HID, "NXP0104")
> > > +  Name (_UID, 0x1)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x021A0000, 0x14, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 68 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (I2C2)
> > > +{
> > > +  Name (_HID, "NXP0104")
> > > +  Name (_UID, 0x2)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x021A4000, 0x14, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 69 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (I2C3)
> > > +{
> > > +  Name (_HID, "NXP0104")
> > > +  Name (_UID, 0x3)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x021A8000, 0x14, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 70 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> > > new file mode 100644
> > > index 000000000000..1e0627f93000
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-PCIe.asl
> > > @@ -0,0 +1,298 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (PCI0)
> > > +{
> > > +  Name (_HID, "PNP0A08")
> > > +  Name (_UID, 0)
> > > +  Name (_STR, Unicode ("PCIe 0 Device"))
> > > +  Name (_BBN, 0)
> > > +  Name (_SEG, 0)
> > > +
> >
> > Please include a _CCA property for all DMA capable device objects -
> > this is mandatory for ACPI on ARM, and even if Linux today does not
> > support ACPI on 32-bit, I'd like to ensure that this code could work
> > on Linux if we ever do support it.
> >
> > > +  // PCIE_PL memory map
> > > +  OperationRegion (PLGC, SystemMemory, 0x01FFC700, 0x220)
> > > +  Field (PLGC, DWordAcc, NoLock, Preserve) {
> > > +    Offset (0x2C),  // Skip to register 0x01FFC72C
> > > +    DBG1, 32,       // PCIE_PL_DEBUG1
> > > +  }
> > > +
> > > +  // IOMUXC memory map
> > > +  OperationRegion (IMXC, SystemMemory, 0x020E0000, 0x4000)
> > > +  Field (IMXC, DWordAcc, NoLock, Preserve) {
> > > +    Offset (0x04),  // Skip to register 0x020E0004
> > > +    GPR1, 32,       // IOMUXC_GPR1
> > > +  }
> > > +
> > > +  // PCIe is only available if PCIe PHY reference clock is enabled and link is up
> > > +  Method (_STA) {
> > > +    Name (LNK, 0x0);
> > > +    Name (GPR, 0x0);
> > > +    Store (GPR1, GPR);  // read IOMUXC_GPR1 register
> > > +
> > > +    // Check if the PCIe PHY reference clock is enabled
> > > +    If (LNotEqual (And (GPR, 0x00010000), 0x00010000)) {
> > > +      Return (0x0)
> > > +    }
> > > +
> > > +    Store (DBG1, LNK);  // read PCIE_PL_DEBUG1 register
> > > +
> > > +    // Check if link is already up and is not in training
> > > +    //  Bit4  : [36]: xmlh_link_up LTSSM reports PHY link up
> > > +    //  Bit29  : [61]: xmlh_link_in_training LTSSM performing link training
> > > +    If (LAnd (And (DBG1, 0x00000010), Lequal (And (DBG1, 0x20000000),
> > 0x00))) {
> > > +      Return (0xF)
> > > +    } else {
> > > +      Return (0x0)
> > > +    }
> > > +  }
> > > +
> > > +  // Declare the resources assigned to this root complex.
> > > +  Method (_CRS, 0, Serialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      WordBusNumber (
> > > +        ResourceProducer, // Specify bus ranged is passed to child devices
> > > +        MinFixed,         // Specify min address is fixed
> > > +        MaxFixed,         // Specify max address is fixed
> > > +        PosDecode,        // Positive decode of bus number
> > > +        0,                // AddressGranularity 2 power of 0
> > > +        0,                // AddressMinimum - Minimum Bus Number
> > > +        1,                // AddressMaximum - Maximum Bus Number
> > > +        0,                // AddressTranslation - Set to 0
> > > +        2)                // RangeLength - Number of Busses
> > > +
> > > +      // PCI memory space
> > > +      Memory32Fixed (ReadWrite, 0x01100000, 0x00E00000, )
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +
> > > +  // Declare the PCI Routing Table.
> > > +  Name (_PRT, Package() {
> > > +    // Routing for device 0, all functions.
> > > +    // Note: ARM doesn't support LNK nodes, so the third param
> > > +    // is 0 and the fourth param is the SPI number of the interrupt
> > > +    // line.
> >
> > ARM supports LNK nodes just fine, so I suppose it is Windows on ARM
> > that does not support them? Otherwise, just drop the comment - LNK
> > nodes don't really buy us anything here anyway, so the current
> > description works just fine.
> >
> > > +    Package() {0x0000FFFF, 0, 0, 155}, // INTA
> > > +    Package() {0x0000FFFF, 1, 0, 154}, // INTB
> > > +    Package() {0x0000FFFF, 2, 0, 153}, // INTC
> > > +    Package() {0x0000FFFF, 3, 0, 152}, // INTD/MSI
> > > +  })
> > > +
> > > +  Name (SUPP, 0) // PCI _OSC Support Field value
> > > +  Name (CTRL, 0) // PCI _OSC Control Field value
> > > +
> > > +  // Declare an _OSC (OS Control Hand-off) method which takes 4 arguments.
> > > +  //
> > > +  // Arguments:
> > > +  //   Arg0  A Buffer containing a UUID
> > > +  //   Arg1  An Integer containing a Revision ID of the buffer format
> > > +  //   Arg2  An Integer containing a count of entries in Arg3
> > > +  //   Arg3  A Buffer containing a list of DWORD capabilities
> > > +  // Return Value:
> > > +  //   A Buffer containing a list of capabilities
> > > +  Method (_OSC, 4) {
> > > +
> > > +    // Create DWord-addressable fields from the Capabilities Buffer
> > > +    // Create CDW1 outside the test as it's used in the else clause.
> > > +    // The first DWORD in the _OSC Capabilities Buffer contains bits
> > > +    // that are generic to _OSC
> > > +    // PCI Firmware Specification - 4.5.1.
> > > +    //
> > > +    // ACPI - 6.2.10
> > > +    // CDW return value information
> > > +    // Bit 0 - Reserved (not used)
> > > +    // Bit 1 - _OSC failure. Platform Firmware was unable to process the
> > request or query
> > > +    // Bit 2 - Unrecognized UUID
> > > +    // Bit 3 - Unrecognized Revision
> > > +    // Bit 4 - Capabilities Masked
> > > +    // All others reserved
> > > +
> > > +    CreateDWordField (Arg3, 0, CDW1)
> > > +    If (LEqual (Arg0, ToUUID ("33DB4D5B-1FF7-401C-9657-
> > 7441C03DD766"))) {
> > > +      CreateDWordField (Arg3, 4, CDW2)
> > > +      CreateDWordField (Arg3, 8, CDW3)
> > > +
> > > +      // Save Capabilities DWord 2 & 3
> > > +      // The second DWORD in the _OSC Capabilities Buffer is the Support Field
> > > +      // The third DWORD in the _OSC Capabilities Buffer is the Control Field
> > > +      // PCI Firmware Specification - 4.5.1.
> > > +      // Supported feature should be set in the control field
> > > +      //
> > > +      // Support field
> > > +      // Bit 0 - Extended PCI Config operation regions supported
> > > +      // Bit 1 - Active State Power Management supported
> > > +      // Bit 2 - Clock Power Management Capability supported
> > > +      // Bit 3 - PCI Segment Groups supported
> > > +      // Bit 4 - MSI supported
> > > +      // Bit 5 - Optimized Buffer Flush and Fill supported
> > > +      // Bit 6 - ASPM Optionality supported
> > > +      //
> > > +      // Control field
> > > +      // Bit 0 - PCI Express Native Hot Plug control
> > > +      // Bit 1 - SHPC Native Hot Plug control
> > > +      // Bit 2 - PCI Express Native Power Management Events control
> > > +      // Bit 3 - PCI Express Advanced Error Reporting control
> > > +      // Bit 4 - PCI Express Capability Structure control
> > > +      // Bit 5 - Latency Tolerance Reporting control
> > > +
> > > +      Store (CDW2, SUPP)
> > > +      Store (CDW3, CTRL)
> > > +
> > > +      // Only allow native hot plug control if OS supports:
> > > +      //  ASPM
> > > +      //  Clock PM
> > > +      //  MSI/MSI-X
> > > +      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
> > > +        And (CTRL, 0x1E, CTRL)
> > > +      }
> > > +
> > > +      // Spec does not mention if standard hot plug is supported
> > > +      // so unmask the bit
> > > +      And (CTRL, 0x1D, CTRL)
> > > +
> > > +      // Check for unknown revision.
> > > +      If (LNotEqual (Arg1, One)) {
> > > +        Or (CDW1, 0x08, CDW1)
> > > +      }
> > > +
> > > +      // Check if capabilities bits were masked.
> > > +      If (LNotEqual (CDW3, CTRL)) {
> > > +        Or (CDW1, 0x10, CDW1)
> > > +      }
> > > +
> > > +      // Update DWORD3 in the buffer.
> > > +      Store (CTRL, CDW3)
> > > +      Return (Arg3)
> > > +    } else {
> > > +      // Unrecognized UUID
> > > +      Or (CDW1, 4, CDW1)
> > > +      Return (Arg3)
> > > +    }
> > > +  }
> > > +
> > > +  // Declare a _DSM method for various functions called by the OS.
> > > +  // See the APCI spec, Section 9.14.1,
> > > +  // and the PCI FW spec, Section 4.6.
> > > +  // See also:
> > > +  //
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdownlo
> > ad.microsoft.com%2Fdownload%2F9%2Fc%2F5%2F9c5b2167-8017-4bae-
> > 9fde-d599bac8184a%2FPCI-
> > rsc.doc&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57e132
> > 26930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db47%7
> > C1%7C0%7C636806420682778903&amp;sdata=%2F%2BvAI1gg5FsEDjrSQ1Ro
> > mHI0AKVOmiBai79tP0qTAOg%3D&amp;reserved=0
> > > +  Method (_DSM, 0x4, Serialized) {
> > > +    // Match against the _DSM PCI UUID. PCI firmware spec - 4.6.1
> > > +    //     Arg0 - UUID
> > > +    //     Arg1 - Revision ID
> > > +    //     Arg2 - Function Index
> > > +    //     Arg3 - Empty Package
> > > +    //
> > > +    // Revision 1 & 2
> > > +    //     Function 1 - PCI Express Slot Information
> > > +    //     Function 2 - PCI Express Slot Number
> > > +    //     Function 3 - Vendor-specific Token ID
> > > +    //     Function 4 - PCI Bus Capabilities
> > > +    //     Function 5 - Ignore PCI Boot Configuration
> > > +    // Revision 2 only
> > > +    //     Function 6 - LTR Maximum Latency
> > > +    //     Function 7 - Express device under OS
> > > +    If (LEqual (Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-
> > EA4D19C3434D"))) {
> > > +
> > > +      switch (ToInteger (Arg2)) {
> > > +      // Function 0: Return supported functions as a bit-field
> > > +      // with one bit for each supported function.
> > > +      // Bit 0 must always be set, as that represents
> > > +      // function 0 (which is what is being called here).
> > > +      // Support for different functions may depend on
> > > +      // the revision ID of the interface, passed as Arg1.
> > > +
> > > +      // Function 0: Get supported functions
> > > +      case (0) {
> > > +          // Functions 0,1,5 are supported.
> > > +          if (LEqual (Arg1, 1)) {
> > > +            return (Buffer() { 0x23 })
> > > +          }
> > > +
> > > +          // Functions 0,1,5,7 are supported.
> > > +          if (LEqual (Arg1, 2)) {
> > > +            return (Buffer() { 0xA3 })
> > > +          }
> > > +
> > > +          // Functions 0,1,5,7 are supported for
> > > +          // future revision. Expect backward compatibility
> > > +          return (Buffer() { 0xA3 })
> > > +        }
> > > +
> > > +      // Function 1: PCI Express Slot Information
> > > +      // PCI firmware spec - 4.6.1
> > > +      case (1) {
> > > +          // Package item 1:
> > > +          //    0: Failure
> > > +          //    1: Success
> > > +          // Package item 2:
> > > +          //  Integer 1:Bit Position
> > > +          //        0 Supports x1
> > > +          //        1 Supports x2
> > > +          //        2 Supports x4
> > > +          //        3 Supports x8
> > > +          //        4 Supports x12
> > > +          //        5 Supports x16
> > > +          //  Integer 2:
> > > +          //        0h Unknown
> > > +          //        1h PCI Express Card Slot
> > > +          //        2h PCI Express Server I/O Module Slot
> > > +          //        3h PCI Express ExpressCard* Slot
> > > +          //        4h PCI Express Mini Card Slot
> > > +          //        5h PCI Express Wireless Form Factor Slot
> > > +          //        Others Reserved
> > > +          //  Integer 3:
> > > +          //        0 SMBus signal
> > > +          //        1 WAKE# signal
> > > +          return ( Package (2) {
> > > +            0x01, // Status success (1)
> > > +            Package() {
> > > +              0, // Supports x1
> > > +              4, // PCI Express Mini Card Slot
> > > +              1  // Supported signals (no SMBus, WAKE#)
> > > +            }
> > > +          })
> > > +        }
> > > +
> > > +      // Function 5: Ignore PCI Boot Configurations
> > > +      // PCI firmware spec - 4.6.5
> > > +      case (5) {
> > > +          // Always allow OS to rebalance
> > > +          return (0x01)
> > > +        }
> > > +
> > > +      // Function 7: Naming a PCI or PCI Express Device Under
> > > +      //             Operating Systems
> > > +      // PCI firmware spec - 4.6.7
> > > +      case (7) {
> > > +          // Verify revision 2
> > > +          if (LEqual (Arg1, 2)) {
> > > +            // PCI Express Slot Parsing
> > > +            Return ( Package (2) {
> > > +              1,            // Instance of the enumeration
> > > +              "PCIe Slot 1" // String name which matches the label on the chassis
> > > +            })
> > > +          }
> > > +        }
> > > +      }
> > > +    }
> > > +    return (Buffer() { 0 })
> > > +  }
> > > +
> > > +  // Root Port 0 Device within the Root Complex.
> > > +  Device (RP0) {
> > > +    Name (_ADR, 0)  // Device 0, Function 0
> > > +    Name (_S0W, 4)  // Supports wake
> > > +  }
> > > +
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> > > new file mode 100644
> > > index 000000000000..0bdc78080d26
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Platform.asl
> > > @@ -0,0 +1,106 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +OperationRegion (GLBL, SystemMemory, 0x10817000, 0x10)
> > > +Field (GLBL, AnyAcc, Nolock, Preserve)
> > > +{
> > > +  Offset (0),       // Miscellaneous Dynamic Registers:
> > > +  SIGN, 32,         // Global Page Signature 'GLBL'
> > > +  REVN, 8,          // Revision
> > > +      , 8,          // Reserved
> > > +      , 8,          // Reserved
> > > +      , 8,          // Reserved
> > > +  M0ID, 8,          // MAC 0 ID
> > > +  MC0V, 8,          // MAC 0 Valid
> > > +  MC0L, 32,         // MAC Address 0 Low
> > > +  MC0H, 16,         // MAC Address 0 High
> > > +}
> > > +
> > > +Device (CPU0)
> > > +{
> > > +  Name (_HID, "ACPI0007")
> > > +  Name (_UID, 0x0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +}
> > > +
> > > +Device (CPU1)
> > > +{
> > > +  Name (_HID, "ACPI0007")
> > > +  Name (_UID, 0x1)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +}
> > > +
> > > +Device (CPU2)
> > > +{
> > > +  Name (_HID, "ACPI0007")
> > > +  Name (_UID, 0x2)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +}
> > > +
> > > +Device (CPU3)
> > > +{
> > > +  Name (_HID, "ACPI0007")
> > > +  Name (_UID, 0x3)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +}
> > > +
> > > +// Timers HAL extension
> > > +Device (EPIT)
> > > +{
> > > +  Name (_HID, "NXP0101")
> > > +  Name (_UID, 0x0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +}
> > > +
> > > +// Platform Extension Plugin
> > > +Device (PEP0)
> > > +{
> > > +  Name (_HID, "NXP0102")
> > > +  Name (_UID, 0x0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      // CCM request 1
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 119 }
> > > +
> > > +      // CCM request 2
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 120 }
> > > +
> > > +      // GPC request 1
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 121 }
> > > +
> > > +      // UART1
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { 58 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> > > new file mode 100644
> > > index 000000000000..22bab0cff575
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Pwm.asl
> > > @@ -0,0 +1,85 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (PWM1)
> > > +{
> > > +  Name (_HID, "NXP010E")
> > > +  Name (_UID, 0x1)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02080000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 115 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (PWM2)
> > > +{
> > > +  Name (_HID, "NXP010E")
> > > +  Name (_UID, 0x2)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02084000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 116 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (PWM3)
> > > +{
> > > +  Name (_HID, "NXP010E")
> > > +  Name (_UID, 0x3)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02088000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 117 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (PWM4)
> > > +{
> > > +  Name (_HID, "NXP010E")
> > > +  Name (_UID, 0x4)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x0208C000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 118 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> > > new file mode 100644
> > > index 000000000000..fad33d2e9d6c
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Sdhc.asl
> > > @@ -0,0 +1,133 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +// uSDHC1
> > > +Device (SDH1)
> > > +{
> > > +  Name (_HID, "NXP0108")
> > > +  Name (_UID, 0x1)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02190000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 54 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +
> > > +  // Child node to represent the only SD/MMC slot on this SD/MMC bus
> > > +  // In theory an SDHC can be connected to multiple SD/MMC slots at
> > > +  // the same time, but only 1 device will be selected and active at
> > > +  // a time
> > > +  Device (SD0) {
> > > +    Method (_ADR) {
> > > +      Return (0)
> > > +    }
> > > +
> > > +    Method (_RMV) {
> > > +      Return (0)
> > > +    }
> > > +  }
> > > +}
> > > +
> > > +// uSDHC2
> > > +Device (SDH2)
> > > +{
> > > +  Name (_HID, "NXP0108")
> > > +  Name (_UID, 0x2)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02194000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 55 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +
> > > +  Device (SD0) {
> > > +    Method (_ADR) {
> > > +      Return (0)
> > > +    }
> > > +
> > > +    Method (_RMV) {
> > > +      Return (0)
> > > +    }
> > > +  }
> > > +}
> > > +
> > > +// uSDHC3
> > > +Device (SDH3)
> > > +{
> > > +  Name (_HID, "NXP0108")
> > > +  Name (_UID, 0x3)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02198000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 56 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +
> > > +  Device (SD0) {
> > > +    Method (_ADR) {
> > > +      Return (0)
> > > +    }
> > > +
> > > +    Method (_RMV) {
> > > +      Return (0)
> > > +    }
> > > +  }
> > > +}
> > > +
> > > +// uSDHC4
> > > +Device (SDH4)
> > > +{
> > > +  Name (_HID, "NXP0108")
> > > +  Name (_UID, 0x4)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x0219C000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 57 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +
> > > +  Device (SD0) {
> > > +    Method (_ADR) {
> > > +      Return (0)
> > > +    }
> > > +
> > > +    Method (_RMV) {
> > > +      Return (0)
> > > +    }
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> > > new file mode 100644
> > > index 000000000000..f68a7f306ecc
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-Spi.asl
> > > @@ -0,0 +1,103 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (SPI1)
> > > +{
> > > +  Name (_HID, "NXP0105")
> > > +  Name (_UID, 0x1)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02008000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 63 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (SPI2)
> > > +{
> > > +  Name (_HID, "NXP0105")
> > > +  Name (_UID, 0x2)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x0200C000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 64 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (SPI3)
> > > +{
> > > +  Name (_HID, "NXP0105")
> > > +  Name (_UID, 0x3)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02010000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 65 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (SPI4)
> > > +{
> > > +  Name (_HID, "NXP0105")
> > > +  Name (_UID, 0x4)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02014000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 66 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > +
> > > +Device (SPI5)
> > > +{
> > > +  Name (_HID, "NXP0105")
> > > +  Name (_UID, 0x5)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      MEMORY32FIXED (ReadWrite, 0x02018000, 0x4000, )
> > > +      Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 67 }
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> > > new file mode 100644
> > > index 000000000000..83975792bcaf
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Dsdt-TrEE.asl
> > > @@ -0,0 +1,33 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +Device (TREE)
> > > +{
> > > +  Name (_HID, "NXP010F")
> > > +  Name (_CID, "TrEECSMP")
> > > +  Name (_UID, 0)
> > > +
> > > +  Method (_STA) {
> > > +    Return (0xf)
> > > +  }
> > > +
> > > +  Method (_CRS, 0x0, NotSerialized) {
> > > +    Name (RBUF, ResourceTemplate () {
> > > +      // OP-TEE Shared memory area.
> > > +      // Needs to match: PcdTrustZoneSharedMemoryBase,
> > PcdTrustZoneSharedMemorySize
> > > +      MEMORY32FIXED (ReadWrite, 0x12800000, 0x00200000, )
> > > +    })
> > > +    Return (RBUF)
> > > +  }
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> > > new file mode 100644
> > > index 000000000000..58181ee9eda7
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Fadt.aslc
> > > @@ -0,0 +1,60 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +// Advertise support for PSCI
> > > +#define FADT_ARM_BOOT_ARCH       0x01
> > > +
> > > +char FACP[268] = {
> > > +  0x46, 0x41, 0x43, 0x50,                         // Signature : 'FACP'
> > > +  0x0C, 0x01, 0x00, 0x00,                         // Length
> > > +  0x05,                                           // Revision
> > > +  0x00,                                           // Checksum
> > > +  0x4E, 0x58, 0x50, 0x4D, 0x58, 0x36,             // OEMID : 'NXPMX6'
> > > +  0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, // OEMTABLE : 'EDK2'
> > > +  0x01, 0x00, 0x00, 0x00,                         // OEM Revision
> > > +  0x4D, 0x53, 0x46, 0x54,                         // CreatorID : 'MSFT'
> > > +  0x01, 0x00, 0x00, 0x00,                         // Creator revision
> > > +  0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x04, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C,
> > > +  0x00, 0x00, 0x21, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > FADT_ARM_BOOT_ARCH,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> > > +};
> > > +
> > > +VOID*
> > > +ReferenceAcpiTable (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return (void *) &FACP;
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> > > new file mode 100644
> > > index 000000000000..1c382306c780
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Madt.aslc
> > > @@ -0,0 +1,120 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +#include <Library/AcpiLib.h>
> > > +
> > > +#include <Platform.h>
> > > +#include <iMX6.h>
> > > +
> > > +#define GICC_BASE                 FixedPcdGet64 (PcdGicInterruptInterfaceBase)
> > > +#define GICD_BASE                 FixedPcdGet64 (PcdGicDistributorBase)
> > > +
> > > +// Virtualization related fields. Not supported on IMX6
> > > +#define GICH_BASE                 0
> > > +#define GICV_BASE                 0
> > > +#define VGIC_MAINT_INT            0
> > > +#define PMU_INTERRUPT             0
> > > +
> > > +#pragma pack(push, 1)
> > > +typedef struct {
> > > +  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
> > > +  EFI_ACPI_6_0_GIC_STRUCTURE GicC[FixedPcdGet32 (PcdCoreCount)];
> > > +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE GicD;
> > > +} ACPI_6_0_MADT_STRUCTURE;
> > > +#pragma pack(pop)
> > > +
> > > +ACPI_6_0_MADT_STRUCTURE Madt = {
> > > +  {
> > > +    {
> > > +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, //
> > Signature
> > > +      sizeof (ACPI_6_0_MADT_STRUCTURE),                       // Length
> > > +      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,  //
> > Revision
> > > +      0,                                                      // Checksum
> > > +      EFI_ACPI_OEM_ID,                                        // OemId[6]
> > > +      EFI_ACPI_OEM_TABLE_ID,                                  // OemTableId
> > > +      EFI_ACPI_OEM_REVISION,                                  // OemRevision
> > > +      EFI_ACPI_CREATOR_ID,                                    // CreatorId
> > > +      EFI_ACPI_CREATOR_REVISION                               // CreatorRevision
> > > +    },
> > > +    0,      // LocalApicAddress
> > > +    0       // Flags
> > > +  },
> > > +  {
> > > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (0,                        // GicId
> > > +                                      0x000,                     // AcpiCpuUid
> > > +                                      0x000,                     // Mpidr
> > > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > > +                                      PMU_INTERRUPT,             // PmuIrq
> > > +                                      GICC_BASE,                 // GicBase
> > > +                                      GICV_BASE,                 // GicVBase
> > > +                                      GICH_BASE,                 // GicHBase
> > > +                                      VGIC_MAINT_INT,            // GsivId
> > > +                                      0,                         // GicRBase
> > > +                                      0                          // Efficiency
> > > +                                     ),
> > > +#if FixedPcdGet32(PcdCoreCount) > 1
> > > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (1,                        // GicId
> > > +                                      0x001,                     // AcpiCpuUid
> > > +                                      0x001,                     // Mpidr
> > > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > > +                                      PMU_INTERRUPT,             // PmuIrq
> > > +                                      GICC_BASE,                 // GicBase
> > > +                                      GICV_BASE,                 // GicVBase
> > > +                                      GICH_BASE,                 // GicHBase
> > > +                                      VGIC_MAINT_INT,            // GsivId
> > > +                                      0,                         // GicRBase
> > > +                                      0                          // Efficiency
> > > +                                     ),
> > > +#if FixedPcdGet32(PcdCoreCount) > 2
> > > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (2,                        // GicId
> > > +                                      0x002,                     // AcpiCpuUid
> > > +                                      0x002,                     // Mpidr
> > > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > > +                                      PMU_INTERRUPT,             // PmuIrq
> > > +                                      GICC_BASE,                 // GicBase
> > > +                                      GICV_BASE,                 // GicVBase
> > > +                                      GICH_BASE,                 // GicHBase
> > > +                                      VGIC_MAINT_INT,            // GsivId
> > > +                                      0,                         // GicRBase
> > > +                                      0                          // Efficiency
> > > +                                     ),
> > > +    EFI_ACPI_6_0_GICC_STRUCTURE_INIT (3,                        // GicId
> > > +                                      0x003,                     // AcpiCpuUid
> > > +                                      0x003,                     // Mpidr
> > > +                                      EFI_ACPI_6_0_GIC_ENABLED,  // Flags
> > > +                                      PMU_INTERRUPT,             // PmuIrq
> > > +                                      GICC_BASE,                 // GicBase
> > > +                                      GICV_BASE,                 // GicVBase
> > > +                                      GICH_BASE,                 // GicHBase
> > > +                                      VGIC_MAINT_INT,            // GsivId
> > > +                                      0,                         // GicRBase
> > > +                                      0                          // Efficiency
> > > +                                     ),
> > > +#endif
> > > +#endif
> > > +  },
> > > +  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (0x0,                   // GicDistHwId
> > > +                                     GICD_BASE,             // GicDistBase
> > > +                                     IC_DIST_VECTOR_BASE,   // GicDistVector
> > > +                                     EFI_ACPI_6_0_GIC_V1    // GicVersion
> > > +                                    )
> > > +};
> > > +
> > > +VOID*
> > > +ReferenceAcpiTable (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return (VOID *)&Madt;
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> > > new file mode 100644
> > > index 000000000000..3e9d163cb52e
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Mcfg.aslc
> > > @@ -0,0 +1,92 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682778903&amp;sdata=5Sz9dYzJ18YJYW%2BBo
> > 9WjdEkYaV%2FCKgYwoxw3ou377Mw%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +#include <Platform.h>
> > > +
> > > +#include
> > <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> > > +
> > > +#include "iMX6.h"
> > > +#include "../Drivers/PciExpress/iMX6PciExpress.h"
> > > +
> > > +#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
> > > +
> > > +// Size in bytes a single bus consumes in ECAM space
> > > +// Configuration size = 4K
> > > +// Max device = 32
> > > +// Max function = 8
> > > +// Max bus size = 4K * 32 * 8
> > > +#define ECAM_BUS_ADDR_SIZE  (1 << 20)
> > > +
> > > +// Provide 2 differenct base PCI space address. The first list would represent
> > > +// the host config space and the second list would be the device config space.
> > > +// Windows is expected to be able to parse the information.
> > > +#define NUM_PCI 2
> > > +
> > > +// MCFG structure
> > > +// PCI Firmware specification Table 4-2
> > > +#pragma pack(push, 1)
> > > +
> > > +typedef struct {
> > > +  EFI_ACPI_DESCRIPTION_HEADER Header;
> > > +  UINT64                      Reserved;
> > > +
> > EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_AD
> > DRESS_ALLOCATION_STRUCTURE AllocationStructure[NUM_PCI];
> > > +}
> > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTIO
> > N_TABLE;
> > > +
> > > +#pragma pack(pop)
> > > +
> > > +//
> > > +// Multiple APIC Description Table
> > > +//
> > >
> > +EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTIO
> > N_TABLE Mcfg = {
> > > +  {
> > > +
> > EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_B
> > ASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> > > +    sizeof
> > (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTIO
> > N_TABLE),
> > > +
> > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVIS
> > ION,
> > > +    0x00,                           // Checksum will be updated at runtime
> > > +    EFI_ACPI_OEM_ID,                // OEMID
> > > +    EFI_ACPI_OEM_TABLE_ID,          // OEM Table ID
> > > +    EFI_ACPI_OEM_MCFG_REVISION,     // OEM Revision
> > > +    EFI_ACPI_CREATOR_ID,            // Creator ID
> > > +    EFI_ACPI_CREATOR_REVISION,      // Creator revision
> > > +  },
> > > +  0x00,                             // Reserved
> > > +
> > > +  {
> > > +    // PCIe Host
> > > +    {
> > > +      PCIE_HOST_CONFIG_BASE_REG,        // PCIE Host Config Base Address
> > > +      0x00,                             // PciSegmentGroupNumber (_SEG)
> > > +      0x00,                             // StartBusNumber
> > > +      0x00,                             // EndBusNumber
> > > +      0x00000000                        // Reserved
> > > +    },
> > > +
> > > +    // PCIe Device
> > > +    {
> > > +      PCIE_DEVICE_CONFIG_BASE_REG - ECAM_BUS_ADDR_SIZE,  //
> > BaseAddress
> >
> > OK, so the 'root port' and device ECAM spaces are disjoint, which is
> > why you need two different entries here. Subtracting
> > ECAM_BUS_ADDR_SIZE is needed since the bus range starts at 0x1
> >
> > Could you clarify this in a comment please?
> >
> >
> > > +      0x00,                              // PciSegmentGroupNumber (_SEG)
> > > +      0x01,                              // StartBusNumber
> > > +      0x01,                              // EndBusNumber
> > > +      0x00000000                         // Reserved
> > > +    }
> > > +  }
> > > +};
> > > +
> > > +VOID*
> > > +ReferenceAcpiTable (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return (VOID *)&Mcfg;
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> > > new file mode 100644
> > > index 000000000000..603422a737c4
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Spcr.aslc
> > > @@ -0,0 +1,95 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682788911&amp;sdata=X8SsmiEyzcOlu%2BLhD
> > EV%2Bvfh3NkYNT9LE%2FNZxheiBPEo%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +#include "Platform.h"
> > > +#include "iMX6.h"
> > > +
> > > +// Ensure proper structure formats
> > > +#pragma pack (1)
> > > +
> > > +typedef struct {
> > > +  EFI_ACPI_DESCRIPTION_HEADER Header;
> > > +  UINT8 Interface_Type;
> > > +  UINT8 Reserved1[3];
> > > +  EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> > > +  UINT8 Interrupt_Type;
> > > +  UINT8 PCAT_compatible_IRQ;
> > > +  UINT32 Interrupt;
> > > +  UINT8 Baud_Rate;
> > > +  UINT8 Parity;
> > > +  UINT8 Stop_Bits;
> > > +  UINT8 Flow_Control;
> > > +  UINT8 Terminal_Type;
> > > +  UINT8 Reserved2;
> > > +  UINT16 PCI_Device_ID;
> > > +  UINT16 PCI_Vender_ID;
> > > +  UINT8 PCI_Bus;
> > > +  UINT8 PCI_Device;
> > > +  UINT8 PCI_Function;
> > > +  UINT32 PCI_Flags;
> > > +  UINT8 PCI_Segment;
> > > +  UINT32 Reserved3;
> > > +} EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE;
> > > +
> > > +#pragma pack ()
> > > +
> > > +EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE SPCR = {
> > > +  {
> > > +
> > EFI_ACPI_5_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> > > +    sizeof (EFI_ACPI_5_0_SPCR_DESCRIPTION_TABLE),
> > > +    0x02,
> > > +    0x00,                           // Checksum will be updated at runtime
> > > +    EFI_ACPI_OEM_ID,
> > > +    EFI_ACPI_OEM_TABLE_ID,
> > > +    EFI_ACPI_OEM_REVISION,
> > > +    EFI_ACPI_CREATOR_ID,
> > > +    EFI_ACPI_CREATOR_REVISION,
> > > +  },
> > > +  DBG_PORT_SUBTYPE_IMX6,   // Serial Interface type = Serial Port Subtypes
> > of the DBG2
> > > +  {0x00, 0x00, 0x00},      // Reserved
> > > +
> > > +  // ACPI Generic Address Structure. Set to all zeroes to disable console
> > redirection
> > > +  {
> > > +    EFI_ACPI_5_0_SYSTEM_MEMORY,         // AddressSpaceId:
> > SystemMemory
> > > +    0x20,                               // RegisterBitWidth
> > > +    0,                                  // RegisterBitOffset
> > > +    EFI_ACPI_5_0_DWORD,                 // AccessSize
> > > +    (UINT64)CSP_BASE_REG_PA_UART3       // Address UART3
> > > +  },
> > > +  0x08,        // Interrupt Type = Bit[3] ARMH GIC interrupt. 0 means not
> > supported.
> > > +  0x00,        // IRQ. Not used since Bit[0] of the Interrupt Type field is not set
> > > +  0x3c,        // Global System Interrupt used by the UART (UART3 interrupt 60)
> > > +  0x07,        // Baud Rate
> > > +  0x00,        // No Parity
> > > +  0x01,        // One Stop Bit
> > > +  0x00,        // Flow Control: None
> > > +  0x03,        // Terminal Type: ANSI
> > > +  0X00,        // Reserved
> > > +  0xffff,      // 0xFFFF - not a PCI device
> > > +  0xffff,      // 0xFFFF - not a PCI device
> > > +  0x00,        // Bus Number. 0 - not a PCI device
> > > +  0x00,        // Device Number. 0 - not a PCI device
> > > +  0x00,        // Function. 0 - not a PCI device
> > > +  0x00000000,  // PCI Flags
> > > +  0x00,        // PCI Segment
> > > +  0x00000000,  //Reserved
> > > +};
> > > +
> > > +VOID*
> > > +ReferenceAcpiTable (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return (VOID *)&SPCR;
> > > +}
> > > diff --git a/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> > b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> > > new file mode 100644
> > > index 000000000000..a5abb2bf15d1
> > > --- /dev/null
> > > +++ b/Silicon/NXP/iMX6Pkg/AcpiTables/Tpm2.aslc
> > > @@ -0,0 +1,53 @@
> > > +/** @file
> > > +*
> > > +*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
> > > +*
> > > +*  This program and the accompanying materials
> > > +*  are licensed and made available under the terms and conditions of the BSD
> > License
> > > +*  which accompanies this distribution.  The full text of the license may be
> > found at
> > > +*
> > https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> > urce.org%2Flicenses%2Fbsd-
> > license.php&amp;data=02%7C01%7CChristopher.Co%40microsoft.com%7C57
> > e13226930b4a6c5cd608d66410ce26%7C72f988bf86f141af91ab2d7cd011db
> > 47%7C1%7C0%7C636806420682788911&amp;sdata=X8SsmiEyzcOlu%2BLhD
> > EV%2Bvfh3NkYNT9LE%2FNZxheiBPEo%3D&amp;reserved=0
> > > +*
> > > +*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > BASIS,
> > > +*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> > EXPRESS OR IMPLIED.
> > > +*
> > > +**/
> > > +
> > > +#include <IndustryStandard/Tpm2Acpi.h>
> > > +
> > > +#include <Library/PcdLib.h>
> > > +
> > > +#include <Platform.h>
> > > +#include "iMX6.h"
> > > +
> > > +// Definition is missing from MdePkg/Include/IndustryStandard/Tpm2Acpi.h
> > > +#ifdef
> > EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_IN
> > TERFACE_WITH_TREE
> > > +#error
> > "EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_I
> > NTERFACE_WITH_TREE is defined elsewhere."
> > > +#else
> > > +#define
> > EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_IN
> > TERFACE_WITH_TREE 9
> > > +#endif
> > > +
> > > +EFI_TPM2_ACPI_TABLE Tpm2Table = {
> > > +  {
> > > +
> > EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
> > > +    sizeof (EFI_TPM2_ACPI_TABLE),
> > > +    EFI_TPM2_ACPI_TABLE_REVISION,
> > > +    0,                          // Checksum will be updated at runtime
> > > +    EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
> > > +    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
> > > +    EFI_ACPI_OEM_REVISION,      // OEM revision number
> > > +    EFI_ACPI_CREATOR_ID,        // Creator vendor ID
> > > +    EFI_ACPI_CREATOR_REVISION,  // Creator revision number
> > > +  },
> > > +  0,                            // Flags
> > > +  FixedPcdGet64 (PcdTpm2AcpiBufferBase),  // Control Area
> > > +  // StartMethod
> > > +
> > EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_IN
> > TERFACE_WITH_TREE,
> > > +};
> > > +
> > > +VOID*
> > > +ReferenceAcpiTable (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return (VOID *)&Tpm2Table;
> > > +}
> >
> >
> > > --
> > > 2.16.2.gvfs.1.33.gf5370f1
> > >


^ permalink raw reply	[flat|nested] 75+ messages in thread

end of thread, other threads:[~2019-01-29 14:10 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-21  8:25 [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Chris Co
2018-09-21  8:25 ` [PATCH edk2-platforms 01/27] Platform/Microsoft: Add OpteeClientPkg dec Chris Co
2018-10-31 20:43   ` Leif Lindholm
2018-11-01 10:55     ` Sumit Garg
2018-11-02  0:41       ` Chris Co
2018-11-02  5:24         ` Sumit Garg
2018-11-02 23:55           ` Chris Co
2018-11-05 10:07             ` Sumit Garg
2018-11-06  1:53               ` Chris Co
2018-11-06 11:09                 ` Sumit Garg
2018-09-21  8:25 ` [PATCH edk2-platforms 02/27] Platform/Microsoft: Add SdMmc Dxe Driver Chris Co
2018-09-21  8:25 ` [PATCH edk2-platforms 04/27] Silicon/NXP: Add iMXPlatformPkg dec Chris Co
2018-09-21  8:25 ` [PATCH edk2-platforms 03/27] Platform/Microsoft: Add MsPkg Chris Co
2018-10-31 21:00   ` Leif Lindholm
2018-09-21  8:25 ` [PATCH edk2-platforms 05/27] Silicon/NXP: Add UART library support for i.MX platforms Chris Co
2018-11-01  8:59   ` Leif Lindholm
2018-11-02  1:46     ` Chris Co
2018-09-21  8:25 ` [PATCH edk2-platforms 06/27] Silicon/NXP: Add I2C " Chris Co
2018-11-01 17:53   ` Leif Lindholm
2018-09-21  8:25 ` [PATCH edk2-platforms 07/27] Silicon/NXP: Add i.MX display library support Chris Co
2018-11-01 18:05   ` Leif Lindholm
2018-11-29  0:55     ` Chris Co
2018-09-21  8:25 ` [PATCH edk2-platforms 08/27] Silicon/NXP: Add Virtual RTC support for i.MX platform Chris Co
2018-12-15 13:26   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 10/27] Silicon/NXP: Add iMX6Pkg dec Chris Co
2018-11-01 18:25   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 09/27] Silicon/NXP: Add headers for SoC-specific i.MX packages to use Chris Co
2018-11-01 18:20   ` Leif Lindholm
2018-12-01  0:22     ` Chris Co
2018-12-03  9:42       ` Leif Lindholm
2018-12-04  1:44         ` Chris Co
2018-12-04  9:33           ` Ard Biesheuvel
2018-12-04 12:22             ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 11/27] Silicon/NXP: Add i.MX6 SoC header files Chris Co
2018-12-13 17:11   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 12/27] Silicon/NXP: Add i.MX6 I/O MUX library Chris Co
2018-11-08 18:00   ` Leif Lindholm
2018-12-04  1:41     ` Chris Co
2018-09-21  8:26 ` [PATCH edk2-platforms 13/27] Silicon/NXP: Add support for iMX SDHC Chris Co
2018-12-05 10:31   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 14/27] Silicon/NXP: Add i.MX6 GPT and EPIT timer headers Chris Co
2018-11-08 18:14   ` Leif Lindholm
2018-12-04  2:06     ` Chris Co
2018-12-04 12:58       ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 15/27] Silicon/NXP: Add i.MX6 GPT Timer library Chris Co
2018-12-13 17:26   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 16/27] Silicon/NXP: Add i.MX6 Timer DXE driver Chris Co
2018-12-13 17:33   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 17/27] Silicon/NXP: Add i.MX6 USB Phy Library Chris Co
2018-12-14 17:10   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library Chris Co
2018-12-14 18:12   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 19/27] Silicon/NXP: Add i.MX6 ACPI tables Chris Co
2018-12-14 19:53   ` Leif Lindholm
2018-12-17 11:14   ` Ard Biesheuvel
2019-01-08 21:43     ` Chris Co
2019-01-29 14:09       ` Ard Biesheuvel
2018-09-21  8:26 ` [PATCH edk2-platforms 20/27] Silicon/NXP: Add i.MX6 Board init library Chris Co
2018-12-14 20:12   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 21/27] Silicon/NXP: Add i.MX6 PCIe DXE driver Chris Co
2018-12-14 21:59   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 23/27] Silicon/NXP: Add i.MX6 Smbios Driver Chris Co
2018-12-14 23:07   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver Chris Co
2018-12-14 22:37   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 24/27] Silicon/NXP: Add i.MX6 common dsc and fdf files Chris Co
2018-12-14 23:36   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 25/27] Platform/Solidrun: Add Hummingboard Peripheral Initialization Chris Co
2018-12-15 12:12   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 26/27] Platform/SolidRun: Add i.MX 6Quad Hummingboard Edge ACPI tables Chris Co
2018-12-15 12:19   ` Leif Lindholm
2018-09-21  8:26 ` [PATCH edk2-platforms 27/27] Platform/Solidrun: Add i.MX 6Quad Hummingboard Edge dsc and fdf files Chris Co
2018-12-15 12:28   ` Leif Lindholm
2018-12-15 13:32 ` [PATCH edk2-platforms 00/27] Import Hummingboard Edge platform for Windows IoT Core Leif Lindholm
2018-12-19 18:28   ` Chris Co

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox