From nobody Wed Dec 25 14:16:22 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 15103238631104.586875862906027; Fri, 10 Nov 2017 06:24:23 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 8E03821C913C7; Fri, 10 Nov 2017 06:19:08 -0800 (PST) Received: from mail-wr0-x22f.google.com (mail-wr0-x22f.google.com [IPv6:2a00:1450:400c:c0c::22f]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 2EADA21C913BF for ; Fri, 10 Nov 2017 06:19:06 -0800 (PST) Received: by mail-wr0-x22f.google.com with SMTP id j23so8740779wra.9 for ; Fri, 10 Nov 2017 06:23:09 -0800 (PST) Received: from localhost.localdomain ([160.167.170.128]) by smtp.gmail.com with ESMTPSA id e131sm1036477wmg.15.2017.11.10.06.23.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Nov 2017 06:23:06 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:400c:c0c::22f; helo=mail-wr0-x22f.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=m7AYTN9pbZbAewJXHaZ4Mfagc+ryWhmyd0nb82FjVBU=; b=YJ0ixxKFj51uyADfaBzKbW4lfHXg4sgNbrThclpzmlhdKbF0C7gKS/+uVHfxRiC1ot g7UGsMKLsOj+Qznh4iB6zpd1lRgfEn4lMxUx8O3isIshc/nktqmgwXa51dUlzZZg2JZZ S8FC2DCQCd3L3OmtlOP3WE39udTBgsMrPsmUc= 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=m7AYTN9pbZbAewJXHaZ4Mfagc+ryWhmyd0nb82FjVBU=; b=GILP81w8P3adOfi1MiOSzd5uIgRwSNwQHc4qUCNBQIkp3+3reqfHQPBxuzJ0QfBpop 3cEpqA6fHVmXgeHeM47IqMG03DzTU9K5vQcZqFICLFLUS4kZCO35JkwWOFlBZI5YuLhP 0MNQ3z1FNkfGu6sqYF3OwX5NK6uHJeetqtnSoqn8H+P2xSaXInf7b35gb87mf+5HiKBN LIHXlWoa02TtT2lXtFZr3xLUBb51j1fSIyYFm2zQ+mMA7Qn/RhfJ7MPEk+BMU10TIS+1 zLeOfL6cG+R/8v0UtH8d0uik51mbxFiYY1wqQ8npDnuv85LqigMV/81FhP6IPlymlop3 hv0w== X-Gm-Message-State: AJaThX4INrtEGPBmhVT7oiWxy/0mJtPk6uE1sxwIXZ88xCJpRRE1Eo01 1ggsBAFNyWDZRDd+jNNL06hR4+BqLC0= X-Google-Smtp-Source: AGs4zMZLXFm5H3G0Vnk/tBTjNisGP0Pz5v/2Cwu7/T50MC1V0w8NzklnY0dAy7qgoe4KYDF5NvmgdQ== X-Received: by 10.223.185.121 with SMTP id b54mr458772wrg.264.1510323786851; Fri, 10 Nov 2017 06:23:06 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org, leif.lindholm@linaro.org, daniel.thompson@linaro.org Date: Fri, 10 Nov 2017 14:21:24 +0000 Message-Id: <20171110142127.12018-32-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171110142127.12018-1-ard.biesheuvel@linaro.org> References: <20171110142127.12018-1-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH edk2-platforms v4 31/34] Silicon/Socionext: implement I2C master protocol for SynQuacer I2C X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: masahisa.kojima@linaro.org, masami.hiramatsu@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add a driver that produces the I2C master protocol on top of the I2C controllers that are implemented in the SynQuacer Socionext SoC. Note that this supports two modes simultaneously: I2C controllers that are only usable at boot time, and usable via the I2C protocol stack, and I2C controllers that are dedicated for the RTC or other runtime components. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel --- Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c | = 185 ++++++ Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c | = 238 ++++++++ Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c | = 586 ++++++++++++++++++++ Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h | = 162 ++++++ Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf | = 59 ++ Silicon/Socionext/SynQuacer/SynQuacer.dec | = 5 + 6 files changed, 1235 insertions(+) diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentN= ame.c b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c new file mode 100644 index 000000000000..8d7aa417505b --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c @@ -0,0 +1,185 @@ +/** @file + + Copyright (c) 2017, Linaro Ltd. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "SynQuacerI2cDxe.h" + +STATIC EFI_UNICODE_STRING_TABLE mSynQuacerI2cDriverNameTable[] =3D { + { + "en", + (CHAR16 *)L"Socionext SynQuacer I2C Driver" + }, + { } +}; + +STATIC EFI_UNICODE_STRING_TABLE mSynQuacerI2cControllerNameTable[] =3D { + { + "en", + (CHAR16 *)L"Socionext SynQuacer I2C Controller" + }, + { } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +STATIC +EFI_STATUS +EFIAPI +SynQuacerI2cGetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 (Language, + This->SupportedLanguages, + mSynQuacerI2cDriverNameTable, + DriverName, + FALSE); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +STATIC +EFI_STATUS +EFIAPI +SynQuacerI2cGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + if (ChildHandle !=3D NULL) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString2 (Language, + This->SupportedLanguages, + mSynQuacerI2cControllerNameTable, + ControllerName, + FALSE); +} + +// +// EFI Component Name 2 Protocol +// +EFI_COMPONENT_NAME2_PROTOCOL gSynQuacerI2cDriverComponentName2 =3D { + SynQuacerI2cGetDriverName, + SynQuacerI2cGetControllerName, + "en" +}; diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBind= ing.c b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c new file mode 100644 index 000000000000..22e53408f419 --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c @@ -0,0 +1,238 @@ +/** @file + + Copyright (c) 2017, Linaro Ltd. 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 licens= e 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 IMP= LIED. + +**/ + +#include "SynQuacerI2cDxe.h" + +/** + Tests to see if this driver supports a given controller. + + @param This[in] A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL + instance. + @param ControllerHandle[in] The handle of the controller to test. + @param RemainingDevicePath[in] The remaining device path. + (Ignored - this is not a bus driver.) + + @retval EFI_SUCCESS The driver supports this controller. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandl= e is + already being managed by the driver spe= cified + by This. + @retval EFI_UNSUPPORTED The device specified by ControllerHandl= e is + not supported by the driver specified b= y This. + +**/ +EFI_STATUS +EFIAPI +SynQuacerI2cDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + NON_DISCOVERABLE_DEVICE *Dev; + EFI_STATUS Status; + + // + // Connect to the USB stack + // + Status =3D gBS->OpenProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + (VOID **) &Dev, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CompareGuid (Dev->Type, &gSynQuacerNonDiscoverableI2cMasterGuid) || + CompareGuid (Dev->Type, &gSynQuacerNonDiscoverableRuntimeI2cMasterGu= id)) { + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_UNSUPPORTED; + } + + // + // Clean up. + // + gBS->CloseProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + This->DriverBindingHandle, + ControllerHandle); + + return Status; +} + + +/** + Starts a device controller or a bus controller. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL + instance. + @param[in] ControllerHandle The handle of the device to start. This + handle must support a protocol interfac= e that + supplies an I/O abstraction to the driv= er. + @param[in] RemainingDevicePath The remaining portion of the device pat= h. + (Ignored - this is not a bus driver.) + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a + device error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due = to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +SynQuacerI2cDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return SynQuacerI2cInit (This->DriverBindingHandle, ControllerHandle); +} + + +/** + Stops a device controller or a bus controller. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOC= OL + instance. + @param[in] ControllerHandle A handle to the device being stopped. The = handle + must support a bus specific I/O protocol f= or the + driver to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in + ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May= be + NULL if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a d= evice + error. + +**/ +EFI_STATUS +EFIAPI +SynQuacerI2cDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + return SynQuacerI2cRelease (This->DriverBindingHandle, ControllerHandle); +} + + +STATIC EFI_DRIVER_BINDING_PROTOCOL gSynQuacerI2cDriverBinding =3D { + SynQuacerI2cDriverBindingSupported, + SynQuacerI2cDriverBindingStart, + SynQuacerI2cDriverBindingStop, + 0xa, + NULL, + NULL +}; + + +/** + The entry point of I2c UEFI Driver. + + @param ImageHandle The image handle of the UEFI Driver. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The Driver or UEFI Driver exited norm= ally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than + SystemTable->Hdr.Revision. + +**/ +EFI_STATUS +EFIAPI +SynQuacerI2cDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Add the driver to the list of drivers + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, SystemTable, &gSynQuacerI2cDriverBinding, ImageH= andle, + NULL, &gSynQuacerI2cDriverComponentName2); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "*** Installed SynQuacer I2C UEFI driver! ***\n")); + + return EFI_SUCCESS; +} + + +/** + Unload function for the I2c UEFI Driver. + + @param ImageHandle[in] The allocated handle for the EFI image + + @retval EFI_SUCCESS The driver was unloaded successfully + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +SynQuacerI2cDxeUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + + // + // Retrieve all USB I/O handles in the handle database + // + Status =3D gBS->LocateHandleBuffer (ByProtocol, + &gEdkiiNonDiscoverableDeviceProtocolGu= id, + NULL, + &HandleCount, + &HandleBuffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Disconnect the driver from the handles in the handle database + // + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->DisconnectController (HandleBuffer[Index], + gImageHandle, + NULL); + } + + // + // Free the handle array + // + gBS->FreePool (HandleBuffer); + + // + // Uninstall protocols installed by the driver in its entrypoint + // + Status =3D gBS->UninstallMultipleProtocolInterfaces (ImageHandle, + &gEfiDriverBindingProtocolGuid, + &gSynQuacerI2cDriverBinding, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI= 2cDxe.c b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cD= xe.c new file mode 100644 index 000000000000..0a2d0528e0a7 --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c @@ -0,0 +1,586 @@ +/** @file + + Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D 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 IMP= LIED. + +**/ + +#include "SynQuacerI2cDxe.h" + +#define __DEBUG(x) do { if (!EfiAtRuntime()) DEBUG (x); } while (0) + +// +// We cannot use Stall () or timer events at runtime, so we need to busy-w= ait +// for the controller to signal the completion interrupts. This value was +// arbitrarily chosen, and does not appear to produce any premature timeou= ts +// nor does it result in noticeable stalls in case of bus errors. +// +#define WAIT_FOR_INTERRUPT_TIMEOUT 50000 + +/** + Set the frequency for the I2C clock line. + + This routine must be called at or below TPL_NOTIFY. + + The software and controller do a best case effort of using the specified + frequency for the I2C bus. If the frequency does not match exactly then + the I2C master protocol selects the next lower frequency to avoid + exceeding the operating conditions for any of the I2C devices on the bus. + For example if 400 KHz was specified and the controller's divide network + only supports 402 KHz or 398 KHz then the I2C master protocol selects 398 + KHz. If there are not lower frequencies available, then return + EFI_UNSUPPORTED. + + @param[in] This Pointer to an EFI_I2C_MASTER_PROTOCOL structure + @param[in] BusClockHertz Pointer to the requested I2C bus clock frequen= cy + in Hertz. Upon return this value contains the + actual frequency in use by the I2C controller. + + @retval EFI_SUCCESS The bus frequency was set successfully. + @retval EFI_ALREADY_STARTED The controller is busy with another transa= ction. + @retval EFI_INVALID_PARAMETER BusClockHertz is NULL + @retval EFI_UNSUPPORTED The controller does not support this frequ= ency. + +**/ +STATIC +EFI_STATUS +EFIAPI +SynQuacerI2cSetBusFrequency ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN OUT UINTN *BusClockHertz + ) +{ + SYNQUACER_I2C_MASTER *I2c; + UINT8 Ccr, Csr; + + I2c =3D SYNQUACER_I2C_FROM_THIS (This); + + if (BusClockHertz =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*BusClockHertz >=3D F_I2C_SPEED_FM) { + if (REFCLK_RATE <=3D F_I2C_CLK_RATE_18M) { + Ccr =3D F_I2C_CCR_CS_FAST_MAX_18M (REFCLK_RATE); + Csr =3D F_I2C_CSR_CS_FAST_MAX_18M (REFCLK_RATE); + } else { + Ccr =3D F_I2C_CCR_CS_FAST_MIN_18M (REFCLK_RATE); + Csr =3D F_I2C_CSR_CS_FAST_MIN_18M (REFCLK_RATE); + } + + // Set Clock and enable, Set fast mode + MmioWrite8 (I2c->MmioBase + F_I2C_REG_CCR, + Ccr | F_I2C_CCR_FM | F_I2C_CCR_EN); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_CSR, Csr); + + *BusClockHertz =3D F_I2C_SPEED_FM; + + } else if (*BusClockHertz >=3D F_I2C_SPEED_SM) { + if (REFCLK_RATE <=3D F_I2C_CLK_RATE_18M) { + Ccr =3D F_I2C_CCR_CS_STANDARD_MAX_18M (REFCLK_RATE); + Csr =3D F_I2C_CSR_CS_STANDARD_MAX_18M (REFCLK_RATE); + } else { + Ccr =3D F_I2C_CCR_CS_STANDARD_MIN_18M (REFCLK_RATE); + Csr =3D F_I2C_CSR_CS_STANDARD_MIN_18M (REFCLK_RATE); + } + + // Set Clock and enable, Set standard mode + MmioWrite8 (I2c->MmioBase + F_I2C_REG_CCR, Ccr | F_I2C_CCR_EN); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_CSR, Csr); + + *BusClockHertz =3D F_I2C_SPEED_SM; + } else { + return EFI_UNSUPPORTED; + } + + MemoryFence (); + + return EFI_SUCCESS; +} + +/** + Reset the I2C controller and configure it for use + + This routine must be called at or below TPL_NOTIFY. + + The I2C controller is reset. The caller must call SetBusFrequench() aft= er + calling Reset(). + + @param[in] This Pointer to an EFI_I2C_MASTER_PROTOCOL structur= e. + + @retval EFI_SUCCESS The reset completed successfully. + @retval EFI_ALREADY_STARTED The controller is busy with another transact= ion. + @retval EFI_DEVICE_ERROR The reset operation failed. + +**/ +STATIC +EFI_STATUS +EFIAPI +SynQuacerI2cReset ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This + ) +{ + SYNQUACER_I2C_MASTER *I2c; + + I2c =3D SYNQUACER_I2C_FROM_THIS (This); + + // Disable the clock + MmioWrite8 (I2c->MmioBase + F_I2C_REG_CCR, 0); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_CSR, 0); + + MemoryFence (); + + // Set own Address + MmioWrite8 (I2c->MmioBase + F_I2C_REG_ADR, 0); + + // Set PCLK frequency + MmioWrite8 (I2c->MmioBase + F_I2C_REG_FSR, F_I2C_BUS_CLK_FR (REFCLK_RATE= )); + + // clear IRQ (INT=3D0, BER=3D0), Interrupt Disable + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, 0); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BC2R, 0); + + MemoryFence (); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SynQuacerI2cMasterStart ( + IN SYNQUACER_I2C_MASTER *I2c, + IN UINTN SlaveAddress, + IN EFI_I2C_OPERATION *Op + ) +{ + UINT8 Bsr; + UINT8 Bcr; + + if (Op->Flags & I2C_FLAG_READ) { + MmioWrite8 (I2c->MmioBase + F_I2C_REG_DAR, (SlaveAddress << 1) | 1); + } else { + MmioWrite8 (I2c->MmioBase + F_I2C_REG_DAR, SlaveAddress << 1); + } + + __DEBUG ((DEBUG_INFO, "%a: slave:0x%02x\n", __FUNCTION__, SlaveAddress)); + + Bsr =3D MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR); + Bcr =3D MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR); + + if ((Bsr & F_I2C_BSR_BB) && !(Bcr & F_I2C_BCR_MSS)) { + __DEBUG ((DEBUG_INFO, "%a: bus is busy\n", __FUNCTION__)); + return EFI_ALREADY_STARTED; + } + + if (Bsr & F_I2C_BSR_BB) { // Bus is busy + __DEBUG ((DEBUG_INFO, "%a: Continuous Start\n", __FUNCTION__)); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, Bcr | F_I2C_BCR_SCC); + } else { + if (Bcr & F_I2C_BCR_MSS) { + __DEBUG ((DEBUG_WARN, "%a: is not in master mode\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + __DEBUG ((DEBUG_INFO, "%a: Start Condition\n", __FUNCTION__)); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, + Bcr | F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE); + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +WaitForInterrupt ( + IN SYNQUACER_I2C_MASTER *I2c + ) +{ + UINT8 Bsr; + UINTN Timeout =3D WAIT_FOR_INTERRUPT_TIMEOUT; + + do { + MemoryFence (); + + Bsr =3D MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR); + if (Bsr & F_I2C_BCR_INT) { + return EFI_SUCCESS; + } + } while (Timeout--); + + return EFI_DEVICE_ERROR; +} + +/** + Start an I2C transaction on the host controller. + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + This function initiates an I2C transaction on the controller. To + enable proper error handling by the I2C protocol stack, the I2C + master protocol does not support queuing but instead only manages + one I2C transaction at a time. This API requires that the I2C bus + is in the correct configuration for the I2C transaction. + + The transaction is performed by sending a start-bit and selecting the + I2C device with the specified I2C slave address and then performing + the specified I2C operations. When multiple operations are requested + they are separated with a repeated start bit and the slave address. + The transaction is terminated with a stop bit. + + When Event is NULL, StartRequest operates synchronously and returns + the I2C completion status as its return value. + + When Event is not NULL, StartRequest synchronously returns EFI_SUCCESS + indicating that the I2C transaction was started asynchronously. The + transaction status value is returned in the buffer pointed to by + I2cStatus upon the completion of the I2C transaction when I2cStatus + is not NULL. After the transaction status is returned the Event is + signaled. + + Note: The typical consumer of this API is the I2C host protocol. + Extreme care must be taken by other consumers of this API to prevent + confusing the third party I2C drivers due to a state change at the + I2C device which the third party I2C drivers did not initiate. I2C + platform specific code may use this API within these guidelines. + + @param[in] This Pointer to an EFI_I2C_MASTER_PROTOCOL structur= e. + @param[in] SlaveAddress Address of the device on the I2C bus. Set the + I2C_ADDRESSING_10_BIT when using 10-bit addres= ses, + clear this bit for 7-bit addressing. Bits 0-6 + are used for 7-bit I2C slave addresses and bits + 0-9 are used for 10-bit I2C slave addresses. + @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET + structure describing the I2C transaction. + @param[in] Event Event to signal for asynchronous transactions, + NULL for synchronous transactions + @param[out] I2cStatus Optional buffer to receive the I2C transaction + completion status + + @retval EFI_SUCCESS The asynchronous transaction was successfu= lly + started when Event is not NULL. + @retval EFI_SUCCESS The transaction completed successfully when + Event is NULL. + @retval EFI_ALREADY_STARTED The controller is busy with another transa= ction. + @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is = too + large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the + transaction. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_NOT_FOUND Reserved bit set in the SlaveAddress param= eter + @retval EFI_NO_RESPONSE The I2C device is not responding to the sl= ave + address. EFI_DEVICE_ERROR will be returne= d if + the controller cannot distinguish when the= NACK + occurred. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction + @retval EFI_UNSUPPORTED The controller does not support the reques= ted + transaction. + +**/ +STATIC +EFI_STATUS +EFIAPI +SynQuacerI2cStartRequest ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN UINTN SlaveAddress, + IN EFI_I2C_REQUEST_PACKET *RequestPacket, + IN EFI_EVENT Event OPTIONAL, + OUT EFI_STATUS *I2cStatus OPTIONAL + ) +{ + SYNQUACER_I2C_MASTER *I2c; + UINTN Idx; + EFI_I2C_OPERATION *Op; + UINTN BufIdx; + EFI_STATUS Status; + EFI_TPL Tpl; + BOOLEAN AtRuntime; + UINT8 Bsr; + UINT8 Bcr; + + I2c =3D SYNQUACER_I2C_FROM_THIS (This); + + // + // We can only do synchronous operations at runtime + // + AtRuntime =3D EfiAtRuntime (); + if (AtRuntime && Event !=3D NULL) { + return EFI_UNSUPPORTED; + } + + if (!AtRuntime) { + Tpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + } + + for (Idx =3D 0, Op =3D RequestPacket->Operation, Status =3D EFI_SUCCESS; + Idx < RequestPacket->OperationCount && !EFI_ERROR (Status); + Idx++, Op++) { + + Status =3D SynQuacerI2cMasterStart (I2c, SlaveAddress, Op); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D WaitForInterrupt (I2c); + if (EFI_ERROR (Status)) { + __DEBUG ((DEBUG_WARN, "%a: Timeout waiting for interrupt - %r\n", + Status)); + break; + } + + if (MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR) & F_I2C_BSR_LRB) { + __DEBUG ((DEBUG_WARN, "%a: No ack received - %r\n", __FUNCTION__)); + Status =3D EFI_DEVICE_ERROR; + break; + } + + BufIdx =3D 0; + do { + Bsr =3D MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR); + Bcr =3D MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR); + + if (Bcr & F_I2C_BCR_BER) { + __DEBUG ((DEBUG_WARN, "%a: Bus error detected\n", __FUNCTION__)); + Status =3D EFI_DEVICE_ERROR; + break; + } + + if ((Bsr & F_I2C_BSR_AL) || !(Bcr & F_I2C_BCR_MSS)) { + __DEBUG ((DEBUG_WARN, "%a: Arbitration lost\n", __FUNCTION__)); + Status =3D EFI_DEVICE_ERROR; + break; + } + + if (Op->Flags & I2C_FLAG_READ) { + if (BufIdx =3D=3D Op->LengthInBytes - 1) { + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, + F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE); + } else { + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, + F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE | F_I2C_BCR_AC= K); + } + + Status =3D WaitForInterrupt (I2c); + if (EFI_ERROR (Status)) { + __DEBUG ((DEBUG_WARN, "%a: Timeout waiting for interrupt - %r\n", + __FUNCTION__, Status)); + break; + } + + if (!(MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR) & F_I2C_BSR_FBT)) { + Op->Buffer [BufIdx++] =3D MmioRead8 (I2c->MmioBase + F_I2C_REG_D= AR); + } + } else { + MmioWrite8 (I2c->MmioBase + F_I2C_REG_DAR, Op->Buffer [BufIdx++]); + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, + F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE); + + Status =3D WaitForInterrupt (I2c); + if (EFI_ERROR (Status)) { + __DEBUG ((DEBUG_WARN, "%a: Timeout waiting for interrupt - %r\n", + __FUNCTION__, Status)); + break; + } + + if (MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR) & F_I2C_BSR_LRB) { + __DEBUG ((DEBUG_WARN, "%a: No ack received\n", __FUNCTION__)); + Status =3D EFI_DEVICE_ERROR; + break; + } + } + } while (BufIdx < Op->LengthInBytes); + } + + // Stop the transfer + MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, 0); + + if (!AtRuntime) { + gBS->RestoreTPL (Tpl); + } + + if (Event) { + *I2cStatus =3D Status; + gBS->SignalEvent (Event); + } + return Status; +} + +STATIC CONST EFI_I2C_CONTROLLER_CAPABILITIES mI2cControllerCapabilities = =3D { + sizeof (EFI_I2C_CONTROLLER_CAPABILITIES), // StructureSizeInBytes + MAX_UINT32, // MaximumReceiveBytes + MAX_UINT32, // MaximumTransmitBytes + MAX_UINT32, // MaximumTotalBytes +}; + +STATIC +VOID +EFIAPI +SynQuacerI2cVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + SYNQUACER_I2C_MASTER *I2c =3D Context; + + EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.SetBusFrequency); + EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.Reset); + EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.StartRequest); + EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.I2cControllerCapabiliti= es); + EfiConvertPointer (0x0, (VOID **)&I2c->MmioBase); +} + +EFI_STATUS +SynQuacerI2cInit ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ) +{ + EFI_STATUS Status; + NON_DISCOVERABLE_DEVICE *Dev; + SYNQUACER_I2C_MASTER *I2c; + BOOLEAN Runtime; + + Status =3D gBS->OpenProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + (VOID **)&Dev, DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVE= R); + if (EFI_ERROR (Status)) { + return Status; + } + + Runtime =3D CompareGuid (Dev->Type, + &gSynQuacerNonDiscoverableRuntimeI2cMasterGuid); + + // Allocate Resources + if (Runtime) { + I2c =3D AllocateRuntimeZeroPool (sizeof (SYNQUACER_I2C_MASTER)); + } else { + I2c =3D AllocateZeroPool (sizeof (SYNQUACER_I2C_MASTER)); + } + if (I2c =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto CloseProtocol; + } + + I2c->Signature =3D SYNQUACER_I2C_SIGNATURE; + I2c->I2cMaster.SetBusFrequency =3D SynQuacerI2cSetBusFrequenc= y; + I2c->I2cMaster.Reset =3D SynQuacerI2cReset; + I2c->I2cMaster.StartRequest =3D SynQuacerI2cStartRequest; + I2c->I2cMaster.I2cControllerCapabilities =3D &mI2cControllerCapabilitie= s; + I2c->MmioBase =3D Dev->Resources[0].AddrRang= eMin; + I2c->Dev =3D Dev; + + if (Runtime) { + I2c->Runtime =3D TRUE; + + // Declare the controller as EFI_MEMORY_RUNTIME + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Dev->Resources[0].AddrRangeMin, + Dev->Resources[0].AddrLen, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + __DEBUG ((DEBUG_WARN, "%a: failed to add memory space - %r\n", + __FUNCTION__, Status)); + } + + Status =3D gDS->SetMemorySpaceAttributes ( + Dev->Resources[0].AddrRangeMin, + Dev->Resources[0].AddrLen, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + goto FreeDevice; + } + + // + // Register for the virtual address change event + // + Status =3D gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, + SynQuacerI2cVirtualNotifyEvent, I2c, + &gEfiEventVirtualAddressChangeGuid, + &I2c->VirtualAddressChangeEvent); + if (EFI_ERROR (Status)) { + goto FreeDevice; + } + } + + CopyGuid (&I2c->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); + I2c->DevicePath.MmioBase =3D I2c->MmioBase; + SetDevicePathNodeLength (&I2c->DevicePath.Vendor, + sizeof (I2c->DevicePath) - sizeof (I2c->DevicePath.End)); + SetDevicePathEndNode (&I2c->DevicePath.End); + + Status =3D gBS->InstallMultipleProtocolInterfaces (&ControllerHandle, + &gEfiI2cMasterProtocolGuid, &I2c->I2cMaster, + &gEfiDevicePathProtocolGuid, &I2c->DevicePath, + NULL); + if (EFI_ERROR (Status)) { + goto CloseEvent; + } + return EFI_SUCCESS; + +CloseEvent: + if (Runtime) { + gBS->CloseEvent (I2c->VirtualAddressChangeEvent); + } + +FreeDevice: + FreePool (I2c); + +CloseProtocol: + gBS->CloseProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + DriverBindingHandle, + ControllerHandle); + return Status; +} + +EFI_STATUS +SynQuacerI2cRelease ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ) +{ + EFI_I2C_MASTER_PROTOCOL *I2cMaster; + SYNQUACER_I2C_MASTER *I2c; + EFI_STATUS Status; + + Status =3D gBS->HandleProtocol (ControllerHandle, + &gEfiI2cMasterProtocolGuid, + (VOID **)&I2cMaster); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + I2c =3D SYNQUACER_I2C_FROM_THIS (I2cMaster); + + Status =3D gBS->UninstallMultipleProtocolInterfaces (ControllerHandle, + &gEfiI2cMasterProtocolGuid, I2cMaster, + &gEfiDevicePathProtocolGuid, &I2c->DevicePath, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + if (I2c->Runtime) { + gBS->CloseEvent (I2c->VirtualAddressChangeEvent); + } + + Status =3D gBS->CloseProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + DriverBindingHandle, + ControllerHandle); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->FreePool (I2c); + + return EFI_SUCCESS; +} diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI= 2cDxe.h b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cD= xe.h new file mode 100644 index 000000000000..8c3d7ef67103 --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h @@ -0,0 +1,162 @@ +/** @file + + Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D 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 IMP= LIED. + +**/ + +#ifndef __SYNQUACER_I2C_DXE_H__ +#define __SYNQUACER_I2C_DXE_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern EFI_COMPONENT_NAME2_PROTOCOL gSynQuacerI2cDriverComponentName2; + +#define SYNQUACER_I2C_SIGNATURE SIGNATURE_32 ('S', 'I', '2', 'C') +#define SYNQUACER_I2C_FROM_THIS(a) CR (a, SYNQUACER_I2C_MASTER, \ + I2cMaster, SYNQUACER_I2C_SIGNA= TURE) + +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH Vendor; + UINT64 MmioBase; + EFI_DEVICE_PATH_PROTOCOL End; +} SYNQUACER_I2C_DEVICE_PATH; +#pragma pack() + +typedef struct { + UINT32 Signature; + EFI_I2C_MASTER_PROTOCOL I2cMaster; + EFI_PHYSICAL_ADDRESS MmioBase; + SYNQUACER_I2C_DEVICE_PATH DevicePath; + NON_DISCOVERABLE_DEVICE *Dev; + EFI_EVENT VirtualAddressChangeEvent; + BOOLEAN Runtime; +} SYNQUACER_I2C_MASTER; + +EFI_STATUS +SynQuacerI2cInit ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ); + +EFI_STATUS +SynQuacerI2cRelease ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ); + +#define REFCLK_RATE FixedPcdGet32 (PcdI2cReferenceClock) + +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +#define F_I2C_SPEED_SM 100000 +#define F_I2C_SPEED_FM 400000 + +// I2C register adress definitions +#define F_I2C_REG_BSR (0x00 << 2) // Bus Status Regster +#define F_I2C_REG_BCR (0x01 << 2) // Bus Control Register +#define F_I2C_REG_CCR (0x02 << 2) // Clock Control Register +#define F_I2C_REG_ADR (0x03 << 2) // Address Register +#define F_I2C_REG_DAR (0x04 << 2) // Data Register +#define F_I2C_REG_CSR (0x05 << 2) // Expansion CS Register +#define F_I2C_REG_FSR (0x06 << 2) // Bus Clock Frequency Register +#define F_I2C_REG_BC2R (0x07 << 2) // Bus Control 2 Register + +// I2C register bit definitions +#define F_I2C_BSR_FBT BIT0 // First Byte Transfer +#define F_I2C_BSR_GCA BIT1 // General Call Address +#define F_I2C_BSR_AAS BIT2 // Address as Slave +#define F_I2C_BSR_TRX BIT3 // Transfer/Receive +#define F_I2C_BSR_LRB BIT4 // Last Received Bit +#define F_I2C_BSR_AL BIT5 // Arbitration Lost +#define F_I2C_BSR_RSC BIT6 // Repeated Start Condition +#define F_I2C_BSR_BB BIT7 // Bus Busy + +#define F_I2C_BCR_INT BIT0 // Interrupt +#define F_I2C_BCR_INTE BIT1 // Interrupt Enable +#define F_I2C_BCR_GCAA BIT2 // General Call Access Acknowledge +#define F_I2C_BCR_ACK BIT3 // Acknowledge +#define F_I2C_BCR_MSS BIT4 // Master Slave Select +#define F_I2C_BCR_SCC BIT5 // Start Condition Continue +#define F_I2C_BCR_BEIE BIT6 // Bus Error Interrupt Enable +#define F_I2C_BCR_BER BIT7 // Bus Error + +#define F_I2C_CCR_CS_MASK 0x1f // CCR Clock Period Select +#define F_I2C_CCR_EN BIT5 // Enable +#define F_I2C_CCR_FM BIT6 // Speed Mode Select + +#define F_I2C_CSR_CS_MASK 0x3f // CSR Clock Period Select + +#define F_I2C_BC2R_SCLL BIT0 // SCL Low Drive +#define F_I2C_BC2R_SDAL BIT1 // SDA Low Drive +#define F_I2C_BC2R_SCLS BIT4 // SCL Status +#define F_I2C_BC2R_SDAS BIT5 // SDA Status + +// PCLK frequency +#define F_I2C_BUS_CLK_FR(rate) ((rate) / 20000000 + 1) + +#define F_I2C_MIN_CLK_RATE (14 * 1000000) // min frequency 1= 4 MHz +#define F_I2C_MAX_CLK_RATE (200 * 1000000) // max frequency 2= 00 MHz +#define F_I2C_CLK_RATE_18M (18 * 1000000) // threshold freq = 18 MHz + +// STANDARD MODE frequency +#define F_I2C_CLK_MASTER_STANDARD(rate) \ + DIV_ROUND_UP (DIV_ROUND_UP ((rate), 100000) - 2, 2) + +// FAST MODE frequency +#define F_I2C_CLK_MASTER_FAST(rate) \ + DIV_ROUND_UP ((DIV_ROUND_UP ((rate), 400000) - 2) * 2, 3) + +// (clkrate <=3D 18000000) +// calculate the value of CS bits in CCR register in standard mode +#define F_I2C_CCR_CS_STANDARD_MAX_18M(rate) \ + ((F_I2C_CLK_MASTER_STANDARD (rate) - 65) & F_I2C_CCR_CS_MASK) + +// calculate the value of CS bits in CSR register in standard mode +#define F_I2C_CSR_CS_STANDARD_MAX_18M(rate) 0x00 + +// calculate the value of CS bits in CCR register in fast mode +#define F_I2C_CCR_CS_FAST_MAX_18M(rate) \ + ((F_I2C_CLK_MASTER_FAST (rate) - 1) & F_I2C_CCR_CS_MASK) + +// calculate the value of CS bits in CSR register in fast mode +#define F_I2C_CSR_CS_FAST_MAX_18M(rate) 0x00 + +// (clkrate > 18000000) +// calculate the value of CS bits in CCR register in standard mode */ +#define F_I2C_CCR_CS_STANDARD_MIN_18M(rate) \ + ((F_I2C_CLK_MASTER_STANDARD (rate) - 1) & F_I2C_CCR_CS_MASK) + +// calculate the value of CS bits in CSR register in standard mode +#define F_I2C_CSR_CS_STANDARD_MIN_18M(rate) \ + (((F_I2C_CLK_MASTER_STANDARD (rate) - 1) >> 5) & F_I2C_CSR_CS_= MASK) + +// calculate the value of CS bits in CCR register in fast mode +#define F_I2C_CCR_CS_FAST_MIN_18M(rate) \ + ((F_I2C_CLK_MASTER_FAST (rate) - 1) & F_I2C_CCR_CS_MASK) + +/* calculate the value of CS bits in CSR register in fast mode */ +#define F_I2C_CSR_CS_FAST_MIN_18M(rate) \ + (((F_I2C_CLK_MASTER_FAST (rate) - 1) >> 5) & F_I2C_CSR_CS_MASK) + +#endif diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI= 2cDxe.inf b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2= cDxe.inf new file mode 100644 index 000000000000..fa715366878c --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.i= nf @@ -0,0 +1,59 @@ +#/** @file +# +# Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e 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 IM= PLIED. +# +#**/ + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D SynQuacerI2cDxe + FILE_GUID =3D ab5ed376-dd38-4d22-ae89-b645a4a3236e + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D SynQuacerI2cDxeEntryPoint + UNLOAD =3D SynQuacerI2cDxeUnload + +[Sources.common] + ComponentName.c + DriverBinding.c + SynQuacerI2cDxe.c + SynQuacerI2cDxe.h + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Socionext/SynQuacer/SynQuacer.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesTableLib + IoLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiLib + UefiDriverEntryPoint + UefiRuntimeLib + +[Guids] + gEfiEventVirtualAddressChangeGuid + gSynQuacerNonDiscoverableI2cMasterGuid + gSynQuacerNonDiscoverableRuntimeI2cMasterGuid + +[Protocols] + gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START + gEfiI2cMasterProtocolGuid ## BY_START + +[FixedPcd] + gSynQuacerTokenSpaceGuid.PcdI2cReferenceClock + +[Depex] + TRUE diff --git a/Silicon/Socionext/SynQuacer/SynQuacer.dec b/Silicon/Socionext/= SynQuacer/SynQuacer.dec index c11550469cd0..76a9b70bc81e 100644 --- a/Silicon/Socionext/SynQuacer/SynQuacer.dec +++ b/Silicon/Socionext/SynQuacer/SynQuacer.dec @@ -22,6 +22,9 @@ [Includes] [Guids] gSynQuacerTokenSpaceGuid =3D { 0x4d04555b, 0xdfdc, 0x418a, { 0x8a, 0xab,= 0x07, 0xce, 0xef, 0x46, 0x82, 0xbb } } =20 + gSynQuacerNonDiscoverableI2cMasterGuid =3D { 0x364ee675, 0x9e44, 0x42b7,= { 0xa5, 0xe4, 0x92, 0x84, 0xdb, 0x85, 0xda, 0x09 } } + gSynQuacerNonDiscoverableRuntimeI2cMasterGuid =3D { 0x5f35aa9b, 0x8c6f, = 0x4828, { 0xbd, 0x44, 0x7c, 0xc0, 0xeb, 0x2d, 0xfe, 0xb9 } } + [Ppis] gSynQuacerDramInfoPpiGuid =3D { 0x3e1d7356, 0xdda4, 0x4b1a, { 0x93, 0x46= , 0xbf, 0x89, 0x1c, 0x86, 0x46, 0xcc } } =20 @@ -32,3 +35,5 @@ [PcdsFixedAtBuild] gSynQuacerTokenSpaceGuid.PcdNetsecPhyAddress|0|UINT8|0x00000003 =20 gSynQuacerTokenSpaceGuid.PcdClearSettingsGpioPin|0|UINT32|0x00000004 + + gSynQuacerTokenSpaceGuid.PcdI2cReferenceClock|62500000|UINT32|0x00000005 --=20 2.11.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel