svn commit: r232213 - projects/armv6/sys/arm/ti
Damjan Marion
dmarion at FreeBSD.org
Mon Feb 27 15:14:37 UTC 2012
Author: dmarion
Date: Mon Feb 27 15:14:36 2012
New Revision: 232213
URL: http://svn.freebsd.org/changeset/base/232213
Log:
ti_i2c: allow different clock configuration on different SoCs
Approved by: cognet (mentor)
Modified:
projects/armv6/sys/arm/ti/ti_i2c.c
Modified: projects/armv6/sys/arm/ti/ti_i2c.c
==============================================================================
--- projects/armv6/sys/arm/ti/ti_i2c.c Mon Feb 27 14:12:49 2012 (r232212)
+++ projects/armv6/sys/arm/ti/ti_i2c.c Mon Feb 27 15:14:36 2012 (r232213)
@@ -95,6 +95,34 @@ struct ti_i2c_softc
uint16_t sc_rev;
};
+struct ti_i2c_clock_config
+{
+ int speed;
+ int bitrate;
+ uint8_t psc; /* Fast/Standard mode prescale divider */
+ uint8_t scll; /* Fast/Standard mode SCL low time */
+ uint8_t sclh; /* Fast/Standard mode SCL high time */
+ uint8_t hsscll; /* High Speed mode SCL low time */
+ uint8_t hssclh; /* High Speed mode SCL high time */
+};
+
+static struct ti_i2c_clock_config ti_i2c_clock_configs[] = {
+
+#if defined(SOC_OMAP4)
+ { IIC_SLOW, 100000, 23, 13, 15, 0, 0},
+ { IIC_FAST, 400000, 9, 5, 7, 0, 0},
+ { IIC_FASTEST, 3310000, 1, 113, 115, 7, 10},
+#elif defined(SOC_TI_AM335X)
+ { IIC_SLOW, 100000, 3, 53, 55, 0, 0},
+ { IIC_FAST, 400000, 3, 8, 10, 0, 0},
+ { IIC_FASTEST, 400000, 3, 8, 10, 0, 0}, /* This might be higher */
+#else
+#error "TI I2C driver is not supported on this SoC"
+#endif
+ { -1, 0 }
+};
+
+
#define TI_I2C_REV1 0x003C /* OMAP3 */
#define TI_I2C_REV2 0x000A /* OMAP4 */
@@ -246,7 +274,20 @@ static int
ti_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
{
struct ti_i2c_softc *sc = device_get_softc(dev);
- uint16_t psc_reg, scll_reg, sclh_reg, con_reg;
+ struct ti_i2c_clock_config *clkcfg;
+ uint16_t con_reg;
+
+ clkcfg = ti_i2c_clock_configs;
+ while (clkcfg->speed != -1) {
+ if (clkcfg->speed == speed)
+ break;
+ /* take slow if speed is unknown */
+ if ((speed == IIC_UNKNOWN) && (clkcfg->speed == IIC_SLOW))
+ break;
+ clkcfg++;
+ }
+ if (clkcfg->speed == -1)
+ return (EINVAL);
TI_I2C_LOCK(sc);
@@ -254,56 +295,28 @@ ti_i2c_reset(device_t dev, u_char speed,
*oldaddr = sc->sc_i2c_addr;
sc->sc_i2c_addr = addr;
- /* The header file doesn't actual tell you what speeds should be used for
- * the 3 possible settings, so I'm going to go with the usual:
- *
- * IIC_SLOW => 100kbps
- * IIC_FAST => 400kbps
- * IIC_FASTEST => 3.4Mbps
- *
- * I2Ci_INTERNAL_CLK = I2Ci_FCLK / (PSC + 1)
- * I2Ci_INTERNAL_CLK = 96MHZ / (PSC + 1)
- */
- switch (speed) {
- case IIC_FASTEST:
- psc_reg = 0x0004;
- scll_reg = 0x0811;
- sclh_reg = 0x0a13;
- break;
-
- case IIC_FAST:
- psc_reg = 0x0009;
- scll_reg = 0x0005;
- sclh_reg = 0x0007;
- break;
-
- case IIC_SLOW:
- case IIC_UNKNOWN:
- default:
- psc_reg = 0x0017;
- scll_reg = 0x000D;
- sclh_reg = 0x000F;
- break;
- }
-
/* First disable the controller while changing the clocks */
con_reg = ti_i2c_read_reg(sc, I2C_REG_CON);
ti_i2c_write_reg(sc, I2C_REG_CON, 0x0000);
/* Program the prescaler */
- ti_i2c_write_reg(sc, I2C_REG_PSC, psc_reg);
+ ti_i2c_write_reg(sc, I2C_REG_PSC, clkcfg->psc);
/* Set the bitrate */
- ti_i2c_write_reg(sc, I2C_REG_SCLL, scll_reg);
- ti_i2c_write_reg(sc, I2C_REG_SCLH, sclh_reg);
+ ti_i2c_write_reg(sc, I2C_REG_SCLL, clkcfg->scll | (clkcfg->hsscll<<8));
+ ti_i2c_write_reg(sc, I2C_REG_SCLH, clkcfg->sclh | (clkcfg->hssclh<<8));
/* Set the remote slave address */
ti_i2c_write_reg(sc, I2C_REG_SA, addr);
+ /* Check if we are dealing with high speed mode */
+ if ((clkcfg->hsscll + clkcfg->hssclh) > 0)
+ con_reg = I2C_CON_OPMODE_HS;
+ else
+ con_reg = I2C_CON_OPMODE_STD;
+
/* Enable the I2C module again */
- con_reg = I2C_CON_I2C_EN;
- con_reg |= (speed == IIC_FASTEST) ? I2C_CON_OPMODE_HS : I2C_CON_OPMODE_STD;
- ti_i2c_write_reg(sc, I2C_REG_CON, con_reg);
+ ti_i2c_write_reg(sc, I2C_REG_CON, I2C_CON_I2C_EN | con_reg);
TI_I2C_UNLOCK(sc);
More information about the svn-src-projects
mailing list