From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR03-AM5-obe.outbound.protection.outlook.com (EUR03-AM5-obe.outbound.protection.outlook.com [40.107.3.65]) by mx.groups.io with SMTP id smtpd.web11.5902.1586153682591127683 for ; Sun, 05 Apr 2020 23:14:43 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nxp1.onmicrosoft.com header.s=selector2-nxp1-onmicrosoft-com header.b=FqRp0xuC; spf=pass (domain: oss.nxp.com, ip: 40.107.3.65, mailfrom: pankaj.bansal@oss.nxp.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hDttLW3BtwcLw13Yr7WvFZdhwafE3vuca7ChU+9pwJVqXtfWANkm4QuWgpI7R0QFPKr3efWkDmPhPLnLBcqgMlT6raPMoJT0ZqM5ne2/PCKtWbgv2iGADEwDDijAeUhLId+/hkOJnQNPHqqzhVGS9UE43kOl9SjBCPemI75dkERswMvK/ktUKY7DawqQl4zaExN5Mc1uQi0xzXtWGmcyaQ+njYoSoVoDqHe7kpWlkGD+6W7lkznzvSccR6K+r63x2KGaVhrekDJWupvScbDDLO5io3ZzPPrzpGe+X+FrVwmPZPPkW+zuWi+9+IxPBdMsok9H7714PLp10+5DDz7sHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NGG4qGMn4z75oLfgwDF0ej8w3lfxsCGl0TIZ/wf0e9s=; b=OC+ztPECmxKbXi7R9EBrsCYte4B56/Fih+w3kmcHGWsCDc5rZOzFhH896pvSJCj7bO3XWKLakbxlH9vfqAB78vvk6qW50qQubg08PdKscbhidJm8Y3frgpE6kLigdu5AFCtNjNeBMgoTQUhbzcZ7nUWfN+JoK4xOuVjM2QdI66lhdIHxsbrT6NB98CNVfMwQPPqkT7UDZM4UuEZqyZUzPfIUs3tFLmRQSFiUqhoqxk7WUTmjIAqYMn8Psoi5HsbIJywdcAf1GYD9FxAtO2fmoUkl9FyqgG0TPd+l3/3L6gwqGol6bb3jkir4syFD+suYXQ7qbA7Abd3HzE3XzKqzTA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NGG4qGMn4z75oLfgwDF0ej8w3lfxsCGl0TIZ/wf0e9s=; b=FqRp0xuCAKtKPPtOMWnQPHdAP7+SHjswU8xLRu0eyyZikiWfJCMD/lRlMoOQrBuTtubdP66xPd4Gj03Xi9aIGosohB7BXuWn3TbXnc9b33z5JQTzlo8gbB3oiOcoj7U7XF0L3DN7748oumzfsU66cyBp3ukmvHd9pcsKHAwljB4= Received: from VI1PR04MB5933.eurprd04.prod.outlook.com (2603:10a6:803:ec::16) by VI1PR04MB6927.eurprd04.prod.outlook.com (2603:10a6:803:139::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2878.16; Mon, 6 Apr 2020 06:14:38 +0000 Received: from VI1PR04MB5933.eurprd04.prod.outlook.com ([fe80::e581:c145:2f3c:fa18]) by VI1PR04MB5933.eurprd04.prod.outlook.com ([fe80::e581:c145:2f3c:fa18%6]) with mapi id 15.20.2878.018; Mon, 6 Apr 2020 06:14:38 +0000 From: "Pankaj Bansal" To: Leif Lindholm , "Pankaj Bansal (OSS)" CC: Meenakshi Aggarwal , Michael D Kinney , "devel@edk2.groups.io" , Varun Sethi , Samer El-Haj-Mahmoud , Jon Nettleton Subject: Re: [PATCH v2 01/28] Silicon/NXP: Add I2c lib Thread-Topic: [PATCH v2 01/28] Silicon/NXP: Add I2c lib Thread-Index: AQHWC9qmSOOSJ3MdF02FgweCc8otHg== Date: Mon, 6 Apr 2020 06:14:38 +0000 Message-ID: References: <20200320143543.18615-1-pankaj.bansal@oss.nxp.com> <20200320143543.18615-2-pankaj.bansal@oss.nxp.com> <20200331115114.GD7468@vanye> In-Reply-To: <20200331115114.GD7468@vanye> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=pankaj.bansal@oss.nxp.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [49.36.135.41] x-ms-publictraffictype: Email x-ms-office365-filtering-ht: Tenant x-ms-office365-filtering-correlation-id: 5293d19a-673f-4992-2b52-08d7d9f1c982 x-ms-traffictypediagnostic: VI1PR04MB6927:|VI1PR04MB6927: x-ms-exchange-sharedmailbox-routingagent-processed: True x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:9508; x-forefront-prvs: 0365C0E14B x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI1PR04MB5933.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(10009020)(4636009)(366004)(136003)(376002)(346002)(39860400002)(396003)(9686003)(19627235002)(966005)(55016002)(5660300002)(66476007)(2906002)(66946007)(186003)(52536014)(66556008)(53546011)(6506007)(76116006)(8676002)(81156014)(81166006)(26005)(8936002)(7696005)(64756008)(66446008)(478600001)(54906003)(71200400001)(4326008)(30864003)(110136005)(86362001)(316002)(33656002)(559001)(579004);DIR:OUT;SFP:1101; received-spf: None (protection.outlook.com: oss.nxp.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 07cytFzVV+WnDBC5xaojKIHhWJA5/K649qSdMSlgqLQLhQiS96l1S5z/xgeVzeu3O7Iar/eS3Lsrv4rUTVvSY2MExD1B6XYkvQ9ozUry7nXGG+Df/U0H09E9hu14cOvP3GTK9wWDF7MyaUJlIDDDe6Wu1clw/1+B5lFmrX0xAIYSJENQldERk2XHeR3JB3Q8N4bj2xQTkqHGPN8L+44E1FpLRWrhFQIzIgLE9edoF67dEBaVXk4J1SzNVTR8LzBo+RiBHBRVoxygRMG6Ughe0k1QNS37sZe69k+Rjnx9s+L4dsa/YzapNbOdfX0bDWouXYR0YaF/4X7W8xmlrmQVu8zRVStObmYb/Uo5Pz5fpLiFhyWUHXFmCAcvqqiNBSnC1XLcM0bu2e/nWSq9kdWolYcXL1XSgbcKzyqdLHRz1lq1JKDuLvpmmKgGNMV3p81prBhPwiyHgvjeHPpnEzRQPofI95gkvECxsMeLZo1rTGa3O8vwGYJhANxiAuinbAO+5MBLRFnh2xN6kgDZPrOYog== x-ms-exchange-antispam-messagedata: lW6MidlCt79FY1/AWkXO89mruqkBRCF3MehlE5T/YNc9wWAZ3DMV88xJrna6WWtfaOQOmGU5hCIo7y0hc3tojIDEgEfBKasARzJnqjCsZD++iA4TXPsRvWLwSj8dOlJsbMS0a89asz0fL24YpSaPXg== MIME-Version: 1.0 X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5293d19a-673f-4992-2b52-08d7d9f1c982 X-MS-Exchange-CrossTenant-originalarrivaltime: 06 Apr 2020 06:14:38.5972 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: nsxoR14q0kQpWPARALNO6e7dhux3ouI5p2PDHowxWSAHrSb3nB/a9Wc98LVBizO+VSLCm/vbrkHolSttHzbx3A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR04MB6927 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable > -----Original Message----- > From: Leif Lindholm > Sent: Tuesday, March 31, 2020 5:21 PM > To: Pankaj Bansal (OSS) > Cc: Meenakshi Aggarwal ; Michael D Kinney > ; devel@edk2.groups.io; Varun Sethi > ; Samer El-Haj-Mahmoud Mahmoud@arm.com>; Jon Nettleton > Subject: Re: [PATCH v2 01/28] Silicon/NXP: Add I2c lib >=20 > On Fri, Mar 20, 2020 at 20:05:16 +0530, Pankaj Bansal wrote: > > From: Pankaj Bansal > > > > I2c lib is going to be used in PrePeiCore sec module to get the > > System clock information from devices connected to i2c (like fpga > > or clock generator) > > > > since we don't have support of DXE modules this early in boot stage, > > move the i2c controller functionality in library. >=20 > This isn't moving the functionality to a library though - it is moving > the functionality to a library *and* adding new features. These are > two separate changes that should be two separate patches. >=20 > The content in this patch is mostly fine as the end result (but some > comments below). >=20 > I suggest this patch is reordered with 2/28 and all of the splitting > out part takes place in that patch. This patch can then be reduced to > ... the bits that are currently impossible to see are changed (at > least the glitch fixing). Actually the I2cLib is not some bug fix over I2cDxe. The I2cLib has been completely re-written. This is because, I2cDxe was written assuming that the I2c transaction would always be of (reg + data) type only (i.e. two operations) . And also the Repeat start condition was not generated In the I2cDxe driver. This caused the I2c Peripheral drivers which were written keeping the contr= oller driver In mind to issue two operations. Which caused bug in Pcf2129 RTC driver, th= at I am fixing in patch 3. Now I have removed these assumptions as well as added Repeat start between = successive operations, which Comply with PI I2c spec. So, it would be difficult for me to merge the 1 and 2. >=20 > > Signed-off-by: Pankaj Bansal > > --- > > Platform/NXP/NxpQoriqLs.dsc.inc | 4 +- > > Silicon/NXP/Include/Library/I2cLib.h | 120 ++++ > > Silicon/NXP/Library/I2cLib/I2cLib.c | 576 ++++++++++++++++++++ > > Silicon/NXP/Library/I2cLib/I2cLib.inf | 31 ++ > > Silicon/NXP/Library/I2cLib/I2cLibInternal.h | 105 ++++ > > Silicon/NXP/NxpQoriqLs.dec | 10 +- > > 6 files changed, 844 insertions(+), 2 deletions(-) > > create mode 100644 Silicon/NXP/Include/Library/I2cLib.h > > create mode 100644 Silicon/NXP/Library/I2cLib/I2cLib.c > > create mode 100644 Silicon/NXP/Library/I2cLib/I2cLib.inf > > create mode 100644 Silicon/NXP/Library/I2cLib/I2cLibInternal.h > > > > diff --git a/Platform/NXP/NxpQoriqLs.dsc.inc > b/Platform/NXP/NxpQoriqLs.dsc.inc > > index fa5f30dd3909..b28e0615f7ca 100644 > > --- a/Platform/NXP/NxpQoriqLs.dsc.inc > > +++ b/Platform/NXP/NxpQoriqLs.dsc.inc > > @@ -1,6 +1,6 @@ > > # @file > > # > > -# Copyright 2017-2019 NXP. > > +# Copyright 2017-2020 NXP. > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > @@ -94,6 +94,8 @@ [LibraryClasses.common] > > > NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverabl > eDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf > > > ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeRep > ortStatusCodeLib.inf > > > > + I2cLib|Silicon/NXP/Library/I2cLib/I2cLib.inf > > + >=20 > I think the changes to this file belong in 2/28. This I can add to 2/28 >=20 > > [LibraryClasses.common.SEC] > > PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf > > > UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecomp > ressLib.inf > > diff --git a/Silicon/NXP/Include/Library/I2cLib.h > b/Silicon/NXP/Include/Library/I2cLib.h > > new file mode 100644 > > index 000000000000..e39237abd3ee > > --- /dev/null > > +++ b/Silicon/NXP/Include/Library/I2cLib.h > > @@ -0,0 +1,120 @@ > > +/** @file > > + I2c Lib to control I2c controller. > > + > > + Copyright 2020 NXP > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef I2C_LIB_H__ > > +#define I2C_LIB_H__ > > + > > +#include > > +#include > > + > > +/** > > + software reset of the entire I2C module. > > + The module is reset and disabled. > > + Status register fields (IBSR) are cleared. > > + > > + @param[in] Base Base Address of I2c controller's registers > > + > > + @return EFI_SUCCESS successfuly reset the I2c module > > +**/ > > +EFI_STATUS > > +I2cReset ( > > + IN UINTN Base > > + ); > > + > > +/** > > + Early init I2C for reading the sysclk from I2c slave device. > > + I2c bus clock is determined from the clock input to I2c controller. > > + The clock input to I2c controller is derived from the sysclk. > > + sysclk is determined by clock generator, which is controller by i2c. > > + > > + So, it's a chicken-egg problem to read the sysclk from clock generat= or. > > + To break this cycle (i.e. to read the sysclk), we setup the i2c bus = clock to > > + lowest value, in the hope that it won't be out of clock generator's = supported > > + i2c clock frequency. Once we have the correct sysclk, we can setup t= he > > + correct i2c bus clock. > > + > > + @param[in] Base Base Address of I2c controller's registers > > + > > + @return EFI_SUCCESS successfuly setup the i2c bus for reading sysc= lk > > +**/ > > +EFI_STATUS > > +I2cEarlyInitialize ( > > + IN UINTN Base > > + ); > > + > > +/** > > + Configure I2c bus to operate at a given speed > > + > > + @param[in] Base Base Address of I2c controller's registers > > + @param[in] I2cBusClock Input clock to I2c controller > > + @param[in] Speed speed to be configured for I2c bus > > + > > + @return EFI_SUCCESS successfuly setup the i2c bus > > +**/ > > +EFI_STATUS > > +I2cInitialize ( > > + IN UINTN Base, > > + IN UINT64 I2cBusClock, > > + IN UINT64 Speed > > + ); > > + > > +/** > > + Transfer data to/from I2c slave device > > + > > + @param[in] Base Base Address of I2c controller's registers > > + @param[in] SlaveAddress Slave Address from which data is to be rea= d > > + @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET > structure > > + describing the I2C transaction > > + > > + @return EFI_SUCCESS successfuly transfer the data > > + @return EFI_DEVICE_ERROR There was an error while transferring dat= a > through > > + I2c bus > > + @return EFI_NO_RESPONSE There was no Ack from i2c device > > + @return EFI_TIMEOUT I2c Bus is busy > > + @return EFI_NOT_READY I2c Bus Arbitration lost > > +**/ > > +EFI_STATUS > > +I2cBusXfer ( > > + IN UINTN Base, > > + IN UINT32 SlaveAddress, > > + IN EFI_I2C_REQUEST_PACKET *RequestPacket > > + ); > > + > > +/** > > + Read a register from I2c slave device. This API is wrapper around I2= cBusXfer > > + > > + @param[in] Base Base Address of I2c controller's = registers > > + @param[in] SlaveAddress Slave Address from which register= value is > > + to be read > > + @param[in] RegAddress Register Address in Slave's memor= y map > > + @param[in] RegAddressWidthInBytes Number of bytes in RegAddress to > send to > > + I2c Slave for simple reads withou= t any > > + register, make this value =3D 0 > > + (RegAddress is don't care in that= case) > > + @param[out] RegValue Value to be read from I2c slave's= regiser > > + @param[in] RegValueNumBytes Number of bytes to read from I2c = slave > > + register > > + > > + @return EFI_SUCCESS successfuly read the registers > > + @return EFI_DEVICE_ERROR There was an error while transferring dat= a > through > > + I2c bus > > + @return EFI_NO_RESPONSE There was no Ack from i2c device > > + @return EFI_TIMEOUT I2c Bus is busy > > + @return EFI_NOT_READY I2c Bus Arbitration lost > > +**/ > > +EFI_STATUS > > +I2cBusReadReg ( > > + IN UINTN Base, > > + IN UINT32 SlaveAddress, > > + IN UINT64 RegAddress, > > + IN UINT8 RegAddressWidthInBytes, > > + OUT UINT8 *RegValue, > > + IN UINT32 RegValueNumBytes > > + ); > > + > > +#endif // I2C_LIB_H__ > > diff --git a/Silicon/NXP/Library/I2cLib/I2cLib.c > b/Silicon/NXP/Library/I2cLib/I2cLib.c > > new file mode 100644 > > index 000000000000..08bf14c490be > > --- /dev/null > > +++ b/Silicon/NXP/Library/I2cLib/I2cLib.c > > @@ -0,0 +1,576 @@ > > +/** @file > > + I2c Lib to control I2c controller. > > + > > + Copyright 2017, 2020 NXP > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "I2cLibInternal.h" > > + > > +/** > > + I2C divisor and Ibfd register values when glitch filter is enabled > > + > > + In case of duplicate SCL Divisor value, the Ibfd value with high MUL= value > > + has been selected. A higher MUL value results in a lower sampling ra= te of > > + the I2C signals. This gives the I2C module greater immunity against = glitches > > + in the I2C signals. >=20 > So this comment (and the subsequent one) have been cleaned up and no > longer refers to an SoC not yet upstream. But this has also removed > any reference to where these values come from. >=20 > Has NXP (including acquisitions) only ever produced one I2C > controller? > If there is no standalone name for the controller, can something be > said about the family of devices that contains it? I don't know if this is the only I2c IP that we have ever used. I asked around and I could not get any definite answer to this question. However, I will add the name of NXP QoriQ Layerscape family of SOCs in comm= ent. >=20 > > +**/ > > +STATIC CONST I2C_CLOCK_DIVISOR_PAIR mI2cClockDivisorGlitchEnabled[] = =3D > { > > + { 34, 0x0 }, { 36, 0x1 }, { 38, 0x2 }, { 40, 0x3 }, > > + { 42, 0x4 }, { 44, 0x8 }, { 48, 0x9 }, { 52, 0xA }, > > + { 54, 0x7 }, { 56, 0xB }, { 60, 0xC }, { 64, 0x10 }, > > + { 68, 0x40 }, { 72, 0x41 }, { 76, 0x42 }, { 80, 0x43 }, > > + { 84, 0x44 }, { 88, 0x48 }, { 96, 0x49 }, { 104, 0x4A }, > > + { 108, 0x47 }, { 112, 0x4B }, { 120, 0x4C }, { 128, 0x50 }, > > + { 136, 0x80 }, { 144, 0x81 }, { 152, 0x82 }, { 160, 0x83 }, > > + { 168, 0x84 }, { 176, 0x88 }, { 192, 0x89 }, { 208, 0x8A }, > > + { 216, 0x87 }, { 224, 0x8B }, { 240, 0x8C }, { 256, 0x90 }, > > + { 288, 0x91 }, { 320, 0x92 }, { 336, 0x8F }, { 352, 0x93 }, > > + { 384, 0x98 }, { 416, 0x95 }, { 448, 0x99 }, { 480, 0x96 }, > > + { 512, 0x9A }, { 576, 0x9B }, { 640, 0xA0 }, { 704, 0x9D }, > > + { 768, 0xA1 }, { 832, 0x9E }, { 896, 0xA2 }, { 960, 0x67 }, > > + { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, > > + { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, > > + { 2560, 0xB0 }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, > > + { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, > > + { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, > > + { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } > > +}; > > + > > +/** > > + I2C divisor and Ibfd register values when glitch filter is disabled > > + > > + In case of duplicate SCL Divisor value, the Ibfd value with high MUL= value > > + has been selected. A higher MUL value results in a lower sampling ra= te of > > + the I2C signals. This gives the I2C module greater immunity against = glitches > > + in the I2C signals. > > +**/ > > +STATIC CONST I2C_CLOCK_DIVISOR_PAIR mI2cClockDivisorGlitchDisabled[] = =3D > { > > + { 20, 0x0 },{ 22, 0x1 },{ 24, 0x2 },{ 26, 0x3 }, > > + { 28, 0x8 },{ 30, 0x5 },{ 32, 0x9 },{ 34, 0x6 }, > > + { 36, 0x0A },{ 40, 0x40 },{ 44, 0x41 },{ 48, 0x42 }, > > + { 52, 0x43 },{ 56, 0x48 },{ 60, 0x45 },{ 64, 0x49 }, > > + { 68, 0x46 },{ 72, 0x4A },{ 80, 0x80 },{ 88, 0x81 }, > > + { 96, 0x82 },{ 104, 0x83 },{ 112, 0x88 },{ 120, 0x85 }, > > + { 128, 0x89 },{ 136, 0x86 },{ 144, 0x8A },{ 160, 0x8B }, > > + { 176, 0x8C },{ 192, 0x90 },{ 208, 0x56 },{ 224, 0x91 }, > > + { 240, 0x1F },{ 256, 0x92 },{ 272, 0x8F },{ 288, 0x93 }, > > + { 320, 0x98 },{ 352, 0x95 },{ 384, 0x99 },{ 416, 0x96 }, > > + { 448, 0x9A },{ 480, 0x5F },{ 512, 0x9B },{ 576, 0x9C }, > > + { 640, 0xA0 },{ 768, 0xA1 },{ 896, 0xA2 },{ 960, 0x9F }, > > + { 1024, 0xA3 },{ 1152, 0xA4 },{ 1280, 0xA8 },{ 1536, 0xA9 }, > > + { 1792, 0xAA },{ 1920, 0xA7 },{ 2048, 0xAB },{ 2304, 0xAC }, > > + { 2560, 0xAD },{ 3072, 0xB1 },{ 3584, 0xB2 },{ 3840, 0xAF }, > > + { 4096, 0xB3 },{ 4608, 0xB4 },{ 5120, 0xB8 },{ 6144, 0xB9 }, > > + { 7168, 0xBA },{ 7680, 0xB7 },{ 8192, 0xBB },{ 9216, 0xBC }, > > + { 10240, 0xBD },{ 12288, 0xBE },{ 15360, 0xBF } > > +}; > > + > > +/** > > + ERR009203 : I2C may not work reliably with the default setting > > + > > + Description : The clocking circuitry of I2C module may not work reli= ably due > > + to the slow rise time of SCL signal. > > + Workaround : Enable the receiver digital filter by setting IBDBG[GL= FLT_EN] > > + to 1. > > +**/ > > +STATIC > > +VOID > > +I2cErratumA009203 ( >=20 > I'm still missing an explanation of why The function contains A009203 > but the comment header describes ERR009203. > I suggested an addition to the file header comment, but can't see > anything there. The Errata in NXP design database are numbered as ERRXXXXX, while in softwa= re database the errata are numbered as AXXXXX. I asked around and I could only get that this is the convention that we hav= e followed everywhere. I will change the ERRXXXXX to AXXXXX. The errata document that mentions this errata is not published in public do= main. However, I can give the link to other software in which this same errata ha= s been added like: https://elixir.bootlin.com/u-boot/latest/source/arch/arm/cpu/armv8/fsl-laye= rscape/soc.c#L283 >=20 > > + IN UINTN Base > > + ) > > +{ > > + I2C_REGS *Regs; > > + > > + Regs =3D (I2C_REGS *)Base; > > + > > + MmioOr8 ((UINTN)&Regs->Ibdbg, I2C_IBDBG_GLFLT_EN); > > +} > > + > > +/** > > + software reset of the entire I2C module. > > + The module is reset and disabled. > > + Status register fields (IBSR) are cleared. > > + > > + @param[in] Base Base Address of I2c controller's registers > > + > > + @return EFI_SUCCESS successfuly reset the I2c module > > +**/ > > +EFI_STATUS > > +I2cReset ( > > + IN UINTN Base > > + ) > > +{ > > + I2C_REGS *Regs; > > + > > + Regs =3D (I2C_REGS *)Base; > > + > > + MmioOr8 ((UINTN)&Regs->Ibcr, I2C_IBCR_MDIS); > > + MmioOr8 ((UINTN)&Regs->Ibsr, (I2C_IBSR_IBAL | I2C_IBSR_IBIF)); > > + MmioAnd8 ((UINTN)&Regs->Ibcr, ~(I2C_IBCR_IBIE | I2C_IBCR_DMAEN)); > > + MmioAnd8 ((UINTN)&Regs->Ibic, (UINT8)(~I2C_IBIC_BIIE)); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Early init I2C for reading the sysclk from I2c slave device. > > + I2c bus clock is determined from the clock input to I2c controller. > > + The clock input to I2c controller is derived from the sysclk. > > + sysclk is determined by clock generator, which is controller by i2c. > > + > > + So, it's a chicken-egg problem to read the sysclk from clock generat= or. > > + To break this cycle (i.e. to read the sysclk), we setup the i2c bus = clock to > > + lowest value, in the hope that it won't be out of clock generator's = supported > > + i2c clock frequency. Once we have the correct sysclk, we can setup t= he > > + correct i2c bus clock. > > + > > + @param[in] Base Base Address of I2c controller's registers > > + > > + @return EFI_SUCCESS successfuly setup the i2c bus for reading sysc= lk > > +**/ > > +EFI_STATUS > > +I2cEarlyInitialize ( > > + IN UINTN Base > > + ) > > +{ > > + I2C_REGS *Regs; > > + UINT8 Ibfd; >=20 > "Ibfd" is not more CamelCase compliant than "Ibc" is, and no more > descriptive. Please, if this is a term used in official NXP > documentation, add it to a glossary in the file header comment. > If not, please name it using camel case as something I can understand > what it is intended to be used for without already knowing. Ok, I will add the abbreviations used in file header=20 >=20 > ... skims ahead ... >=20 > OK, so now it's "I2c Bus Frequency Dividor" (think that should be > Divider). Sure, that can be Ibfd *if* introduced in the file header > glossary, in *every* file that contains this abbreviation. >=20 Ok, I will add the abbreviations used in file header > > + > > + Regs =3D (I2C_REGS *)Base; > > + if (FeaturePcdGet (PcdI2cErratumA009203)) { > > + I2cErratumA009203 (Base); > > + } > > + > > + if (MmioRead8 ((UINTN)&Regs->Ibdbg) & I2C_IBDBG_GLFLT_EN) { > > + Ibfd =3D ARRAY_LAST_ELEM (mI2cClockDivisorGlitchEnabled).Ibfd; > > + } else { > > + Ibfd =3D ARRAY_LAST_ELEM (mI2cClockDivisorGlitchDisabled).Ibfd; > > + } > > + > > + MmioWrite8 ((UINTN)&Regs->Ibfd, Ibfd); > > + > > + I2cReset (Base); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Configure I2c bus to operate at a given speed > > + > > + @param[in] Base Base Address of I2c controller's registers > > + @param[in] I2cBusClock Input clock to I2c controller > > + @param[in] Speed speed to be configured for I2c bus > > + > > + @return EFI_SUCCESS successfuly setup the i2c bus > > +**/ > > +EFI_STATUS > > +I2cInitialize ( > > + IN UINTN Base, > > + IN UINT64 I2cBusClock, > > + IN UINT64 Speed > > + ) > > +{ > > + I2C_REGS *Regs; > > + UINT16 ClockDivisor; > > + UINT8 Ibfd; // I2c Bus Frequency Dividor Re= gister >=20 > Introduction of non-standard abbreviations happen in the file header comm= ent > block: > https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards- > specification/content/v/release/2.20/5_source_files/52_spacing.html#5231- > every-new-file-shall-begin-with-a-file-header-comment-block Ok, I will add the abbreviations used in file header >=20 > > + CONST I2C_CLOCK_DIVISOR_PAIR *ClockDivisorPair; > > + UINT32 ClockDivisorPairSize; > > + UINT32 Index; > > + > > + Regs =3D (I2C_REGS *)Base; > > + if (FeaturePcdGet (PcdI2cErratumA009203)) { > > + I2cErratumA009203 (Base); > > + } >=20 > Is this erratum workaround intentionally invoked twice? > If so, the code could do with comments at all call sites explaining why. > I.e. "apply workaround before enabling controller", "re-apply > workaround after updating X", ... Ok I will add the comments at call sites. >=20 > > + > > + Ibfd =3D 0; > > + ClockDivisor =3D (I2cBusClock + Speed - 1) / Speed; > > + > > + if (MmioRead8 ((UINTN)&Regs->Ibdbg) & I2C_IBDBG_GLFLT_EN) { > > + ClockDivisorPair =3D mI2cClockDivisorGlitchEnabled; > > + ClockDivisorPairSize =3D ARRAY_SIZE (mI2cClockDivisorGlitchEnabled= ); > > + } else { > > + ClockDivisorPair =3D mI2cClockDivisorGlitchDisabled; > > + ClockDivisorPairSize =3D ARRAY_SIZE (mI2cClockDivisorGlitchDisable= d); > > + } > > + > > + if (ClockDivisor > ClockDivisorPair[ClockDivisorPairSize - 1].Diviso= r) { > > + Ibfd =3D ClockDivisorPair[ClockDivisorPairSize - 1].Ibfd; > > + } else { > > + for (Index =3D 0; Index < ClockDivisorPairSize; Index++) { > > + if (ClockDivisorPair[Index].Divisor >=3D ClockDivisor) { > > + Ibfd =3D ClockDivisorPair[Index].Ibfd; > > + break; > > + } > > + } > > + } > > + > > + MmioWrite8 ((UINTN)&Regs->Ibfd, Ibfd); > > + > > + I2cReset (Base); > > + > > + return EFI_SUCCESS; > > +} > > + > > +STATIC > > +EFI_STATUS > > +I2cBusTestBusBusy ( > > + IN I2C_REGS *Regs, > > + IN BOOLEAN TestBusy > > + ) > > +{ > > + UINT32 Index; > > + UINT8 Reg; > > + > > + for (Index =3D 0; Index < I2C_NUM_RETRIES; Index++) { > > + Reg =3D MmioRead8 ((UINTN)&Regs->Ibsr); > > + > > + if (Reg & I2C_IBSR_IBAL) { > > + MmioWrite8 ((UINTN)&Regs->Ibsr, Reg); > > + return EFI_NOT_READY; > > + } > > + > > + if (TestBusy && (Reg & I2C_IBSR_IBB)) { > > + break; > > + } > > + > > + if (!TestBusy && !(Reg & I2C_IBSR_IBB)) { > > + break; > > + } > > + > > + MicroSecondDelay (1); > > + } > > + > > + if (Index =3D=3D I2C_NUM_RETRIES) { > > + return EFI_TIMEOUT; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +STATIC > > +EFI_STATUS > > +I2cTransferComplete ( > > + IN I2C_REGS *Regs, > > + IN BOOLEAN TestRxAck > > +) > > +{ > > + UINT32 Index; > > + UINT8 Reg; > > + > > + for (Index =3D 0; Index < I2C_NUM_RETRIES; Index++) { > > + Reg =3D MmioRead8 ((UINTN)&Regs->Ibsr); > > + > > + if (Reg & I2C_IBSR_IBIF) { > > + // Write 1 to clear the IBIF field > > + MmioWrite8 ((UINTN)&Regs->Ibsr, Reg); > > + break; > > + } > > + > > + MicroSecondDelay (1); > > + } > > + > > + if (Index =3D=3D I2C_NUM_RETRIES) { > > + return EFI_TIMEOUT; > > + } > > + > > + if (TestRxAck && (Reg & I2C_IBSR_RXAK)) { > > + return EFI_NO_RESPONSE; > > + } > > + > > + if (Reg & I2C_IBSR_TCF) { > > + return EFI_SUCCESS; > > + } > > + > > + return EFI_DEVICE_ERROR; > > +} > > + > > +STATIC > > +EFI_STATUS > > +I2cRead ( > > + IN I2C_REGS *Regs, > > + IN UINT32 SlaveAddress, > > + IN EFI_I2C_OPERATION *Operation, > > + IN BOOLEAN IsLastOperation > > +) > > +{ > > + EFI_STATUS Status; > > + UINTN Index; > > + > > + // Write Slave Address > > + MmioWrite8 ((UINTN)&Regs->Ibdr, (SlaveAddress << BIT0) | BIT0); > > + Status =3D I2cTransferComplete (Regs, I2C_BUS_TEST_RX_ACK); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + // select Receive mode. > > + MmioAnd8 ((UINTN)&Regs->Ibcr, ~I2C_IBCR_TXRX); > > + if (Operation->LengthInBytes > 1) { > > + // Set No ACK =3D 0 > > + MmioAnd8 ((UINTN)&Regs->Ibcr, ~I2C_IBCR_NOACK); > > + } > > + > > + // Perform a dummy read to initiate the receive operation. > > + MmioRead8 ((UINTN)&Regs->Ibdr); > > + > > + for (Index =3D 0; Index < Operation->LengthInBytes; Index++) { > > + Status =3D I2cTransferComplete (Regs, I2C_BUS_NO_TEST_RX_ACK); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + if (Index =3D=3D (Operation->LengthInBytes - 2)) { > > + // Set No ACK =3D 1 > > + MmioOr8 ((UINTN)&Regs->Ibcr, I2C_IBCR_NOACK); > > + } else if (Index =3D=3D (Operation->LengthInBytes - 1)) { > > + if (!IsLastOperation) { > > + // select Transmit mode (for repeat start) > > + MmioOr8 ((UINTN)&Regs->Ibcr, I2C_IBCR_TXRX); > > + } else { > > + // Generate Stop Signal > > + MmioAnd8 ((UINTN)&Regs->Ibcr, ~(I2C_IBCR_MSSL | I2C_IBCR_TXRX)= ); > > + Status =3D I2cBusTestBusBusy (Regs, I2C_BUS_TEST_IDLE); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } > > + } > > + Operation->Buffer[Index] =3D MmioRead8 ((UINTN)&Regs->Ibdr); > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +STATIC > > +EFI_STATUS > > +I2cWrite ( > > + IN I2C_REGS *Regs, > > + IN UINT32 SlaveAddress, > > + IN EFI_I2C_OPERATION *Operation > > +) > > +{ > > + EFI_STATUS Status; > > + UINTN Index; > > + > > + // Write Slave Address > > + MmioWrite8 ((UINTN)&Regs->Ibdr, (SlaveAddress << BIT0) & > (UINT8)(~BIT0)); > > + Status =3D I2cTransferComplete (Regs, I2C_BUS_TEST_RX_ACK); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + // Write Data > > + for (Index =3D 0; Index < Operation->LengthInBytes; Index++) { > > + MmioWrite8 ((UINTN)&Regs->Ibdr, Operation->Buffer[Index]); > > + Status =3D I2cTransferComplete (Regs, I2C_BUS_TEST_RX_ACK); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } > > + return EFI_SUCCESS; > > +} > > + > > +STATIC > > +EFI_STATUS > > +I2cStop ( > > + IN I2C_REGS *Regs > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT8 Reg; > > + > > + Status =3D EFI_SUCCESS; > > + Reg =3D MmioRead8 ((UINTN)&Regs->Ibsr); > > + if (Reg & I2C_IBSR_IBB) { > > + // Generate Stop Signal > > + MmioAnd8 ((UINTN)&Regs->Ibcr, ~(I2C_IBCR_MSSL | I2C_IBCR_TXRX)); > > + Status =3D I2cBusTestBusBusy (Regs, I2C_BUS_TEST_IDLE); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } > > + > > + // Disable I2c Controller > > + MmioOr8 ((UINTN)&Regs->Ibcr, I2C_IBCR_MDIS); > > + > > + return Status; > > +} > > + > > +STATIC > > +EFI_STATUS > > +I2cStart ( > > + IN I2C_REGS *Regs > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + MmioOr8 ((UINTN)&Regs->Ibsr, (I2C_IBSR_IBAL | I2C_IBSR_IBIF)); > > + MmioAnd8 ((UINTN)&Regs->Ibcr, (UINT8)(~I2C_IBCR_MDIS)); > > + > > + //Wait controller to be stable > > + MicroSecondDelay (1); > > + > > + // Generate Start Signal > > + MmioOr8 ((UINTN)&Regs->Ibcr, I2C_IBCR_MSSL); > > + Status =3D I2cBusTestBusBusy (Regs, I2C_BUS_TEST_BUSY); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + // Select Transmit Mode. set No ACK =3D 1 > > + MmioOr8 ((UINTN)&Regs->Ibcr, (I2C_IBCR_TXRX | I2C_IBCR_NOACK)); > > + > > + return Status; > > +} > > + > > +/** > > + Transfer data to/from I2c slave device > > + > > + @param[in] Base Base Address of I2c controller's registers > > + @param[in] SlaveAddress Slave Address from which data is to be rea= d > > + @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET > structure > > + describing the I2C transaction > > + > > + @return EFI_SUCCESS successfuly transfer the data > > + @return EFI_DEVICE_ERROR There was an error while transferring dat= a > through > > + I2c bus > > + @return EFI_NO_RESPONSE There was no Ack from i2c device > > + @return EFI_TIMEOUT I2c Bus is busy > > + @return EFI_NOT_READY I2c Bus Arbitration lost > > +**/ > > +EFI_STATUS > > +I2cBusXfer ( > > + IN UINTN Base, > > + IN UINT32 SlaveAddress, > > + IN EFI_I2C_REQUEST_PACKET *RequestPacket > > + ) > > +{ > > + UINTN Index; > > + I2C_REGS *Regs; > > + EFI_I2C_OPERATION *Operation; > > + EFI_STATUS Status; > > + BOOLEAN IsLastOperation; > > + > > + Regs =3D (I2C_REGS *)Base; > > + IsLastOperation =3D FALSE; > > + > > + Status =3D I2cBusTestBusBusy (Regs, I2C_BUS_TEST_IDLE); > > + if (EFI_ERROR (Status)) { > > + goto ErrorExit; > > + } > > + > > + Status =3D I2cStart (Regs); > > + if (EFI_ERROR (Status)) { > > + goto ErrorExit; > > + } > > + > > + for (Index =3D 0, Operation =3D RequestPacket->Operation; > > + Index < RequestPacket->OperationCount; > > + Index++, Operation++) { > > + if (Index =3D=3D (RequestPacket->OperationCount - 1)) { > > + IsLastOperation =3D TRUE; > > + } > > + // Send repeat start after first transmit/recieve > > + if (Index) { > > + MmioOr8 ((UINTN)&Regs->Ibcr, I2C_IBCR_RSTA); > > + Status =3D I2cBusTestBusBusy (Regs, I2C_BUS_TEST_BUSY); > > + if (EFI_ERROR (Status)) { > > + goto ErrorExit; > > + } > > + } > > + // Read/write data > > + if (Operation->Flags & I2C_FLAG_READ) { > > + Status =3D I2cRead (Regs, SlaveAddress, Operation, IsLastOperati= on); > > + } else { > > + Status =3D I2cWrite (Regs, SlaveAddress, Operation); > > + } > > + if (EFI_ERROR (Status)) { > > + goto ErrorExit; > > + } > > + } > > + > > +ErrorExit: > > + > > + I2cStop (Regs); > > + > > + return Status; > > +} > > + > > +/** > > + Read a register from I2c slave device. This API is wrapper around I2= cBusXfer > > + > > + @param[in] Base Base Address of I2c controller's = registers > > + @param[in] SlaveAddress Slave Address from which register= value is > > + to be read > > + @param[in] RegAddress Register Address in Slave's memor= y map > > + @param[in] RegAddressWidthInBytes Number of bytes in RegAddress to > send to > > + I2c Slave for simple reads withou= t any > > + register, make this value =3D 0 > > + (RegAddress is don't care in that= case) > > + @param[out] RegValue Value to be read from I2c slave's= regiser > > + @param[in] RegValueNumBytes Number of bytes to read from I2c = slave > > + register > > + > > + @return EFI_SUCCESS successfuly read the registers > > + @return EFI_DEVICE_ERROR There was an error while transferring dat= a > through > > + I2c bus > > + @return EFI_NO_RESPONSE There was no Ack from i2c device > > + @return EFI_TIMEOUT I2c Bus is busy > > + @return EFI_NOT_READY I2c Bus Arbitration lost > > +**/ > > +EFI_STATUS > > +I2cBusReadReg ( > > + IN UINTN Base, > > + IN UINT32 SlaveAddress, > > + IN UINT64 RegAddress, > > + IN UINT8 RegAddressWidthInBytes, > > + OUT UINT8 *RegValue, > > + IN UINT32 RegValueNumBytes > > + ) > > +{ > > + EFI_I2C_OPERATION *Operations; > > + I2C_REG_REQUEST RequestPacket; > > + UINTN OperationCount; > > + UINT8 Address[sizeof (RegAddress)]; > > + UINT8 *PtrAddress; >=20 > This is too close to hungarian notation - AddressPtr works better. Ok. I will change it. >=20 > / > Leif >=20 > > + EFI_STATUS Status; > > + > > + ZeroMem (&RequestPacket, sizeof (RequestPacket)); > > + OperationCount =3D 0; > > + Operations =3D RequestPacket.Operation; > > + PtrAddress =3D Address; > > + > > + if (RegAddressWidthInBytes > ARRAY_SIZE (Address)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (RegAddressWidthInBytes !=3D 0) { > > + Operations[OperationCount].LengthInBytes =3D RegAddressWidthInByte= s; > > + Operations[OperationCount].Buffer =3D PtrAddress; > > + while (RegAddressWidthInBytes--) { > > + *PtrAddress++ =3D RegAddress >> (8 * RegAddressWidthInBytes); > > + } > > + OperationCount++; > > + } > > + > > + Operations[OperationCount].LengthInBytes =3D RegValueNumBytes; > > + Operations[OperationCount].Buffer =3D RegValue; > > + Operations[OperationCount].Flags =3D I2C_FLAG_READ; > > + OperationCount++; > > + > > + RequestPacket.OperationCount =3D OperationCount; > > + > > + Status =3D I2cBusXfer ( > > + Base, SlaveAddress, > > + (EFI_I2C_REQUEST_PACKET *)&RequestPacket > > + ); > > + > > + return Status; > > +} > > + > > diff --git a/Silicon/NXP/Library/I2cLib/I2cLib.inf > b/Silicon/NXP/Library/I2cLib/I2cLib.inf > > new file mode 100644 > > index 000000000000..b9bd79ac1ef1 > > --- /dev/null > > +++ b/Silicon/NXP/Library/I2cLib/I2cLib.inf > > @@ -0,0 +1,31 @@ > > +# @file > > +# > > +# Component description file for I2cLib module > > +# Copyright 2017, 2020 NXP > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +# > > + > > +[Defines] > > + INF_VERSION =3D 0x0001001A > > + BASE_NAME =3D I2cLib > > + FILE_GUID =3D 8ecefc8f-a2c4-4091-b81f-20f7aeb05= 67f > > + MODULE_TYPE =3D BASE > > + VERSION_STRING =3D 1.0 > > + LIBRARY_CLASS =3D I2cLib > > + > > +[Sources.common] > > + I2cLib.c > > + > > +[LibraryClasses] > > + IoLib > > + TimerLib > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + Silicon/NXP/NxpQoriqLs.dec > > + > > +[FeaturePcd] > > + gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203 > > + > > diff --git a/Silicon/NXP/Library/I2cLib/I2cLibInternal.h > b/Silicon/NXP/Library/I2cLib/I2cLibInternal.h > > new file mode 100644 > > index 000000000000..2ca4a3639d2c > > --- /dev/null > > +++ b/Silicon/NXP/Library/I2cLib/I2cLibInternal.h > > @@ -0,0 +1,105 @@ > > +/** @file > > + I2c Lib to control I2c controller. > > + > > + Copyright 2020 NXP > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef I2C_LIB_INTERNAL_H__ > > +#define I2C_LIB_INTERNAL_H__ > > + > > +#include > > +#include > > + > > +/** Module Disable > > + 0b - The module is enabled. You must clear this field before any oth= er IBCR > > + fields have any effect. > > + 1b - The module is reset and disabled. This is the power-on reset si= tuation. > > + When high, the interface is held in reset, but registers can st= ill be > > + accessed. Status register fields (IBSR) are not valid when the = module > > + is disabled. > > +**/ > > +#define I2C_IBCR_MDIS BIT7 > > +// I2c Bus Interrupt Enable > > +#define I2C_IBCR_IBIE BIT6 > > +/** Master / Slave Mode 0b - Slave mode 1b - Master mode > > + When you change this field from 0 to 1, the module generates a START > signal > > + on the bus and selects the master mode. When you change this field f= rom 1 > to > > + 0, the module generates a STOP signal and changes the operation mode > from > > + master to slave. You should generate a STOP signal only if IBSR[IBIF= ]=3D1. > > + The module clears this field without generating a STOP signal when t= he > > + master loses arbitration. > > +*/ > > +#define I2C_IBCR_MSSL BIT5 > > +// 0b - Receive 1b - Transmit > > +#define I2C_IBCR_TXRX BIT4 > > +/** Data acknowledge disable > > + Values written to this field are only used when the I2C module is a = receiver, > > + not a transmitter. > > + 0b - The module sends an acknowledge signal to the bus at the 9th cl= ock bit > > + after receiving one byte of data. > > + 1b - The module does not send an acknowledge-signal response (that i= s, > > + acknowledge bit =3D 1). > > +**/ > > +#define I2C_IBCR_NOACK BIT3 > > +/**Repeat START > > + If the I2C module is the current bus master, and you program RSTA=3D= 1, the > I2C > > + module generates a repeated START condition. This field always reads= as a 0. > > + If you attempt a repeated START at the wrong time, if the bus is own= ed by > > + another master the result is loss of arbitration. > > +**/ > > +#define I2C_IBCR_RSTA BIT2 > > +// DMA enable > > +#define I2C_IBCR_DMAEN BIT1 > > + > > +// Transfer Complete > > +#define I2C_IBSR_TCF BIT7 > > +// I2C bus Busy. 0b - Bus is idle, 1b - Bus is busy > > +#define I2C_IBSR_IBB BIT5 > > +// Arbitration Lost. software must clear this field by writing a one t= o it. > > +#define I2C_IBSR_IBAL BIT4 > > +// I2C bus interrupt flag > > +#define I2C_IBSR_IBIF BIT1 > > +// Received acknowledge 0b - Acknowledge received 1b - No acknowledge > received > > +#define I2C_IBSR_RXAK BIT0 > > + > > +//Bus idle interrupt enable > > +#define I2C_IBIC_BIIE BIT7 > > + > > +// Glitch filter enable > > +#define I2C_IBDBG_GLFLT_EN BIT3 > > + > > +#define I2C_BUS_TEST_BUSY TRUE > > +#define I2C_BUS_TEST_IDLE !I2C_BUS_TEST_BUSY > > +#define I2C_BUS_TEST_RX_ACK TRUE > > +#define I2C_BUS_NO_TEST_RX_ACK !I2C_BUS_TEST_RX_ACK > > + > > +#define ARRAY_LAST_ELEM(x) (x)[ARRAY_SIZE (x) - 1] > > +#define I2C_NUM_RETRIES 500 > > + > > +typedef struct _I2C_REGS { > > + UINT8 Ibad; // I2c Bus Address Register > > + UINT8 Ibfd; // I2c Bus Frequency Dividor Register > > + UINT8 Ibcr; // I2c Bus Control Register > > + UINT8 Ibsr; // I2c Bus Status Register > > + UINT8 Ibdr; // I2C Bus Data I/O Register > > + UINT8 Ibic; // I2C Bus Interrupt Config Register > > + UINT8 Ibdbg; // I2C Bus Debug Register > > +} I2C_REGS; > > + > > +/* > > + * sorted list of clock divisor, Ibfd register value pairs > > + */ > > +typedef struct _I2C_CLOCK_DIVISOR_PAIR { > > + UINT16 Divisor; > > + UINT16 Ibfd; // I2c Bus Frequency Dividor Register value > > +} I2C_CLOCK_DIVISOR_PAIR; > > + > > +typedef struct { > > + UINTN OperationCount; > > + EFI_I2C_OPERATION Operation[2]; > > +} I2C_REG_REQUEST; > > + > > +#endif // I2C_LIB_INTERNAL_H__ > > + > > diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec > > index 764b9bb0e2d3..4a1cfb3e278e 100644 > > --- a/Silicon/NXP/NxpQoriqLs.dec > > +++ b/Silicon/NXP/NxpQoriqLs.dec > > @@ -1,6 +1,6 @@ > > # @file. > > # > > -# Copyright 2017-2019 NXP > > +# Copyright 2017-2020 NXP > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > @@ -13,6 +13,10 @@ [Defines] > > [Includes] > > Include > > > > +[LibraryClasses] > > + ## @libraryclass Provides services to read/write to I2c devices > > + I2cLib|Include/Library/I2cLib.h > > + > > [Guids.common] > > gNxpQoriqLsTokenSpaceGuid =3D {0x98657342, 0x4aee, 0x4fc6, {0xb= c, 0xb5, > 0xff, 0x45, 0xb7, 0xa8, 0x71, 0xf2}} > > gNxpNonDiscoverableI2cMasterGuid =3D { 0x5f2c099c, 0x54a3, 0x4dd4, {= 0x9e, > 0xc5, 0xe9, 0x12, 0x8c, 0x36, 0x81, 0x6a}} > > @@ -101,3 +105,7 @@ [PcdsFixedAtBuild.common] > > > gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|FALSE|BOOLEAN|0x0000031 > 2 > > > gNxpQoriqLsTokenSpaceGuid.PcdWatchdogBigEndian|FALSE|BOOLEAN|0x0000 > 0313 > > > gNxpQoriqLsTokenSpaceGuid.PcdIfcBigEndian|FALSE|BOOLEAN|0x00000314 > > + > > +[PcdsFeatureFlag] > > + > gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203|FALSE|BOOLEAN|0x0000 > 0315 > > + > > -- > > 2.17.1 > >