From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@semihalf-com.20150623.gappssmtp.com header.s=20150623 header.b=OJFlvidW; spf=none, err=SPF record not found (domain: semihalf.com, ip: 209.85.167.67, mailfrom: mw@semihalf.com) Received: from mail-lf1-f67.google.com (mail-lf1-f67.google.com [209.85.167.67]) by groups.io with SMTP; Wed, 17 Apr 2019 11:06:18 -0700 Received: by mail-lf1-f67.google.com with SMTP id d12so2990394lfk.6 for ; Wed, 17 Apr 2019 11:06:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mO3ugI0ufm5szVjraoAnPzdltKVNiR0QyHMn6npAcDE=; b=OJFlvidWi9vxFw7qfrzYin0+VTA5dujiB7zP+LfmVpLUVbJ4lOhRI6fEIcEI3cvnVd DVxOibLDSAaw05FlNk7za0XzBbLPne89hbDEpRkwN/4OHI+XjjPBGDgrhi09z8ecfdSg A1jx5bh/eksvjoXWTOH3yY0y4tCPE8NMn2EVNbHuFKAn/21wIJc90UF4jKL0kl0tdh+y fWoIjGGr9moFycqZ2/QCQafwtR83wAbX6304IeyBR6w9FlTbcyJtpoFkaHBiXJ1Q3w5P +TfkU/K7zvB1jlNpNrUfebu0HEsO3XLb8LnkPTtYBNu/22jcWtiOasfVU86mwJu5YlUb N9Uw== 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:in-reply-to :references; bh=mO3ugI0ufm5szVjraoAnPzdltKVNiR0QyHMn6npAcDE=; b=nJyu3Sb7qocFWkxwCgBNIeXixIo0nH2UQQLMK2AXEielMrqxyeT6wIdYbuC/HZMvh3 c+JGWcI9fRMCRRLRbNV0LfqSs4irRI+qHGvFQxJxowilDw1XD+Tfig0mIvkUthtGSo5N i5Du01iti1HPk5XajYWxuz3wEdXSlpivzU86pTu/JFSenGFSVmcUKr9ufWRt9sLbZY6j N2REdLFhQMFjgV0EgKDJ2xP2WLgO/0bVgNfrhqeUh1mtUwvpTVzcjU27ZQWX7+awOECW 6yOdKsf/G4+zkE+X00XsEQPVFYl0IzBqS8blMroPYwIqdQcRICgPdp1Yqs7JWZ7bbQXn SvGg== X-Gm-Message-State: APjAAAWd1BBSC4fYcGVlDY2PyeRbqIfjNwQhokcm8srOdAy4KlIZkuuQ yZK+yvTHza+jQcdEFzmgQ2xMeE2XLfvlpQ== X-Google-Smtp-Source: APXvYqzI2TjdNEUYBEFiIOt2VZSaJfpR4SBEoh8b5AY6LDvFIrftt9KGXZMcRJcCKMnu92YGoyetdA== X-Received: by 2002:a19:ae0a:: with SMTP id f10mr46827098lfc.118.1555524375849; Wed, 17 Apr 2019 11:06:15 -0700 (PDT) Return-Path: Received: from gilgamesh.semihalf.com (31-172-191-173.noc.fibertech.net.pl. [31.172.191.173]) by smtp.gmail.com with ESMTPSA id r3sm11147375ljr.7.2019.04.17.11.06.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 17 Apr 2019 11:06:15 -0700 (PDT) From: "Marcin Wojtas" To: devel@edk2.groups.io Cc: leif.lindholm@linaro.org, ard.biesheuvel@linaro.org, nadavh@marvell.com, mw@semihalf.com, jsd@semihalf.com, jaz@semihalf.com, kostap@marvell.com, Jici.Gao@arm.com Subject: [edk2-platforms: PATCH 2/3] Marvell/Drivers: MvSpiOrionDxe: Keep clock enabled at runtime Date: Wed, 17 Apr 2019 20:05:55 +0200 Message-Id: <1555524356-1740-3-git-send-email-mw@semihalf.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1555524356-1740-1-git-send-email-mw@semihalf.com> References: <1555524356-1740-1-git-send-email-mw@semihalf.com> Linux MTD subsystem enables the SPI controller clock only when explicitly accessing the device. Because of that, using variables stored in the SPI flash could cause a hang when this clock remained disabled. Such issue was prevented when booting with the default DTB - see commit 124073e4d440 ("Marvell/Armada7k8k: DeviceTree: Use fixed clocks"). However in case someone wishes to try a different DTB, the issue can become problematic again. Fix above problem by enabling the clock when accessing SPI controller registers or mapped memory region AtRuntime. For this purpose add required callbacks to the SpiMaster and SpiFlash protocols that are called from MvFvbDxe driver. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Marcin Wojtas --- Silicon/Marvell/Marvell.dec | 3 + Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.inf | 3 + Silicon/Marvell/Include/Protocol/Spi.h | 10 ++++ Silicon/Marvell/Include/Protocol/SpiFlash.h | 7 +++ Silicon/Marvell/Drivers/Spi/MvFvbDxe/MvFvbDxe.c | 34 +++++++++++ Silicon/Marvell/Drivers/Spi/MvSpiFlashDxe/MvSpiFlashDxe.c | 11 ++++ Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.c | 63 +++++++++++++++++++- 7 files changed, 129 insertions(+), 2 deletions(-) diff --git a/Silicon/Marvell/Marvell.dec b/Silicon/Marvell/Marvell.dec index 7210ba2..201a62f 100644 --- a/Silicon/Marvell/Marvell.dec +++ b/Silicon/Marvell/Marvell.dec @@ -138,6 +138,9 @@ gMarvellTokenSpaceGuid.PcdI2cBusCount|0|UINT32|0x3000183 #SPI + gMarvellTokenSpaceGuid.PcdSpiClockFixed|TRUE|BOOLEAN|0x30000054 + gMarvellTokenSpaceGuid.PcdSpiClockMask|0|UINT32|0x30000055 + gMarvellTokenSpaceGuid.PcdSpiClockRegBase|0|UINT64|0x30000056 gMarvellTokenSpaceGuid.PcdSpiRegBase|0|UINT32|0x3000051 gMarvellTokenSpaceGuid.PcdSpiMemoryBase|0|UINT64|0x3000059 gMarvellTokenSpaceGuid.PcdSpiMaxFrequency|0|UINT32|0x30000052 diff --git a/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.inf b/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.inf index 4779371..1857484 100644 --- a/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.inf +++ b/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.inf @@ -59,7 +59,10 @@ UefiRuntimeLib [FixedPcd] + gMarvellTokenSpaceGuid.PcdSpiClockFixed gMarvellTokenSpaceGuid.PcdSpiClockFrequency + gMarvellTokenSpaceGuid.PcdSpiClockMask + gMarvellTokenSpaceGuid.PcdSpiClockRegBase gMarvellTokenSpaceGuid.PcdSpiMaxFrequency gMarvellTokenSpaceGuid.PcdSpiRegBase diff --git a/Silicon/Marvell/Include/Protocol/Spi.h b/Silicon/Marvell/Include/Protocol/Spi.h index abbad19..4d66f7f 100644 --- a/Silicon/Marvell/Include/Protocol/Spi.h +++ b/Silicon/Marvell/Include/Protocol/Spi.h @@ -54,6 +54,9 @@ typedef struct { UINT32 AddrSize; NOR_FLASH_INFO *Info; UINTN HostRegisterBaseAddress; + BOOLEAN HostClockFixed; + UINTN HostClockEnableRegister; + UINT32 HostClockEnableMask; UINTN CoreClock; } SPI_DEVICE; @@ -107,6 +110,12 @@ EFI_STATUS IN SPI_DEVICE *SpiDev ); +typedef +EFI_STATUS +(EFIAPI *MV_SPI_POWER_ON) ( + IN SPI_DEVICE *SpiDev + ); + struct _MARVELL_SPI_MASTER_PROTOCOL { MV_SPI_INIT Init; MV_SPI_READ_WRITE ReadWrite; @@ -114,6 +123,7 @@ struct _MARVELL_SPI_MASTER_PROTOCOL { MV_SPI_SETUP_DEVICE SetupDevice; MV_SPI_FREE_DEVICE FreeDevice; MV_SPI_CONFIG_RT ConfigRuntime; + MV_SPI_POWER_ON ControllerPowerOn; }; #endif // __MARVELL_SPI_MASTER_PROTOCOL_H__ diff --git a/Silicon/Marvell/Include/Protocol/SpiFlash.h b/Silicon/Marvell/Include/Protocol/SpiFlash.h index e703330..0336dda 100644 --- a/Silicon/Marvell/Include/Protocol/SpiFlash.h +++ b/Silicon/Marvell/Include/Protocol/SpiFlash.h @@ -102,6 +102,12 @@ EFI_STATUS IN UINTN EndPercentage ); +typedef +EFI_STATUS +(EFIAPI *MV_SPI_FLASH_POWER_ON) ( + IN SPI_DEVICE *SpiDev + ); + struct _MARVELL_SPI_FLASH_PROTOCOL { MV_SPI_FLASH_INIT Init; MV_SPI_FLASH_READ_ID ReadId; @@ -110,6 +116,7 @@ struct _MARVELL_SPI_FLASH_PROTOCOL { MV_SPI_FLASH_ERASE Erase; MV_SPI_FLASH_UPDATE Update; MV_SPI_FLASH_UPDATE_WITH_PROGRESS UpdateWithProgress; + MV_SPI_FLASH_POWER_ON FlashPowerOn; }; #endif // __MV_SPI_FLASH__ diff --git a/Silicon/Marvell/Drivers/Spi/MvFvbDxe/MvFvbDxe.c b/Silicon/Marvell/Drivers/Spi/MvFvbDxe/MvFvbDxe.c index cb006cd..b57f415 100644 --- a/Silicon/Marvell/Drivers/Spi/MvFvbDxe/MvFvbDxe.c +++ b/Silicon/Marvell/Drivers/Spi/MvFvbDxe/MvFvbDxe.c @@ -311,6 +311,11 @@ MvFvbGetAttributes ( FlashInstance = INSTANCE_FROM_FVB_THIS (This); + // Ensure proper access to the flash device from OS level + if (EfiAtRuntime ()) { + FlashInstance->SpiFlashProtocol->FlashPowerOn (&FlashInstance->SpiDevice); + } + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FlashInstance->RegionBaseAddress; FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2 *)&(FwVolHeader->Attributes); @@ -349,10 +354,18 @@ MvFvbSetAttributes ( EFI_FVB_ATTRIBUTES_2 OldAttributes; EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; + FVB_DEVICE *FlashInstance; UINT32 Capabilities; UINT32 OldStatus; UINT32 NewStatus; + FlashInstance = INSTANCE_FROM_FVB_THIS (This); + + // Ensure proper access to the flash device from OS level + if (EfiAtRuntime ()) { + FlashInstance->SpiFlashProtocol->FlashPowerOn (&FlashInstance->SpiDevice); + } + // // Obtain attributes from FVB header // @@ -468,6 +481,11 @@ MvFvbGetPhysicalAddress ( FlashInstance = INSTANCE_FROM_FVB_THIS (This); + // Ensure proper access to the flash device from OS level + if (EfiAtRuntime ()) { + FlashInstance->SpiFlashProtocol->FlashPowerOn (&FlashInstance->SpiDevice); + } + *Address = FlashInstance->RegionBaseAddress; return EFI_SUCCESS; @@ -588,6 +606,10 @@ MvFvbRead ( FlashInstance = INSTANCE_FROM_FVB_THIS (This); + // Ensure proper access to the flash device from OS level + if (EfiAtRuntime ()) { + FlashInstance->SpiFlashProtocol->FlashPowerOn (&FlashInstance->SpiDevice); + } // Cache the block size to avoid de-referencing pointers all the time BlockSize = FlashInstance->Media.BlockSize; @@ -697,6 +719,11 @@ MvFvbWrite ( FlashInstance = INSTANCE_FROM_FVB_THIS (This); + // Ensure proper access to the flash device from OS level + if (EfiAtRuntime ()) { + FlashInstance->SpiFlashProtocol->FlashPowerOn (&FlashInstance->SpiDevice); + } + DataOffset = GET_DATA_OFFSET (FlashInstance->FvbOffset + Offset, FlashInstance->StartLba + Lba, FlashInstance->Media.BlockSize); @@ -770,6 +797,11 @@ MvFvbEraseBlocks ( FlashInstance = INSTANCE_FROM_FVB_THIS (This); + // Ensure proper access to the flash device from OS level + if (EfiAtRuntime ()) { + FlashInstance->SpiFlashProtocol->FlashPowerOn (&FlashInstance->SpiDevice); + } + Status = EFI_SUCCESS; // Detect WriteDisabled state @@ -882,11 +914,13 @@ MvFvbVirtualNotifyEvent ( // Convert SPI device description EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiDevice.Info); EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiDevice.HostRegisterBaseAddress); + EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiDevice.HostClockEnableRegister); EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiDevice); // Convert SpiFlashProtocol EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiFlashProtocol->Erase); EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiFlashProtocol->Write); + EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiFlashProtocol->FlashPowerOn); EfiConvertPointer (0x0, (VOID**)&mFvbDevice->SpiFlashProtocol); return; diff --git a/Silicon/Marvell/Drivers/Spi/MvSpiFlashDxe/MvSpiFlashDxe.c b/Silicon/Marvell/Drivers/Spi/MvSpiFlashDxe/MvSpiFlashDxe.c index d81f6e3..4cc897f 100755 --- a/Silicon/Marvell/Drivers/Spi/MvSpiFlashDxe/MvSpiFlashDxe.c +++ b/Silicon/Marvell/Drivers/Spi/MvSpiFlashDxe/MvSpiFlashDxe.c @@ -548,6 +548,15 @@ MvSpiFlashInit ( } EFI_STATUS +EFIAPI +MvSpiFlashPowerOn ( + IN SPI_DEVICE *Slave + ) +{ + return SpiMasterProtocol->ControllerPowerOn (Slave); +} + +EFI_STATUS MvSpiFlashInitProtocol ( IN MARVELL_SPI_FLASH_PROTOCOL *SpiFlashProtocol ) @@ -560,6 +569,7 @@ MvSpiFlashInitProtocol ( SpiFlashProtocol->Erase = MvSpiFlashErase; SpiFlashProtocol->Update = MvSpiFlashUpdate; SpiFlashProtocol->UpdateWithProgress = MvSpiFlashUpdateWithProgress; + SpiFlashProtocol->FlashPowerOn = MvSpiFlashPowerOn; return EFI_SUCCESS; } @@ -586,6 +596,7 @@ MvSpiFlashVirtualNotifyEvent ( // EfiConvertPointer (0x0, (VOID**)&SpiMasterProtocol->ReadWrite); EfiConvertPointer (0x0, (VOID**)&SpiMasterProtocol->Transfer); + EfiConvertPointer (0x0, (VOID**)&SpiMasterProtocol->ControllerPowerOn); EfiConvertPointer (0x0, (VOID**)&SpiMasterProtocol); return; diff --git a/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.c b/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.c index cbf403f..3f7f67e 100755 --- a/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.c +++ b/Silicon/Marvell/Drivers/Spi/MvSpiOrionDxe/MvSpiOrionDxe.c @@ -323,6 +323,11 @@ MvSpiSetupSlave ( } Slave->HostRegisterBaseAddress = PcdGet32 (PcdSpiRegBase); + Slave->HostClockFixed = PcdGetBool (PcdSpiClockFixed); + if (!Slave->HostClockFixed) { + Slave->HostClockEnableRegister = PcdGet64 (PcdSpiClockRegBase); + Slave->HostClockEnableMask = PcdGet32 (PcdSpiClockMask); + } Slave->CoreClock = PcdGet32 (PcdSpiClockFrequency); Slave->MaxFreq = PcdGet32 (PcdSpiMaxFrequency); @@ -344,12 +349,26 @@ MvSpiFreeSlave ( EFI_STATUS EFIAPI +MvSpiControllerPowerOn ( + IN SPI_DEVICE *Slave + ) +{ + if (!Slave->HostClockFixed) { + MmioOr32 (Slave->HostClockEnableRegister, Slave->HostClockEnableMask); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI MvSpiConfigRuntime ( IN SPI_DEVICE *Slave ) { EFI_STATUS Status; UINTN AlignedAddress; + UINTN ClockEnableAlignedAddress; // // Host register base may be not aligned to the page size, @@ -373,11 +392,50 @@ MvSpiConfigRuntime ( EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: Failed to set memory attributes\n", __FUNCTION__)); - gDS->RemoveMemorySpace (AlignedAddress, SIZE_4KB); - return Status; + goto ErrorSetHostMemorySpace; + } + + // + // In case a clock feeding the SPI interface is always on, skip its + // configuration for Runtime. + // + if (Slave->HostClockFixed) { + return EFI_SUCCESS; + } + + // + // Make sure about an alignment of the memory space needed for clock enabling. + // Add one aligned page of memory space which covers the clock enabling + // register. + // + ClockEnableAlignedAddress = Slave->HostClockEnableRegister & ~(SIZE_4KB - 1); + + Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo, + ClockEnableAlignedAddress, + SIZE_4KB, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to add memory space\n", __FUNCTION__)); + goto ErrorSetHostMemorySpace; + } + + Status = gDS->SetMemorySpaceAttributes (ClockEnableAlignedAddress, + SIZE_4KB, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to set memory attributes\n", __FUNCTION__)); + goto ErrorSetClockMemorySpace; } return EFI_SUCCESS; + +ErrorSetClockMemorySpace: + gDS->RemoveMemorySpace (ClockEnableAlignedAddress, SIZE_4KB); + +ErrorSetHostMemorySpace: + gDS->RemoveMemorySpace (AlignedAddress, SIZE_4KB); + + return Status; } STATIC @@ -393,6 +451,7 @@ SpiMasterInitProtocol ( SpiMasterProtocol->Transfer = MvSpiTransfer; SpiMasterProtocol->ReadWrite = MvSpiReadWrite; SpiMasterProtocol->ConfigRuntime = MvSpiConfigRuntime; + SpiMasterProtocol->ControllerPowerOn = MvSpiControllerPowerOn; return EFI_SUCCESS; } -- 2.7.4