From: Jan Dąbroś jsd@semihalf.com
Spi master driver implements EFI_SPI_MASTER_PROTOCOL. It configures and manages SPI controller.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jan Dabros jsd@semihalf.com --- Documentation/Marvell/Drivers/SpiDriver.txt | 116 +++++++++ Documentation/Marvell/PortingGuide/Spi.txt | 15 ++ Drivers/Spi/SpiDxe.c | 376 ++++++++++++++++++++++++++++ Drivers/Spi/SpiDxe.h | 145 +++++++++++ Drivers/Spi/SpiDxe.inf | 73 ++++++ Platforms/Marvell/Marvell.dec | 5 + 6 files changed, 730 insertions(+) create mode 100644 Documentation/Marvell/Drivers/SpiDriver.txt create mode 100644 Documentation/Marvell/PortingGuide/Spi.txt create mode 100644 Drivers/Spi/SpiDxe.c create mode 100644 Drivers/Spi/SpiDxe.h create mode 100644 Drivers/Spi/SpiDxe.inf
diff --git a/Documentation/Marvell/Drivers/SpiDriver.txt b/Documentation/Marvell/Drivers/SpiDriver.txt new file mode 100644 index 0000000..fc323ef --- /dev/null +++ b/Documentation/Marvell/Drivers/SpiDriver.txt @@ -0,0 +1,116 @@ +1. Introduction +--------------- +**SpiDxe** driver implements EFI_SPI_MASTER_PROTOCOL in order to manage SPI +controller on Marvell A8k boards. It exposes below functionalities: + - create and setup SPI slaves + - raw transfer over SPI bus + +2. SpiDxe driver design +----------------------- + + 2.1 EFI_SPI_MASTER_PROTOCOL + ----------------------- + First member of SPI_MASTER protocol is Init function, implemented for SPI + master controller initialization. + + ->Init() + + // + //Initializes the host controller to execute SPI commands. + // + + param[IN] This Pointer to the EFI_SPI_MASTER_PROTOCOL instance + + return EFI_SUCCESS Opcode initialization on the SPI host + controller completed. + return EFI_ACCESS_DENIED The SPI configuration interface is + locked. + return EFI_OUT_OF_RESOURCES Not enough resource available to + initialize the device. + return EFI_DEVICE_ERROR Device error, operation failed. + + ******** + + SPI devices (slaves) do not support any kind of automatic discovery or + enumaration, so every device needs manual configuration, which may be done + with SetupDevice function. + + ->SetupDevice() + + // + //Allocate and zero all fields in the SPI_DEVICE struct. Set the chip + //select, max frequency and transfer mode supported by slave device. + // + + param[IN] Cs Chip select ID of the slave chip. + param[IN] MaxFreq Maximum SCK rate in Hz. + param[IN] Mode Clock polarity and clock phase. + + return *SPI_DEVICE Pointer to new allocated struct SPI_DEVICE. + return NULL NULL pointer if any eroor occured. + + ******** + + Developers have to destroy all created SPI device structs (with FreeDevice + function) in order to prevent from memory leak. + + ->FreeDevice() + + // + //Free any memory associated with a SPI device. + // + + param[in] SpiDev Pointer to the SPI_DEVICE struct. + + return EFI_SUCCESS Memory fried succesfully. + return EFI_DEVICE_ERROR Device error, operation failed. + + ******** + + Transfer function allows write/read raw bytes over SPI bus. + + ->Transfer() + + // + //Perform transfer over SPI bus + // + param[in] This Pointer to the EFI_SPI_MASTER_PROTOCOL + instance. + param[in] Slave Pointer to the SPI_DEVICE struct. + param[in] DataByteCount Number of bytes in the data portion of + the SPI cycle. + param[in] DataOut Pointer to caller-allocated buffer + containing the data to send. + param[out] DataIn Pointer to caller-allocated buffer + where received data will be placed. + param[in] Flag Flags which indicate state of CS line + during/after transfer (see file + Drivers/Spi/Devices/A8kSpiFlash.h) + + return EFI_SUCCESS Memory fried succesfully. + return EFI_DEVICE_ERROR Device error, operation failed. + + ********* + + When working with SPI devices it is often necessary to perform "command and + address" transactions. It may be done via ReadWrite function. + + ->ReadWrite() + + // + //Perform two steps transactions. First write Command, then read/write + //buffer + // + + param[in] This Pointer to the EFI_SPI_MASTER_PROTOCOL + instance. + param[in] Slave Pointer to the SPI_DEVICE struct. + param[in] Cmd Pointer to caller-allocated buffer + containing the command to send. + param[in] CmdSize Size of command (in bytes). + param[in] DataOut Pointer to caller-allocated buffer + containing the data to send. + param[out] DataIn Pointer to caller-allocated buffer + where received data will be placed. + param[in] DataSize Number of bytes in the data portion of + the SPI cycle. diff --git a/Documentation/Marvell/PortingGuide/Spi.txt b/Documentation/Marvell/PortingGuide/Spi.txt new file mode 100644 index 0000000..f1f36ad --- /dev/null +++ b/Documentation/Marvell/PortingGuide/Spi.txt @@ -0,0 +1,15 @@ +Spi driver configuration +------------------------ +Following PCDs are available for configuration of spi driver: + + gMarvellTokenSpaceGuid.PcdSpiClockFrequency + +Frequency (in Hz) of SPI clock + + gMarvellTokenSpaceGuid.PcdSpiMaxFrequency + +Max SCLK line frequency (in Hz) (max transfer frequency) + + gMarvellTokenSpaceGuid.PcdSpiDefaultMode + +default SCLK mode (see SPI_MODE enum in file OpenPlatformPkg/Drivers/Spi/MvSpi.h) diff --git a/Drivers/Spi/SpiDxe.c b/Drivers/Spi/SpiDxe.c new file mode 100644 index 0000000..53fcf2c --- /dev/null +++ b/Drivers/Spi/SpiDxe.c @@ -0,0 +1,376 @@ +/******************************************************************************* +Copyright (C) 2016 Marvell International Ltd. + +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "SpiDxe.h" + +SPI_MASTER *mSpiMasterInstance; + +STATIC +EFI_STATUS +SpiSetBaudRate ( + IN UINT32 CpuClock, + IN UINT32 MaxFreq + ) +{ + UINT32 Spr, BestSpr, Sppr, BestSppr, ClockDivider, Match, Reg, MinBaudDiff; + UINTN SpiRegBase = PcdGet32 (PcdSpiRegBase); + + MinBaudDiff = 0xFFFFFFFF; + //Spr is in range 1-15 and Sppr in range 0-8 + for (Spr = 1; Spr <= 15; Spr++) { + for (Sppr = 0; Sppr <= 7; Sppr++) { + ClockDivider = Spr * (1 << Sppr); + + if ((CpuClock / ClockDivider) > MaxFreq) { + continue; + } + + if ((CpuClock / ClockDivider) == MaxFreq) { + BestSpr = Spr; + BestSppr = Sppr; + Match = 1; + break; + } + + if ((MaxFreq - (CpuClock / ClockDivider)) < MinBaudDiff) { + MinBaudDiff = (MaxFreq - (CpuClock / ClockDivider)); + BestSpr = Spr; + BestSppr = Sppr; + } + } + + if (Match == 1) { + break; + } + } + + if (BestSpr == 0) { + return (EFI_INVALID_PARAMETER); + } + + Reg = MmioRead32 (SpiRegBase + SPI_CONF_REG); + Reg &= ~(SPI_SPR_MASK | SPI_SPPR_0_MASK | SPI_SPPR_HI_MASK); + Reg |= (BestSpr << SPI_SPR_OFFSET) | + ((BestSppr & 0x1) << SPI_SPPR_0_OFFSET) | + ((BestSppr >> 1) << SPI_SPPR_HI_OFFSET); + MmioWrite32 (SpiRegBase + SPI_CONF_REG, Reg); + + return EFI_SUCCESS; +} + +STATIC +VOID +SpiSetCs ( + UINT8 CsId + ) +{ + UINT32 Reg, SpiRegBase = PcdGet32 (PcdSpiRegBase); + + Reg = MmioRead32 (SpiRegBase + SPI_CTRL_REG); + Reg &= ~SPI_CS_NUM_MASK; + Reg |= (CsId << SPI_CS_NUM_OFFSET); + MmioWrite32 (SpiRegBase + SPI_CTRL_REG, Reg); +} + +STATIC +VOID +SpiActivateCs ( + UINT8 IN CsId + ) +{ + UINT32 Reg, SpiRegBase = PcdGet32 (PcdSpiRegBase); + + SpiSetCs(CsId); + Reg = MmioRead32 (SpiRegBase + SPI_CTRL_REG); + Reg |= SPI_CS_EN_MASK; + MmioWrite32(SpiRegBase + SPI_CTRL_REG, Reg); +} + +STATIC +VOID +SpiDeactivateCs ( + VOID + ) +{ + UINT32 Reg, SpiRegBase = PcdGet32 (PcdSpiRegBase); + + Reg = MmioRead32 (SpiRegBase + SPI_CTRL_REG); + Reg &= ~SPI_CS_EN_MASK; + MmioWrite32(SpiRegBase + SPI_CTRL_REG, Reg); +} + +STATIC +VOID +SpiSetupTransfer ( + IN EFI_SPI_MASTER_PROTOCOL *This, + IN SPI_DEVICE *Slave + ) +{ + SPI_MASTER *SpiMaster; + UINT32 Reg, SpiRegBase, CoreClock, SpiMaxFreq; + + SpiMaster = SPI_MASTER_FROM_SPI_MASTER_PROTOCOL (This); + + // Initialize values from PCDs + SpiRegBase = PcdGet32 (PcdSpiRegBase); + CoreClock = PcdGet32 (PcdSpiClockFrequency); + SpiMaxFreq = PcdGet32 (PcdSpiMaxFrequency); + + EfiAcquireLock (&SpiMaster->Lock); + + Reg = MmioRead32 (SpiRegBase + SPI_CONF_REG); + Reg |= SPI_BYTE_LENGTH; + MmioWrite32 (SpiRegBase + SPI_CONF_REG, Reg); + + SpiSetCs(Slave->Cs); + + SpiSetBaudRate (CoreClock, SpiMaxFreq); + + Reg = MmioRead32 (SpiRegBase + SPI_CONF_REG); + Reg &= ~(SPI_CPOL_MASK | SPI_CPHA_MASK | SPI_TXLSBF_MASK | SPI_RXLSBF_MASK); + + switch (Slave->Mode) { + case SPI_MODE0: + break; + case SPI_MODE1: + Reg |= SPI_CPHA_MASK; + break; + case SPI_MODE2: + Reg |= SPI_CPOL_MASK; + break; + case SPI_MODE3: + Reg |= SPI_CPOL_MASK; + Reg |= SPI_CPHA_MASK; + break; + } + + MmioWrite32 (SpiRegBase + SPI_CONF_REG, Reg); + + EfiReleaseLock (&SpiMaster->Lock); +} + +EFI_STATUS +EFIAPI +EfiSpiTransfer ( + IN EFI_SPI_MASTER_PROTOCOL *This, + IN SPI_DEVICE *Slave, + IN UINTN DataByteCount, + IN VOID *DataOut, + IN VOID *DataIn, + IN UINTN Flag + ) +{ + SPI_MASTER *SpiMaster; + UINT64 Length; + UINT32 Iterator, Reg, SpiRegBase; + UINT8 *DataOutPtr = (UINT8 *)DataOut; + UINT8 *DataInPtr = (UINT8 *)DataIn; + UINT8 DataToSend = 0; + + SpiMaster = SPI_MASTER_FROM_SPI_MASTER_PROTOCOL (This); + + SpiRegBase = PcdGet32 (PcdSpiRegBase); + + Length = 8 * DataByteCount; + + EfiAcquireLock (&SpiMaster->Lock); + + if (Flag & SPI_TRANSFER_BEGIN) { + SpiActivateCs (Slave->Cs); + } + + // Set 8-bit mode + Reg = MmioRead32 (SpiRegBase + SPI_CONF_REG); + Reg &= ~SPI_BYTE_LENGTH; + MmioWrite32 (SpiRegBase + SPI_CONF_REG, Reg); + + while (Length > 0) { + if (DataOut != NULL) { + DataToSend = *DataOutPtr & 0xFF; + } + // Transmit Data + MmioWrite32 (SpiRegBase + SPI_DATA_OUT_REG, DataToSend); + // Wait for memory ready + for (Iterator = 0; Iterator < SPI_TIMEOUT; Iterator++) { + if ((MmioRead32 (SpiRegBase + SPI_CTRL_REG) & SPI_MEM_READY_MASK) != 0) { + *DataInPtr = MmioRead32 (SpiRegBase + SPI_DATA_IN_REG); + + if (DataInPtr != NULL) { + DataInPtr++; + } + if (DataOutPtr != NULL) { + DataOutPtr++; + } + Length -= 8; + break; + } + } + + if (Iterator >= SPI_TIMEOUT) { + DEBUG ((DEBUG_ERROR, "Timeout\n")); + } + } + + if (Flag & SPI_TRANSFER_END) { + SpiDeactivateCs (); + } + + EfiReleaseLock (&SpiMaster->Lock); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +EfiSpiReadWrite ( + IN EFI_SPI_MASTER_PROTOCOL *This, + IN SPI_DEVICE *Slave, + IN UINT8 *Cmd, + IN UINTN CmdSize, + IN UINT8 *DataOut, + OUT UINT8 *DataIn, + IN UINTN DataSize + ) +{ + EFI_STATUS Status; + + Status = EfiSpiTransfer (This, Slave, CmdSize, Cmd, NULL, SPI_TRANSFER_BEGIN); + if (EFI_ERROR (Status)) { + Print (L"Spi Transfer Error\n"); + return EFI_DEVICE_ERROR; + } + + Status = EfiSpiTransfer (This, Slave, DataSize, DataOut, DataIn, SPI_TRANSFER_END); + if (EFI_ERROR (Status)) { + Print (L"Spi Transfer Error\n"); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +EfiSpiInit ( + IN EFI_SPI_MASTER_PROTOCOL * This + ) +{ + + return EFI_SUCCESS; +} + +SPI_DEVICE * +EFIAPI +EfiSpiSetupSlave ( + IN EFI_SPI_MASTER_PROTOCOL *This, + IN UINTN Cs, + IN SPI_MODE Mode + ) +{ + SPI_DEVICE *Slave; + + Slave = AllocateZeroPool (sizeof(SPI_DEVICE)); + if (Slave == NULL) { + DEBUG((DEBUG_ERROR, "Cannot allocate memory\n")); + return NULL; + } + + Slave->Cs = Cs; + Slave->Mode = Mode; + + SpiSetupTransfer (This, Slave); + + return Slave; +} + +EFI_STATUS +EFIAPI +EfiSpiFreeSlave ( + IN SPI_DEVICE *Slave + ) +{ + FreePool (Slave); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SpiMasterInitProtocol ( + IN EFI_SPI_MASTER_PROTOCOL *SpiMasterProtocol + ) +{ + + SpiMasterProtocol->Init = EfiSpiInit; + SpiMasterProtocol->SetupDevice = EfiSpiSetupSlave; + SpiMasterProtocol->FreeDevice = EfiSpiFreeSlave; + SpiMasterProtocol->Transfer = EfiSpiTransfer; + SpiMasterProtocol->ReadWrite = EfiSpiReadWrite; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SpiMasterEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + mSpiMasterInstance = AllocateZeroPool (sizeof (SPI_MASTER)); + + if (mSpiMasterInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + EfiInitializeLock (&mSpiMasterInstance->Lock, TPL_NOTIFY); + + SpiMasterInitProtocol (&mSpiMasterInstance->SpiMasterProtocol); + + mSpiMasterInstance->Signature = SPI_MASTER_SIGNATURE; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &(mSpiMasterInstance->Handle), + &gEfiSpiMasterProtocolGuid, + &(mSpiMasterInstance->SpiMasterProtocol), + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (mSpiMasterInstance); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} diff --git a/Drivers/Spi/SpiDxe.h b/Drivers/Spi/SpiDxe.h new file mode 100644 index 0000000..dee0177 --- /dev/null +++ b/Drivers/Spi/SpiDxe.h @@ -0,0 +1,145 @@ +/******************************************************************************* +Copyright (C) 2016 Marvell International Ltd. + +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __SPI_MASTER_H__ +#define __SPI_MASTER_H__ + +#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Uefi/UefiBaseType.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/Spi.h> + +#define SPI_MASTER_SIGNATURE SIGNATURE_32 ('M', 'S', 'P', 'I') +#define SPI_MASTER_FROM_SPI_MASTER_PROTOCOL(a) CR (a, SPI_MASTER, SpiMasterProtocol, SPI_MASTER_SIGNATURE) + +// Marvell Flash Device Controller Registers +#define SPI_CTRL_REG (0x00) +#define SPI_CONF_REG (0x04) +#define SPI_DATA_OUT_REG (0x08) +#define SPI_DATA_IN_REG (0x0c) +#define SPI_INT_CAUSE_REG (0x10) + +// Serial Memory Interface Control Register Masks +#define SPI_CS_NUM_OFFSET 2 +#define SPI_CS_NUM_MASK (0x7 << SPI_CS_NUM_OFFSET) +#define SPI_MEM_READY_MASK (0x1 << 1) +#define SPI_CS_EN_MASK (0x1 << 0) + +// Serial Memory Interface Configuration Register Masks +#define SPI_BYTE_LENGTH_OFFSET 5 +#define SPI_BYTE_LENGTH (0x1 << SPI_BYTE_LENGTH_OFFSET) +#define SPI_CPOL_OFFSET 11 +#define SPI_CPOL_MASK (0x1 << SPI_CPOL_OFFSET) +#define SPI_CPHA_OFFSET 12 +#define SPI_CPHA_MASK (0x1 << SPI_CPHA_OFFSET) +#define SPI_TXLSBF_OFFSET 13 +#define SPI_TXLSBF_MASK (0x1 << SPI_TXLSBF_OFFSET) +#define SPI_RXLSBF_OFFSET 14 +#define SPI_RXLSBF_MASK (0x1 << SPI_RXLSBF_OFFSET) + +#define SPI_SPR_OFFSET 0 +#define SPI_SPR_MASK (0xf << SPI_SPR_OFFSET) +#define SPI_SPPR_0_OFFSET 4 +#define SPI_SPPR_0_MASK (0x1 << SPI_SPPR_0_OFFSET) +#define SPI_SPPR_HI_OFFSET 6 +#define SPI_SPPR_HI_MASK (0x3 << SPI_SPPR_HI_OFFSET) + +#define SPI_TRANSFER_BEGIN 0x01 // Assert CS before transfer +#define SPI_TRANSFER_END 0x02 // Deassert CS after transfers + +#define SPI_TIMEOUT 100000 + +typedef struct { + EFI_SPI_MASTER_PROTOCOL SpiMasterProtocol; + UINTN Signature; + EFI_HANDLE Handle; + EFI_LOCK Lock; +} SPI_MASTER; + +EFI_STATUS +EFIAPI +EfiSpiTransfer ( + IN EFI_SPI_MASTER_PROTOCOL *This, + IN SPI_DEVICE *Slave, + IN UINTN DataByteCount, + IN VOID *DataOut, + IN VOID *DataIn, + IN UINTN Flag + ); + +EFI_STATUS +EFIAPI +EfiSpiReadWrite ( + IN EFI_SPI_MASTER_PROTOCOL *This, + IN SPI_DEVICE *Slave, + IN UINT8 *Cmd, + IN UINTN CmdSize, + IN UINT8 *DataOut, + OUT UINT8 *DataIn, + IN UINTN DataSize + ); + +EFI_STATUS +EFIAPI +EfiSpiInit ( + IN EFI_SPI_MASTER_PROTOCOL * This + ); + +SPI_DEVICE * +EFIAPI +EfiSpiSetupSlave ( + IN EFI_SPI_MASTER_PROTOCOL * This, + IN UINTN Cs, + IN SPI_MODE Mode + ); + +EFI_STATUS +EFIAPI +EfiSpiFreeSlave ( + IN SPI_DEVICE *Slave + ); + +EFI_STATUS +EFIAPI +SpiMasterEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif // __SPI_MASTER_H__ diff --git a/Drivers/Spi/SpiDxe.inf b/Drivers/Spi/SpiDxe.inf new file mode 100644 index 0000000..70f1c1d --- /dev/null +++ b/Drivers/Spi/SpiDxe.inf @@ -0,0 +1,73 @@ +#/******************************************************************************* +#Copyright (C) 2016 Marvell International Ltd. +# +#Marvell BSD License Option +# +#If you received this File from Marvell, you may opt to use, redistribute and/or +#modify this File under the following licensing terms. +#Redistribution and use in source and binary forms, with or without modification, +#are permitted provided that the following conditions are met: +# +#* Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +#* Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +#* Neither the name of Marvell nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#*******************************************************************************/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SpiMasterDxe + FILE_GUID = c19dbc8a-f4f9-43b0-aee5-802e3ed03d15 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SpiMasterEntryPoint + +[Sources] + SpiDxe.c + SpiDxe.h + +[Packages] + MdePkg/MdePkg.dec + OpenPlatformPkg/Platforms/Marvell/Marvell.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiDriverEntryPoint + TimerLib + UefiLib + DebugLib + MemoryAllocationLib + +[FixedPcd] + gMarvellTokenSpaceGuid.PcdSpiRegBase + gMarvellTokenSpaceGuid.PcdSpiClockFrequency + gMarvellTokenSpaceGuid.PcdSpiMaxFrequency + +[Protocols] + gEfiSpiMasterProtocolGuid + +[Depex] + TRUE diff --git a/Platforms/Marvell/Marvell.dec b/Platforms/Marvell/Marvell.dec index ad90ffc..b0d7d9c 100644 --- a/Platforms/Marvell/Marvell.dec +++ b/Platforms/Marvell/Marvell.dec @@ -113,6 +113,11 @@ gMarvellTokenSpaceGuid.PcdI2cClockFrequency|0|UINT32|0x3000048 gMarvellTokenSpaceGuid.PcdI2cBaudRate|0|UINT32|0x3000049
+#SPI + gMarvellTokenSpaceGuid.PcdSpiRegBase|0|UINT32|0x3000051 + gMarvellTokenSpaceGuid.PcdSpiMaxFrequency|0|UINT32|0x30000052 + gMarvellTokenSpaceGuid.PcdSpiClockFrequency|0|UINT32|0x30000053 + [Protocols] gEfiEepromProtocolGuid = { 0xcd728a1f, 0x45b5, 0x4feb, { 0x98, 0xc8, 0x31, 0x3d, 0xa8, 0x11, 0x74, 0x62 }} gEfiSpiMasterProtocolGuid = { 0x23de66a3, 0xf666, 0x4b3e, { 0xaa, 0xa2, 0x68, 0x9b, 0x18, 0xae, 0x2e, 0x19 }}