From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-io1-f67.google.com (mail-io1-f67.google.com [209.85.166.67]) by mx.groups.io with SMTP id smtpd.web10.29517.1590981700692141641 for ; Sun, 31 May 2020 20:21:40 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Nz7e9+tD; spf=pass (domain: gmail.com, ip: 209.85.166.67, mailfrom: andrey.warkentin@gmail.com) Received: by mail-io1-f67.google.com with SMTP id h4so2202692iob.10 for ; Sun, 31 May 2020 20:21:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=e3pXkDr8Q2S2pZwr3fmaTZCV6jbiIRFX8rBjSWitmyI=; b=Nz7e9+tDOj/s6OOBLvdd9l4qrKlXj0IDy77+/iviFSL9Fq4KYZ8LCn/E9f8V6c1iWC m+BH1/+IFjk/ZQD88jkJCLzSLglUQP8cWZVVCcgDL1Ye8q9mptAqGUcAOeCLLHHuxjpM W3x3dbzuu7KRU02eqdfxP7DDJpA6DmRgKfqrL8ORNmyYEy6egajik5b6ExKOy11uF0Jw 6Xp010Swp+JS7CkBIYSMybwC95DT6vkevUF67YaWeOXqRaMDSgNY6yOqTX+Whwh/2r/i IBHryuC0/5vqMiep2H3SOmlELwhUYeHKXOqii1s35Nl9gxW1ifek6WlDPwpXDqIfcbci ASxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=e3pXkDr8Q2S2pZwr3fmaTZCV6jbiIRFX8rBjSWitmyI=; b=mf1S7zKJgQIscNJ+9p+BbLB3cG0c10MbubPT5tq6qiQoex4airv5e53Gd9/mhPHqJh NGsEowXoxZneZsedtt3cObJz3r0k6NK01gR3xIRX+P57kpTsPmLNyrYmpB7SSBL1EYfg 6f7QvwNjmUH4oirr4cQndhESQ2iVwbhlKgKaDY5yKT3+drojzi92da4WJtw1Cb7LJFJA wckG16BmFHAE+pzpSJL5HL1xt8axUzcIKXVvT0l2fYIstAcF4Do56PiI5P6IH/xf7Ct1 TcIVi/CMUio6O8+yYirSl/laFdGulVr3bkjsk98dTsLNriF2JJVDc8Deq7kz3l3DTflt 3lpA== X-Gm-Message-State: AOAM531+3TdbWwtCuSz6FxvKDzowX/A0Yc5EevhEKH7PGG8KiBQbEJIt weQL1mKynHZ6OZiukp7YdUx21fRX X-Google-Smtp-Source: ABdhPJwbdWVwJYnDuPjpe+jMXbPswAWwM62KhIV6tYrafmWrIGNKDIS9V0JBhy4KHZRStRLab96mFg== X-Received: by 2002:a5d:8958:: with SMTP id b24mr17273759iot.53.1590981699648; Sun, 31 May 2020 20:21:39 -0700 (PDT) Return-Path: Received: from localhost.localdomain (c-98-214-99-181.hsd1.il.comcast.net. [98.214.99.181]) by smtp.gmail.com with ESMTPSA id i10sm8931205ilp.28.2020.05.31.20.21.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 31 May 2020 20:21:39 -0700 (PDT) From: "Andrei Warkentin" To: devel@edk2.groups.io Cc: ard.biesheuvel@arm.com, leif@nuviainc.com, pete@akeo.ie, philmd@redhat.com Subject: [edk2-platforms][PATCH 1/1] Pi4: notify VPU to load xHCI firmware before XhciDxe binds Date: Sun, 31 May 2020 20:21:30 -0700 Message-Id: <20200601032130.95634-1-andrey.warkentin@gmail.com> X-Mailer: git-send-email 2.17.1 Newer Pi 4 boards (such as 8GiB variant) no longer carry a SPI EEPROM with the VLI805 (USB) controller firmware. So, ask the VPU firmare to load the image it has into the controller specified by BDF. This is benign on non-8GiB boards (reloading that firmware if VPU fw is new enough or doing nothing on old VPU firmware). Tested on 4GB. Also have a positive test report for an 8GB board from a forum member. Signed-off-by: Andrei Warkentin --- Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 12 ++- Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.h | 22 +++++ Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf | 5 +- Platform/RaspberryPi/Drivers/ConfigDxe/XhciQuirk.c | 97 ++++++++++++++++++++ Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c | 58 +++++++++++- Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h | 3 + Platform/RaspberryPi/Include/Protocol/RpiFirmware.h | 10 ++ 7 files changed, 200 insertions(+), 7 deletions(-) diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c index ac1004fe..ad14eb3d 100644 --- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c +++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c @@ -1,7 +1,7 @@ /** @file * * Copyright (c) 2019 - 2020, ARM Limited. All rights reserved. - * Copyright (c) 2018 - 2019, Andrei Warkentin + * Copyright (c) 2018 - 2020, Andrei Warkentin * * SPDX-License-Identifier: BSD-2-Clause-Patent * @@ -11,21 +11,18 @@ #include #include #include -#include #include -#include #include #include #include #include #include #include -#include #include #include -#include #include #include "ConfigDxeFormSetGuid.h" +#include "ConfigDxe.h" #define FREQ_1_MHZ 1000000 @@ -584,5 +581,10 @@ ConfigInitialize ( NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent); ASSERT_EFI_ERROR (Status); + + if (mModelFamily == 4) { + RegisterXhciQuirkHandler (mFwProtocol); + } + return EFI_SUCCESS; } diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.h b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.h new file mode 100644 index 00000000..6e35fd95 --- /dev/null +++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.h @@ -0,0 +1,22 @@ +/** @file + * + * Copyright (c) 2020, Andrei Warkentin + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef _CONFIG_DXE_H_ +#define _CONFIG_DXE_H_ + +#include +#include +#include +#include +#include + +VOID RegisterXhciQuirkHandler ( + IN RASPBERRY_PI_FIRMWARE_PROTOCOL *FwProtocol + ); + +#endif /* _CONFIG_DXE_H_ */ diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf index f20f3bcc..b3ef2624 100644 --- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf +++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf @@ -3,7 +3,7 @@ # Component description file for the RasbperryPi DXE platform config driver. # # Copyright (c) 2019 - 2020, ARM Limited. All rights reserved. -# Copyright (c) 2018, Andrei Warkentin +# Copyright (c) 2018 - 2020, Andrei Warkentin # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -25,6 +25,7 @@ # [Sources] ConfigDxe.c + XhciQuirk.c ConfigDxeFormSetGuid.h ConfigDxeHii.vfr ConfigDxeHii.uni @@ -50,6 +51,7 @@ HiiLib NetLib PcdLib + UefiLib UefiBootServicesTableLib UefiDriverEntryPoint UefiRuntimeServicesTableLib @@ -62,6 +64,7 @@ gBcmGenetPlatformDeviceProtocolGuid ## PRODUCES gRaspberryPiFirmwareProtocolGuid ## CONSUMES gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES + gEfiPciIoProtocolGuid ## CONSUMES [FixedPcd] gRaspberryPiTokenSpaceGuid.PcdCpuLowSpeedMHz diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/XhciQuirk.c b/Platform/RaspberryPi/Drivers/ConfigDxe/XhciQuirk.c new file mode 100644 index 00000000..93ab5a35 --- /dev/null +++ b/Platform/RaspberryPi/Drivers/ConfigDxe/XhciQuirk.c @@ -0,0 +1,97 @@ +/** @file + * + * Copyright (c) 2020, Andrei Warkentin + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#include "ConfigDxe.h" +#include +#include +#include + +#pragma pack(1) +typedef struct { + UINT8 ProgInterface; + UINT8 SubClassCode; + UINT8 BaseCode; +} USB_CLASSC; +#pragma pack() + +STATIC VOID *mPciIoNotificationRegistration = NULL; + +STATIC +VOID +PciIoNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + USB_CLASSC UsbClassCReg; + UINTN SegmentNumber; + UINTN BusNumber; + UINTN DeviceNumber; + UINTN FunctionNumber; + RASPBERRY_PI_FIRMWARE_PROTOCOL *FwProtocol = Context; + + Status = gBS->LocateProtocol (&gEfiPciIoProtocolGuid, + mPciIoNotificationRegistration, (VOID **)&PciIo); + if (EFI_ERROR (Status)) { + return; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (USB_CLASSC) / sizeof (UINT8), + &UsbClassCReg + ); + + if (EFI_ERROR (Status)) { + return; + } + + // + // Test whether the controller belongs to Xhci type + // + if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || + (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) || + (UsbClassCReg.ProgInterface != PCI_IF_XHCI)) { + return; + } + + Status = PciIo->GetLocation (PciIo, &SegmentNumber, &BusNumber, + &DeviceNumber, &FunctionNumber); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: failed to get SBDF for xHCI controller: %r\n", + __FUNCTION__, Status)); + } + + DEBUG ((DEBUG_INFO, "xHCI found at %u:%u:%u:%u\n", + SegmentNumber, BusNumber, DeviceNumber, FunctionNumber)); + + ASSERT (SegmentNumber == 0); + Status = FwProtocol->NotifyXhciReset(BusNumber, DeviceNumber, FunctionNumber); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: couldn't signal xHCI firmware load: %r\n", + __FUNCTION__, Status)); + } +} + +VOID +RegisterXhciQuirkHandler ( + IN RASPBERRY_PI_FIRMWARE_PROTOCOL *FwProtocol + ) +{ + EfiCreateProtocolNotifyEvent ( + &gEfiPciIoProtocolGuid, + TPL_NOTIFY, + PciIoNotificationEvent, + FwProtocol, + &mPciIoNotificationRegistration + ); +} diff --git a/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c index 6c45cf47..22f75a52 100644 --- a/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c +++ b/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c @@ -2,7 +2,7 @@ * * Copyright (c) 2020, Pete Batard * Copyright (c) 2019, ARM Limited. All rights reserved. - * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) 2017-2020, Andrei Warkentin * Copyright (c) 2016, Linaro, Ltd. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent @@ -1237,6 +1237,61 @@ RpiFirmwareSetLed ( } } +#pragma pack() +typedef struct { + UINT32 DeviceAddress; +} RPI_FW_NOTIFY_XHCI_RESET_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_NOTIFY_XHCI_RESET_TAG TagBody; + UINT32 EndTag; +} RPI_FW_NOTIFY_XHCI_RESET_CMD; +#pragma pack() + +STATIC +EFI_STATUS +RpiFirmwareNotifyXhciReset ( + IN UINTN BusNumber, + IN UINTN DeviceNumber, + IN UINTN FunctionNumber + ) +{ + RPI_FW_NOTIFY_XHCI_RESET_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof (*Cmd)); + + Cmd->BufferHead.BufferSize = sizeof (*Cmd); + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_MBOX_NOTIFY_XHCI_RESET; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->TagBody.DeviceAddress = BusNumber << 20 | DeviceNumber << 15 | FunctionNumber << 12; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + } + + return Status; +} + STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = { RpiFirmwareSetPowerState, RpiFirmwareGetMacAddress, @@ -1259,6 +1314,7 @@ STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = { RpiFirmwareGetCpuName, RpiFirmwareGetArmMemory, RPiFirmwareGetModelInstalledMB, + RpiFirmwareNotifyXhciReset }; /** diff --git a/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h b/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h index 3328be58..71040689 100644 --- a/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h +++ b/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h @@ -1,6 +1,7 @@ /** @file * * Copyright (c) 2019-2020, Pete Batard + * Copyright (c) 2017-2020, Andrei Warkentin * Copyright (c) 2016, Linaro Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent @@ -61,6 +62,8 @@ #define RPI_MBOX_GET_MAX_CLOCK_RATE 0x00030004 #define RPI_MBOX_GET_MIN_CLOCK_RATE 0x00030007 +#define RPI_MBOX_NOTIFY_XHCI_RESET 0x00030058 + #define RPI_MBOX_SET_CLOCK_RATE 0x00038002 #define RPI_MBOX_SET_GPIO 0x00038041 diff --git a/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h b/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h index 108becbd..56a8d15a 100644 --- a/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h +++ b/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h @@ -1,6 +1,7 @@ /** @file * * Copyright (c) 2019, ARM Limited. All rights reserved. + * Copyright (c) 2017 - 2020, Andrei Warkentin * Copyright (c) 2016, Linaro Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent @@ -140,6 +141,14 @@ EFI_STATUS UINT32 *Size ); +typedef +EFI_STATUS +(EFIAPI *NOTIFY_XHCI_RESET) ( + UINTN BusNumber, + UINTN DeviceNumber, + UINTN FunctionNumber + ); + typedef struct { SET_POWER_STATE SetPowerState; GET_MAC_ADDRESS GetMacAddress; @@ -162,6 +171,7 @@ typedef struct { GET_CPU_NAME GetCpuName; GET_ARM_MEM GetArmMem; GET_MODEL_INSTALLED_MB GetModelInstalledMB; + NOTIFY_XHCI_RESET NotifyXhciReset; } RASPBERRY_PI_FIRMWARE_PROTOCOL; extern EFI_GUID gRaspberryPiFirmwareProtocolGuid; -- 2.17.1