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...@microsoft.com> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org> Cc: Leif Lindholm <leif.lindh...@linaro.org> Cc: Michael D Kinney <michael.d.kin...@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 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel