From: "Ard Biesheuvel" <ard.biesheuvel@linaro.org>
To: Marcin Wojtas <mw@semihalf.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>,
"Leif Lindholm" <leif.lindholm@linaro.org>,
"Nadav Haklai" <nadavh@marvell.com>,
"Jan Dąbroś" <jsd@semihalf.com>,
"Grzegorz Jaszczyk" <jaz@semihalf.com>,
"Kostya Porotchkin" <kostap@marvell.com>,
"Jici Gao" <Jici.Gao@arm.com>
Subject: Re: [edk2-platforms: PATCH 2/3] Marvell/Drivers: MvSpiOrionDxe: Keep clock enabled at runtime
Date: Wed, 17 Apr 2019 11:30:03 -0700 [thread overview]
Message-ID: <CAKv+Gu_rXYpv1V0OL1K4G0R6t0aedb24aho2uVS=9g4kZR-dsQ@mail.gmail.com> (raw)
In-Reply-To: <CAKv+Gu_yVgCbthw19LHkDTXDkoHa3Sj1gPPdWt2xzqdyN8Cymw@mail.gmail.com>
On Wed, 17 Apr 2019 at 11:27, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> On Wed, 17 Apr 2019 at 11:06, Marcin Wojtas <mw@semihalf.com> wrote:
> >
> > 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 <mw@semihalf.com>
>
> This is really not the right solution. Linux runs UEFI runtime
> services on a single core with interrupts enabled, and it thinks it
> owns the SPI subsystem if you describe it in the DT, and may decide to
> access it at the same time, either in interrupt ot softirq context, or
> from another core.
>
Note that this applies to just the clock as well.
>
> > ---
> > 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
> >
next prev parent reply other threads:[~2019-04-17 18:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-17 18:05 [edk2-platforms: PATCH 0/3] Armada7k8k FVB improvements Marcin Wojtas
2019-04-17 18:05 ` [edk2-platforms: PATCH 1/3] Marvell/Drivers: MvFvbDxe: Change Pcd parameters to be 64 bit Marcin Wojtas
2019-04-17 18:05 ` [edk2-platforms: PATCH 2/3] Marvell/Drivers: MvSpiOrionDxe: Keep clock enabled at runtime Marcin Wojtas
2019-04-17 18:27 ` Ard Biesheuvel
2019-04-17 18:30 ` Ard Biesheuvel [this message]
2019-04-17 19:33 ` Marcin Wojtas
2019-04-17 18:05 ` [edk2-platforms: PATCH 3/3] Marvell/Drivers: Add non-mmio mode to MvFvbDxe Marcin Wojtas
2019-04-20 17:45 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAKv+Gu_rXYpv1V0OL1K4G0R6t0aedb24aho2uVS=9g4kZR-dsQ@mail.gmail.com' \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox