From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::143; helo=mail-it1-x143.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it1-x143.google.com (mail-it1-x143.google.com [IPv6:2607:f8b0:4864:20::143]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id B1C6321959CB2 for ; Fri, 21 Dec 2018 03:09:14 -0800 (PST) Received: by mail-it1-x143.google.com with SMTP id z7so6280574iti.0 for ; Fri, 21 Dec 2018 03:09:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=vBUypNcMZMqADdz/LGJq9dC/8GVfVW5miEI42zzLZ+Q=; b=ZVv/D6S7YO+4nTHOrNnCosYa8Ob9ew9r2OOGEE6OOaOeJ/m9Oo8TlRTo9L03NA4NbQ qL+CVSj3gSsk8yu+bl8f9ane29lD+mOQK7cpYarVy/d+yqgn91UOFlR+8bkDTCxHM/mZ Z/veEdZrthEPql0eV76hdbVXQ9dG8VradFGuY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=vBUypNcMZMqADdz/LGJq9dC/8GVfVW5miEI42zzLZ+Q=; b=AMUJ6iOr7abNOYMmmCdfdC7zqhSFOlW/zz160hmF+cAkr5PqOrbTqyZGPEXUSOkRa1 pEXcBe719TS4upQpi6hPky34DtoLxkS8gk3I2HXdf+MISpV+RAk9Reu7vD5zbqUW9b8t M+7AlnmRFy2P6JJkkCc8fWEnMSzpvqfms1ZQum5VZ1WD79d3whRbQpY4idxX1TTwzePu ZD/EZQEPe153Mb77G/FRtw77qxTq3SobSxBugeMathVa5q65rWiPPuQnh4O6Ab2f09pj Vff8TRAViHjxtoabv+SSEwjhly6bt5NYKzlFRiKSt7mcQXFLgIBNsF1/GDRui/BfwXIP 3h5A== X-Gm-Message-State: AA+aEWa44/MFQZRaKayuWKOrSDagZGfIp2j7uzluKrveC/4Ncs0umYvn pKcTwqYlKh7EHywuVbcVD3Styi/t5NLbC+EQOvQXHA== X-Google-Smtp-Source: AFSGD/UpYpas/K/EqqcLEGml7w+YYmBUeexz6nx5EdPeu5ZtWG6R5OTiO+68OG85S3KEKM9+6zRvvmXoQNiHSO3NJGM= X-Received: by 2002:a05:660c:4b:: with SMTP id p11mr1668850itk.71.1545390552841; Fri, 21 Dec 2018 03:09:12 -0800 (PST) MIME-Version: 1.0 References: <1518771035-6733-1-git-send-email-meenakshi.aggarwal@nxp.com> <1543417315-5763-1-git-send-email-meenakshi.aggarwal@nxp.com> <1543417315-5763-37-git-send-email-meenakshi.aggarwal@nxp.com> In-Reply-To: <1543417315-5763-37-git-send-email-meenakshi.aggarwal@nxp.com> From: Ard Biesheuvel Date: Fri, 21 Dec 2018 12:09:00 +0100 Message-ID: To: Meenakshi Aggarwal Cc: Leif Lindholm , "Kinney, Michael D" , "edk2-devel@lists.01.org" , Udit Kumar , Varun Sethi , Vabhav Subject: Re: [PATCH edk2-platforms 36/41] Silicon/NXP: Implement EFI_CPU_IO2_PROTOCOL X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Dec 2018 11:09:15 -0000 Content-Type: text/plain; charset="UTF-8" On Wed, 28 Nov 2018 at 10:16, Meenakshi Aggarwal wrote: > > From: Vabhav > > NXP SOC has mutiple PCIe RCs,Adding respective implementation of > EFI_CPU_IO2_PROTOCOL to provide Memory Space Read/Write functions > used by generic Host Bridge Driver including correct value for > the translation offset during MMIO accesses > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Vabhav > Signed-off-by: Meenakshi Aggarwal > --- > Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 633 ++++++++++++++++++++++ > Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 49 ++ > 2 files changed, 682 insertions(+) > create mode 100644 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c > create mode 100644 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf > > diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c > new file mode 100644 > index 0000000..b5c175b > --- /dev/null > +++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c > @@ -0,0 +1,633 @@ > +/** @file > + Produces the CPU I/O 2 Protocol. > + > + Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
> + Copyright (c) 2016, Linaro Ltd. 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 > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define MAX_IO_PORT_ADDRESS PCI_SEG_PORTIO_LIMIT > + > +// > +// Handle for the CPU I/O 2 Protocol > +// > +STATIC EFI_HANDLE mHandle; > + > +// > +// Lookup table for increment values based on transfer widths > +// > +STATIC CONST UINT8 mInStride[] = { > + 1, // EfiCpuIoWidthUint8 > + 2, // EfiCpuIoWidthUint16 > + 4, // EfiCpuIoWidthUint32 > + 8, // EfiCpuIoWidthUint64 > + 0, // EfiCpuIoWidthFifoUint8 > + 0, // EfiCpuIoWidthFifoUint16 > + 0, // EfiCpuIoWidthFifoUint32 > + 0, // EfiCpuIoWidthFifoUint64 > + 1, // EfiCpuIoWidthFillUint8 > + 2, // EfiCpuIoWidthFillUint16 > + 4, // EfiCpuIoWidthFillUint32 > + 8 // EfiCpuIoWidthFillUint64 > +}; > + > +// > +// Lookup table for increment values based on transfer widths > +// > +STATIC CONST UINT8 mOutStride[] = { > + 1, // EfiCpuIoWidthUint8 > + 2, // EfiCpuIoWidthUint16 > + 4, // EfiCpuIoWidthUint32 > + 8, // EfiCpuIoWidthUint64 > + 1, // EfiCpuIoWidthFifoUint8 > + 2, // EfiCpuIoWidthFifoUint16 > + 4, // EfiCpuIoWidthFifoUint32 > + 8, // EfiCpuIoWidthFifoUint64 > + 0, // EfiCpuIoWidthFillUint8 > + 0, // EfiCpuIoWidthFillUint16 > + 0, // EfiCpuIoWidthFillUint32 > + 0 // EfiCpuIoWidthFillUint64 > +}; > + > +/** > + Check parameters to a CPU I/O 2 Protocol service request. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. > + > + @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[in] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The parameters for this request pass the checks. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +CpuIoCheckParameter ( > + IN BOOLEAN MmioOperation, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + UINT64 MaxCount; > + UINT64 Limit; > + > + // > + // Check to see if Buffer is NULL > + // > + if (Buffer == NULL) { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check to see if Width is in the valid range > + // > + if ((UINT32)Width >= EfiCpuIoWidthMaximum) { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // For FIFO type, the target address won't increase during the access, > + // so treat Count as 1 > + // > + if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { > + Count = 1; > + } > + > + // > + // Check to see if Width is in the valid range for I/O Port operations > + // > + Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); > + if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check to see if Address is aligned > + // > + if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + > + // > + // Check to see if any address associated with this transfer exceeds the maximum > + // allowed address. The maximum address implied by the parameters passed in is > + // Address + Size * Count. If the following condition is met, then the transfer > + // is not supported. > + // > + // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1 > + // > + // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count > + // can also be the maximum integer value supported by the CPU, this range > + // check must be adjusted to avoid all oveflow conditions. > + // > + Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); > + if (Count == 0) { > + if (Address > Limit) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + } else { > + MaxCount = RShiftU64 (Limit, Width); > + if (MaxCount < (Count - 1)) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + } > + > + // > + // Check to see if Buffer is aligned > + // > + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Reads memory-mapped registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[out] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuMemoryServiceRead ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + // > + // Make sure the parameters are valid > + // > + Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((Address >= (PCI_SEG0_MMIO32_MIN + PCI_SEG0_MMIO_OFFSET)) && > + (Address <= (PCI_SEG0_MMIO32_MAX + PCI_SEG0_MMIO_OFFSET))) { > + Address += PCI_SEG0_MMIO_MEMBASE - PCI_SEG0_MMIO_OFFSET; > + } else if ((Address >= (PCI_SEG1_MMIO32_MIN + PCI_SEG1_MMIO_OFFSET)) && > + (Address <= (PCI_SEG1_MMIO32_MAX + PCI_SEG1_MMIO_OFFSET))) { > + Address += PCI_SEG1_MMIO_MEMBASE - PCI_SEG1_MMIO_OFFSET; > + } else if ((Address >= (PCI_SEG2_MMIO32_MIN + PCI_SEG2_MMIO_OFFSET)) && > + (Address <= (PCI_SEG2_MMIO32_MAX + PCI_SEG2_MMIO_OFFSET))) { > + Address += PCI_SEG2_MMIO_MEMBASE - PCI_SEG2_MMIO_OFFSET; > + } else if ((Address >= (PCI_SEG3_MMIO32_MIN + PCI_SEG3_MMIO_OFFSET)) && > + (Address <= (PCI_SEG3_MMIO32_MAX + PCI_SEG3_MMIO_OFFSET))) { > + Address += PCI_SEG3_MMIO_MEMBASE - PCI_SEG3_MMIO_OFFSET; > + } else { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + Please put this in a helper function instead of duplicating it. > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + *Uint8Buffer = MmioRead8 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint64) { > + *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); > + } > + } > + return EFI_SUCCESS; > +} > + > +/** > + Writes memory-mapped registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[in] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuMemoryServiceWrite ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + // > + // Make sure the parameters are valid > + // > + Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((Address >= (PCI_SEG0_MMIO32_MIN + PCI_SEG0_MMIO_OFFSET)) && > + (Address <= (PCI_SEG0_MMIO32_MAX + PCI_SEG0_MMIO_OFFSET))) { > + Address += PCI_SEG0_MMIO_MEMBASE - PCI_SEG0_MMIO_OFFSET; > + } else if ((Address >= (PCI_SEG1_MMIO32_MIN + PCI_SEG1_MMIO_OFFSET)) && > + (Address <= (PCI_SEG1_MMIO32_MAX + PCI_SEG1_MMIO_OFFSET))) { > + Address += PCI_SEG1_MMIO_MEMBASE - PCI_SEG1_MMIO_OFFSET; > + } else if ((Address >= (PCI_SEG2_MMIO32_MIN + PCI_SEG2_MMIO_OFFSET)) && > + (Address <= (PCI_SEG2_MMIO32_MAX + PCI_SEG2_MMIO_OFFSET))) { > + Address += PCI_SEG2_MMIO_MEMBASE - PCI_SEG2_MMIO_OFFSET; > + } else if ((Address >= (PCI_SEG3_MMIO32_MIN + PCI_SEG3_MMIO_OFFSET)) && > + (Address <= (PCI_SEG3_MMIO32_MAX + PCI_SEG3_MMIO_OFFSET))) { > + Address += PCI_SEG3_MMIO_MEMBASE - PCI_SEG3_MMIO_OFFSET; > + } else { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); > + for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + MmioWrite8 ((UINTN)Address, *Uint8Buffer); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); > + } else if (OperationWidth == EfiCpuIoWidthUint64) { > + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); > + } > + } > + return EFI_SUCCESS; > +} > + > +/** > + Reads I/O registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[out] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuIoServiceRead ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + // > + // Make sure the parameters are valid > + // > + Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG0_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG0_PORTIO_OFFSET))) { > + Address += PCI_SEG0_PORTIO_MEMBASE - PCI_SEG0_PORTIO_OFFSET; > + } else if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG1_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG1_PORTIO_OFFSET))) { > + Address += PCI_SEG1_PORTIO_MEMBASE - PCI_SEG1_PORTIO_OFFSET; > + } else if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG2_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG2_PORTIO_OFFSET))) { > + Address += PCI_SEG2_PORTIO_MEMBASE - PCI_SEG2_PORTIO_OFFSET; > + } else if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG3_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG3_PORTIO_OFFSET))) { > + Address += PCI_SEG3_PORTIO_MEMBASE - PCI_SEG3_PORTIO_OFFSET; > + } else { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); > + > + for (Uint8Buffer = Buffer; Count > 0; > + Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + *Uint8Buffer = MmioRead8 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Write I/O registers. > + > + The I/O operations are carried out exactly as requested. The caller is responsible > + for satisfying any alignment and I/O width restrictions that a PI System on a > + platform might require. For example on some platforms, width requests of > + EfiCpuIoWidthUint64 do not work. > + > + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, > + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for > + each of the Count operations that is performed. > + > + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, > + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times on the same Address. > + > + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, > + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is > + incremented for each of the Count operations that is performed. The read or > + write operation is performed Count times from the first element of Buffer. > + > + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. > + @param[in] Width Signifies the width of the I/O or Memory operation. > + @param[in] Address The base address of the I/O operation. > + @param[in] Count The number of I/O operations to perform. The number of > + bytes moved is Width size * Count, starting at Address. > + @param[in] Buffer For read operations, the destination buffer to store the results. > + For write operations, the source buffer from which to write data. > + > + @retval EFI_SUCCESS The data was read from or written to the PI system. > + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. > + @retval EFI_INVALID_PARAMETER Buffer is NULL. > + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. > + @retval EFI_UNSUPPORTED The address range specified by Address, Width, > + and Count is not valid for this PI system. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +CpuIoServiceWrite ( > + IN EFI_CPU_IO2_PROTOCOL *This, > + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, > + IN UINT64 Address, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT8 InStride; > + UINT8 OutStride; > + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; > + UINT8 *Uint8Buffer; > + > + // > + // Make sure the parameters are valid > + // > + Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG0_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG0_PORTIO_OFFSET))) { > + Address += PCI_SEG0_PORTIO_MEMBASE - PCI_SEG0_PORTIO_OFFSET; > + } else if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG1_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG1_PORTIO_OFFSET))) { > + Address += PCI_SEG1_PORTIO_MEMBASE - PCI_SEG1_PORTIO_OFFSET; > + } else if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG2_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG2_PORTIO_OFFSET))) { > + Address += PCI_SEG2_PORTIO_MEMBASE - PCI_SEG2_PORTIO_OFFSET; > + } else if ((Address >= (PCI_SEG_PORTIO_MIN + PCI_SEG3_PORTIO_OFFSET)) && > + (Address <= (PCI_SEG_PORTIO_MAX + PCI_SEG3_PORTIO_OFFSET))) { > + Address += PCI_SEG3_PORTIO_MEMBASE - PCI_SEG3_PORTIO_OFFSET; > + } else { > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Select loop based on the width of the transfer > + // > + InStride = mInStride[Width]; > + OutStride = mOutStride[Width]; > + OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); > + > + for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; > + Address += InStride, Uint8Buffer += OutStride, Count--) { > + if (OperationWidth == EfiCpuIoWidthUint8) { > + MmioWrite8 ((UINTN)Address, *Uint8Buffer); > + } else if (OperationWidth == EfiCpuIoWidthUint16) { > + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); > + } else if (OperationWidth == EfiCpuIoWidthUint32) { > + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); > + } > + } > + > + return EFI_SUCCESS; > +} > + > +// > +// CPU I/O 2 Protocol instance > +// > +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 = { > + { > + CpuMemoryServiceRead, > + CpuMemoryServiceWrite > + }, > + { > + CpuIoServiceRead, > + CpuIoServiceWrite > + } > +}; > + > + > +/** > + The user Entry Point for module CpuIo2Dxe. The user code starts with this function. > + > + @param[in] ImageHandle The firmware allocated handle for the EFI image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully. > + @retval other Some error occurs when executing this entry point. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciCpuIo2Initialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid); > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &mHandle, > + &gEfiCpuIo2ProtocolGuid, &mCpuIo2, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + > + return Status; > +} > diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf > new file mode 100644 > index 0000000..7e958b1 > --- /dev/null > +++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf > @@ -0,0 +1,49 @@ > +## @file > +# Produces the CPU I/O 2 Protocol by using the services of the I/O Library. > +# > +# 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. > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = PciCpuIo2Dxe > + FILE_GUID = 7bff18d7-9aae-434b-9c06-f10a7e157eac > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = PciCpuIo2Initialize > + > +[Sources] > + PciCpuIo2Dxe.c > + > +[Packages] > + MdePkg/MdePkg.dec > + Silicon/NXP/NxpQoriqLs.dec > + > +[LibraryClasses] > + BaseLib > + DebugLib > + IoLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + > +[Pcd] > + gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr > + gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseAddr > + gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseAddr > + gNxpQoriqLsTokenSpaceGuid.PcdPciExp4BaseAddr > + gNxpQoriqLsTokenSpaceGuid.PcdNumPciController > + > +[Protocols] > + gEfiCpuIo2ProtocolGuid ## PRODUCES > + > +[Depex] > + TRUE > -- > 1.9.1 >