Skip to content

Commit

Permalink
ARM/JunoPkg: Adding SCMI MTL library
Browse files Browse the repository at this point in the history
This change adds a new Mailbox Transport Layer library for the Juno
platform. This library is required for ArmScmiDxe driver communication
with the SCP.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Girish Pathak <[email protected]>
Reviewed-by: Leif Lindholm <[email protected]>
  • Loading branch information
girishpathak authored and Leif Lindholm committed Apr 23, 2018
1 parent adf5023 commit b3b892d
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 4 deletions.
9 changes: 8 additions & 1 deletion Platform/ARM/JunoPkg/ArmJuno.dec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015, ARM Limited. All rights reserved.
# Copyright (c) 2013-2018, ARM Limited. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
Expand Down Expand Up @@ -46,3 +46,10 @@
# Juno Device Trees are loaded from NOR Flash
gArmJunoTokenSpaceGuid.PcdJunoFdtDevicePath|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/board.dtb"|VOID*|0x00000008

# MHU Register base used by SCMI Mailbox transport
gArmJunoTokenSpaceGuid.PcdArmMtlDoorBell|0x2B1F0000|UINT64|0x00000024

# ARM_JUNO_NON_SECURE_SRAM_BASE used by SCMI Mailbox transport
gArmJunoTokenSpaceGuid.PcdArmMtlMailBoxBase|0x2E000000|UINT64|0x00000025
gArmJunoTokenSpaceGuid.PcdArmMtlMailBoxSize|0x80|UINT32|0x00000026

5 changes: 4 additions & 1 deletion Platform/ARM/JunoPkg/ArmJuno.dsc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2017, ARM Limited. All rights reserved.
# Copyright (c) 2013-2018, ARM Limited. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
Expand Down Expand Up @@ -47,6 +47,9 @@
# USB Requirements
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf

# SCMI Mailbox Transport Layer
ArmMtlLib|Platform/ARM/JunoPkg/Library/ArmJunoMtlLib/ArmJunoMtlLib.inf

[LibraryClasses.common.SEC]
PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
Expand Down
8 changes: 6 additions & 2 deletions Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoMem.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @file
*
* Copyright (c) 2013-2015, ARM Limited. All rights reserved.
* Copyright (c) 2013-2018, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
Expand Down Expand Up @@ -107,7 +107,11 @@ ArmPlatformGetVirtualMemoryMap (
VirtualMemoryTable[++Index].PhysicalBase = ARM_JUNO_NON_SECURE_SRAM_BASE;
VirtualMemoryTable[Index].VirtualBase = ARM_JUNO_NON_SECURE_SRAM_BASE;
VirtualMemoryTable[Index].Length = ARM_JUNO_NON_SECURE_SRAM_SZ;
VirtualMemoryTable[Index].Attributes = CacheAttributes;
// This memory is shared between the application processor
// and the SCP. To avoid coherency problems, map it as uncached memory.
// NOTE: The attribute value is misleading, it indicates memory map type as
// an un-cached, un-buffered but allows buffering and reordering.
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;

// PCI Root Complex
VirtualMemoryTable[++Index].PhysicalBase = PcdGet64 (PcdPcieControlBaseAddress);
Expand Down
198 changes: 198 additions & 0 deletions Platform/ARM/JunoPkg/Library/ArmJunoMtlLib/ArmJunoMtlLib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/** @file
Copyright (c) 2017-2018, Arm Limited. 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.
System Control and Management Interface V1.0
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
DEN0056A_System_Control_and_Management_Interface.pdf
**/

#include <Uefi/UefiBaseType.h>
#include <Uefi/UefiSpec.h>
#include <Library/ArmLib.h>
#include <Library/ArmMtlLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h>

#include "ArmJunoMtlPrivateLib.h"

// Each channel has a shared mailbox and a doorbell register.
STATIC CONST MTL_CHANNEL Channels[NUM_CHANNELS] = {
// Low priority channel.
{
MTL_CHANNEL_TYPE_LOW,
(MTL_MAILBOX*)(MTL_MAILBOX_BASE),
DOORBELL_LOW
},
// High priority channel
{
MTL_CHANNEL_TYPE_HIGH,
(MTL_MAILBOX*)(MTL_MAILBOX_BASE + MTL_MAILBOX_HIGH_PRIORITY_OFFSET),
DOORBELL_HIGH
}
};

/** Wait until channel is free.
@param[in] Channel Pointer to a channel.
@param[in] TimeOutInMicroSeconds Time out in micro seconds.
@retval EFI_SUCCESS Channel is free.
@retval EFI_TIMEOUT Time out error.
**/
EFI_STATUS
MtlWaitUntilChannelFree (
IN MTL_CHANNEL *Channel,
IN UINTN TimeOutInMicroSeconds
)
{
while (TimeOutInMicroSeconds != 0) {
// If channel is free then we have received the reply.
if (Channel->MailBox->ChannelStatus == MTL_CHANNEL_FREE) {
return EFI_SUCCESS;
}
if (TimeOutInMicroSeconds < MTL_POLL_WAIT_TIME) {
gBS->Stall (TimeOutInMicroSeconds);
break;
}
// Wait for some arbitrary time.
gBS->Stall (MTL_POLL_WAIT_TIME);
TimeOutInMicroSeconds -= MTL_POLL_WAIT_TIME;
}

// No response from SCP.
if (Channel->MailBox->ChannelStatus != MTL_CHANNEL_FREE) {
ASSERT (FALSE);
return EFI_TIMEOUT;
}

return EFI_SUCCESS;
}

/** Return the address of the message payload.
@param[in] Channel Pointer to a channel.
@retval UINT32* Pointer to the payload.
**/
UINT32*
MtlGetChannelPayload (
IN MTL_CHANNEL *Channel
)
{
return Channel->MailBox->Payload;
}

/** Return pointer to a channel for the requested channel type.
@param[in] ChannelType ChannelType, Low or High priority channel.
MTL_CHANNEL_TYPE_LOW or
MTL_CHANNEL_TYPE_HIGH
@param[out] Channel Holds pointer to the channel.
@retval EFI_SUCCESS Pointer to channel is returned.
@retval EFI_UNSUPPORTED Requested channel type not supported.
**/
EFI_STATUS
MtlGetChannel (
IN MTL_CHANNEL_TYPE ChannelType,
OUT MTL_CHANNEL **Channel
)
{
if (ChannelType != MTL_CHANNEL_TYPE_LOW
&& ChannelType != MTL_CHANNEL_TYPE_HIGH) {
return EFI_UNSUPPORTED;
}

*Channel = (MTL_CHANNEL*)&Channels[ChannelType];

return EFI_SUCCESS;
}

/** Mark the channel busy and ring the doorbell.
@param[in] Channel Pointer to a channel.
@param[in] MessageHeader Message header.
@param[out] PayloadLength Message length.
@retval EFI_SUCCESS Message sent successfully.
@retval EFI_DEVICE_ERROR Channel is busy.
**/
EFI_STATUS
MtlSendMessage (
IN MTL_CHANNEL *Channel,
IN UINT32 MessageHeader,
OUT UINT32 PayloadLength
)
{
MTL_MAILBOX *MailBox = Channel->MailBox;

if (Channel->MailBox->ChannelStatus != MTL_CHANNEL_FREE) {
return EFI_DEVICE_ERROR;
}

// Mark the channel busy before ringing doorbell.
Channel->MailBox->ChannelStatus = MTL_CHANNEL_BUSY;
ArmDataSynchronizationBarrier ();

MailBox->Flags = MTL_POLL;
MailBox->MessageHeader = MessageHeader;

// Add length of message header.
MailBox->Length = PayloadLength + sizeof (MessageHeader);

// Ring the doorbell. It sets SET bit of the MHU register.
MmioWrite32 (
Channel->DoorBell.PhysicalAddress,
Channel->DoorBell.ModifyMask
);

return EFI_SUCCESS;
}

/** Wait for a response on a channel.
If channel is free after sending message, it implies SCP responded
with a response on the channel.
@param[in] Channel Pointer to a channel.
@retval EFI_SUCCESS Message received successfully.
@retval EFI_TIMEOUT Time out error.
**/
EFI_STATUS
MtlReceiveMessage (
IN MTL_CHANNEL *Channel,
OUT UINT32 *MessageHeader,
OUT UINT32 *PayloadLength
)
{
EFI_STATUS Status;

MTL_MAILBOX *MailBox = Channel->MailBox;

Status = MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}

*MessageHeader = MailBox->MessageHeader;

// Deduct message header length.
*PayloadLength = MailBox->Length - sizeof (*MessageHeader);

return EFI_SUCCESS;
}
39 changes: 39 additions & 0 deletions Platform/ARM/JunoPkg/Library/ArmJunoMtlLib/ArmJunoMtlLib.inf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#/** @file
# Copyright (c) 2017-2018, Arm Limited. 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 = 0x00010019
BASE_NAME = ArmJunoMtlLib
FILE_GUID = 21FB2D8F-C6C8-4B2C-A616-A30CB2FBA277
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = ArmMtlLib

[Sources.common]
ArmJunoMtlLib.c

[Packages]
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
MdePkg/MdePkg.dec
Platform/ARM/JunoPkg/ArmJuno.dec

[LibraryClasses]
ArmLib
DebugLib
IoLib
UefiBootServicesTableLib

[FixedPcd.common]
gArmJunoTokenSpaceGuid.PcdArmMtlDoorBell
gArmJunoTokenSpaceGuid.PcdArmMtlMailBoxBase
gArmJunoTokenSpaceGuid.PcdArmMtlMailBoxSize
94 changes: 94 additions & 0 deletions Platform/ARM/JunoPkg/Library/ArmJunoMtlLib/ArmJunoMtlPrivateLib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/** @file
Copyright (c) 2017-2018, Arm Limited. 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.
System Control and Management Interface V1.0
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
DEN0056A_System_Control_and_Management_Interface.pdf
Juno ARM Development Platform SoC
https://www.arm.com/files/pdf/
DDI0515D1a_juno_arm_development_platform_soc_trm.pdf
**/

#ifndef ARM_JUNO_MTL_PRIVATE_LIB_H_
#define ARM_JUNO_MTL_PRIVATE_LIB_H_

// Mailbox transport layer.
#define MTL_DOORBELL_MODIFY_MASK (0x00000001U)
#define MTL_DOORBELL_PRESERVE_MASK (~MTL_DOORBELL_MODIFY_MASK)

#define MTL_DOORBELL_BASE (FixedPcdGet64 (PcdArmMtlDoorBell))
#define MTL_MAILBOX_BASE (FixedPcdGet64 (PcdArmMtlMailBoxBase))
#define MTL_MAILBOX_SIZE (FixedPcdGet32 (PcdArmMtlMailBoxSize))

#define MTL_POLL 0
#define MTL_INTR 1

/* For Juno, the mailbox for high priority is non-trusted SRAM + 256.
NOTE: Below is not documented anywhere (yet)
The payload sizes are 128 bytes.
There are two channels:
Channel 0
- Agent (OS) to Platform (SCP) memory base: non-trusted SRAM + 0
- Platform (SCP) to Agent (OS) memory base: non-trusted SRAM + 128
- Doorbell (both directions): MHU, bit 0
Channel 1
- Agent (OS) to Platform (SCP) memory base: non-trusted SRAM + 256
- Platform (SCP) to Agent (OS) memory base: non-trusted SRAM + 384
- Doorbell (both directions): MHU, bit 0
*/
#define MTL_MAILBOX_HIGH_PRIORITY_OFFSET (MTL_MAILBOX_SIZE * 2)

// ARM MHU interrupt registers.
#define CPU_INTR_L_SET 0x108
#define CPU_INTR_H_SET 0x128

// MTL uses MHU interrupt registers for communication with the SCP.
#define MTL_DOORBELL_REGISTER_LOW (MTL_DOORBELL_BASE + CPU_INTR_L_SET)
#define MTL_DOORBELL_REGISTER_HIGH (MTL_DOORBELL_BASE + CPU_INTR_H_SET)

#define MTL_CHANNEL_BUSY 0
#define MTL_CHANNEL_FREE 1

// Response time out value on a MHU channel 20ms.
#define RESPONSE_TIMEOUT 20000

/* As per SCMI spec. as a agent UEFI(or OS) can access only two channels
(low or high priority) secure channel is only accessible
to ARM Trusted firmware. */
#define NUM_CHANNELS 2

/* Each channel must use a doorbell register to interrupt the SCP firmware.
on Juno these are MHU interrupt registers for low and high priority
channels. */
#define DOORBELL_LOW { \
MTL_DOORBELL_REGISTER_LOW, \
MTL_DOORBELL_MODIFY_MASK, \
MTL_DOORBELL_PRESERVE_MASK \
}

#define DOORBELL_HIGH { \
MTL_DOORBELL_REGISTER_HIGH, \
MTL_DOORBELL_MODIFY_MASK, \
MTL_DOORBELL_PRESERVE_MASK \
}

// Arbitarary poll time.
#define MTL_POLL_WAIT_TIME 100

#endif /* ARM_JUNO_MTL_PRIVATE_LIB_H_ */

0 comments on commit b3b892d

Please sign in to comment.