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...@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
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 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel