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 <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Leif Lindholm <[email protected]> Cc: Michael D Kinney <[email protected]> --- Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c | 163 ++++++++++++++++++++ Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf | 41 +++++ 2 files changed, 204 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..573f6c581a63 --- /dev/null +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMux.c @@ -0,0 +1,163 @@ +/** @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. +* +**/ + +#include <PiDxe.h> +#include <Library/IoLib.h> +#include <Library/DebugLib.h> + +#include <iMX6.h> +#include <iMX6IoMux.h> + +// +// Muxing functions +// + +VOID +ImxPadConfig ( + IMX_PAD Pad, + IMX_PADCFG PadConfig + ) +{ + _Static_assert( + (IOMUXC_SELECT_INPUT_UPPER_BOUND - IOMUXC_SELECT_INPUT_BASE_ADDRESS) < (0xff * 4), + "Too many SELECT_INPUT registers values to encode in IMX_PADCFG"); + + // + // 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 ( + char *SignalFriendlyName, + IMX_PAD Pad + ) +{ + IMX_IOMUXC_MUX_CTL muxCtl; + 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)); + + IMX_IOMUXC_PAD_CTL padCtl; + 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 ( + IMX_GPIO_BANK Bank, + UINT32 IoNumber, + IMX_GPIO_DIR Direction + ) +{ + volatile IMX_GPIO_REGISTERS *gpioRegisters = + (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE; + + ASSERT (IoNumber < 32); + + 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 ( + IMX_GPIO_BANK Bank, + UINT32 IoNumber, + IMX_GPIO_VALUE Value + ) +{ + volatile IMX_GPIO_REGISTERS *gpioRegisters = + (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE; + + ASSERT (IoNumber < 32); + + 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 ( + IMX_GPIO_BANK Bank, + UINT32 IoNumber + ) +{ + volatile IMX_GPIO_REGISTERS *gpioRegisters = + (IMX_GPIO_REGISTERS *) IMX_GPIO_BASE; + + ASSERT (IoNumber < 32); + + UINT32 Mask = (1 << IoNumber); + UINT32 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..8af5502be4d8 --- /dev/null +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6IoMuxLib/iMX6IoMuxLib.inf @@ -0,0 +1,41 @@ +## @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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = iMX6IoMuxLib + FILE_GUID = FA41BEF0-0666-4C07-9EC3-47F61C36EDBE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = iMX6IoMuxLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec + Silicon/NXP/iMX6Pkg/iMX6Pkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + IoLib + TimerLib + +[Sources.common] + iMX6IoMux.c + + [FixedPcd] + giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange -- 2.16.2.gvfs.1.33.gf5370f1 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

