From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heiko Schocher Date: Mon, 27 Mar 2017 10:46:57 +0200 Subject: [U-Boot] [PATCH 2/2] i2c: ti: Update method to calculate psc, sscl and ssch I2C parameters In-Reply-To: <20170327100453.544523da@jawa> References: <1489593563-17749-1-git-send-email-lukma@denx.de> <1489593563-17749-2-git-send-email-lukma@denx.de> <20170327100453.544523da@jawa> Message-ID: <58D8D181.5060808@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello Lukasz, Am 27.03.2017 um 10:04 schrieb Lukasz Majewski: > Dear All, > >> This patch updates the way in which psc, sscl and ssch I2C parameters >> are calculated to be in sync with v4.9 Linux kernel >> SHA1: 69973b830859bc6529a7a0468ba0d80ee5117826 >> in the ./drivers/i2c/busses/i2c-omap.c > > Any comments on this? I am fine with it, it is in my queue for sending a pull request to Tom. bye, Heiko > >> >> The previous method was causing several issues: >> - The internal I2C frequency (after prescaler) was far above >> recommended one (7 - 12 MHz [*]) - the current approach brings better >> noise suppression (as stated in Linux commit: SHA1: >> 84bf2c868f3ca996e5bb) >> >> - The values calculated (psc, sscl and ssch) were far from optimal, >> which caused on the test platform (AM57xx) the I2C0 SCL signal low >> time (Fast Mode) of ~1.0us (the standard requires > 1.3 us). >> >> [*] for AM57xx TRM SPRUHZ6G, Table 24,7 >> "HS I2C Register Values for Maximum I2C Bit Rates in I2C F/S, I2C HS >> Modes" >> >> Signed-off-by: Lukasz Majewski >> --- >> drivers/i2c/omap24xx_i2c.c | 66 >> ++++++++++++++++++++++++++++------------------ 1 file changed, 41 >> insertions(+), 25 deletions(-) >> >> diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c >> index 0006343..26996e9 100644 >> --- a/drivers/i2c/omap24xx_i2c.c >> +++ b/drivers/i2c/omap24xx_i2c.c >> @@ -64,36 +64,52 @@ struct omap_i2c { >> >> static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) >> { >> - unsigned int sampleclk, prescaler; >> - int fsscll, fssclh; >> + unsigned long internal_clk = 0, fclk; >> + unsigned int prescaler; >> >> - speed <<= 1; >> - prescaler = 0; >> /* >> - * some divisors may cause a precission loss, but shouldn't >> - * be a big thing, because i2c_clk is then allready very >> slow. >> + * This method is only called for Standard and Fast Mode >> speeds >> + * >> + * For some TI SoCs it is explicitly written in TRM (e,g, >> SPRUHZ6G, >> + * page 5685, Table 24-7) >> + * that the internal I2C clock (after prescaler) should be >> between >> + * 7-12 MHz (at least for Fast Mode (FS)). >> + * >> + * Such approach is used in v4.9 Linux kernel in: >> + * ./drivers/i2c/busses/i2c-omap.c (omap_i2c_init function). >> */ >> - while (prescaler <= 0xFF) { >> - sampleclk = I2C_IP_CLK / (prescaler+1); >> >> - fsscll = sampleclk / speed; >> - fssclh = fsscll; >> - fsscll -= I2C_FASTSPEED_SCLL_TRIM; >> - fssclh -= I2C_FASTSPEED_SCLH_TRIM; >> - >> - if (((fsscll > 0) && (fssclh > 0)) && >> - ((fsscll <= (255-I2C_FASTSPEED_SCLL_TRIM)) && >> - (fssclh <= (255-I2C_FASTSPEED_SCLH_TRIM)))) { >> - if (pscl) >> - *pscl = fsscll; >> - if (psch) >> - *psch = fssclh; >> - >> - return prescaler; >> - } >> - prescaler++; >> + speed /= 1000; /* convert speed to kHz */ >> + >> + if (speed > 100) >> + internal_clk = 9600; >> + else >> + internal_clk = 4000; >> + >> + fclk = I2C_IP_CLK / 1000; >> + prescaler = fclk / internal_clk; >> + prescaler = prescaler - 1; >> + >> + if (speed > 100) { >> + unsigned long scl; >> + >> + /* Fast mode */ >> + scl = internal_clk / speed; >> + *pscl = scl - (scl / 3) - I2C_FASTSPEED_SCLL_TRIM; >> + *psch = (scl / 3) - I2C_FASTSPEED_SCLH_TRIM; >> + } else { >> + /* Standard mode */ >> + *pscl = internal_clk / (speed * 2) - >> I2C_FASTSPEED_SCLL_TRIM; >> + *psch = internal_clk / (speed * 2) - >> I2C_FASTSPEED_SCLH_TRIM; } >> - return -1; >> + >> + debug("%s: speed [kHz]: %d psc: 0x%x sscl: 0x%x ssch: >> 0x%x\n", >> + __func__, speed, prescaler, *pscl, *psch); >> + >> + if (*pscl <= 0 || *psch <= 0 || prescaler <= 0) >> + return -EINVAL; >> + >> + return prescaler; >> } >> >> /* > > > > > Best regards, > > Lukasz Majewski > > -- > > DENX Software Engineering GmbH, Managing Director: Wolfgang Denk > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany > Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de > -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany