#include "omap24xx_i2c.h"
-DECLARE_GLOBAL_DATA_PTR;
-
#define I2C_TIMEOUT 1000
/* Absolutely safe for status update at 100 kHz 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;
}
/*
u16 stat;
writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/
-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+#if defined(CONFIG_OMAP34XX)
while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
#else
/* Read RAW status */
do {
udelay(waitdelay);
-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+#if defined(CONFIG_OMAP34XX)
status = readw(&i2c_base->stat);
#else
/* Read RAW status */
/* own address */
writew(slaveadd, &i2c_base->oa);
-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+#if defined(CONFIG_OMAP34XX)
/*
* Have to enable interrupts for OMAP2/3, these IPs don't have
* an 'irqstatus_raw' register and we shall have to poll 'stat'
case 1:
return (struct i2c *)I2C_BASE2;
break;
-#if (I2C_BUS_MAX > 2)
+#if (CONFIG_SYS_I2C_BUS_MAX > 2)
case 2:
return (struct i2c *)I2C_BASE3;
break;
-#if (I2C_BUS_MAX > 3)
+#if (CONFIG_SYS_I2C_BUS_MAX > 3)
case 3:
return (struct i2c *)I2C_BASE4;
break;
-#if (I2C_BUS_MAX > 4)
+#if (CONFIG_SYS_I2C_BUS_MAX > 4)
case 4:
return (struct i2c *)I2C_BASE5;
break;
ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay);
if (ret) {
- error("%s: set i2c speed failed\n", __func__);
+ pr_err("%s: set i2c speed failed\n", __func__);
return ret;
}
CONFIG_SYS_OMAP24_I2C_SPEED1,
CONFIG_SYS_OMAP24_I2C_SLAVE1,
1)
-#if (I2C_BUS_MAX > 2)
+#if (CONFIG_SYS_I2C_BUS_MAX > 2)
#if !defined(CONFIG_SYS_OMAP24_I2C_SPEED2)
#define CONFIG_SYS_OMAP24_I2C_SPEED2 CONFIG_SYS_OMAP24_I2C_SPEED
#endif
CONFIG_SYS_OMAP24_I2C_SPEED2,
CONFIG_SYS_OMAP24_I2C_SLAVE2,
2)
-#if (I2C_BUS_MAX > 3)
+#if (CONFIG_SYS_I2C_BUS_MAX > 3)
#if !defined(CONFIG_SYS_OMAP24_I2C_SPEED3)
#define CONFIG_SYS_OMAP24_I2C_SPEED3 CONFIG_SYS_OMAP24_I2C_SPEED
#endif
CONFIG_SYS_OMAP24_I2C_SPEED3,
CONFIG_SYS_OMAP24_I2C_SLAVE3,
3)
-#if (I2C_BUS_MAX > 4)
+#if (CONFIG_SYS_I2C_BUS_MAX > 4)
#if !defined(CONFIG_SYS_OMAP24_I2C_SPEED4)
#define CONFIG_SYS_OMAP24_I2C_SPEED4 CONFIG_SYS_OMAP24_I2C_SPEED
#endif
{
struct omap_i2c *priv = dev_get_priv(bus);
- priv->regs = map_physmem(dev_get_addr(bus), sizeof(void *),
+ priv->regs = map_physmem(devfdt_get_addr(bus), sizeof(void *),
MAP_NOCACHE);
priv->speed = CONFIG_SYS_OMAP24_I2C_SPEED;
};
static const struct udevice_id omap_i2c_ids[] = {
+ { .compatible = "ti,omap3-i2c" },
{ .compatible = "ti,omap4-i2c" },
{ }
};