diff options
| -rw-r--r-- | drivers/i2c/omap24xx_i2c.c | 74 | ||||
| -rw-r--r-- | include/asm-arm/arch-omap24xx/i2c.h | 44 | ||||
| -rw-r--r-- | include/asm-arm/arch-omap3/i2c.h | 70 | 
3 files changed, 174 insertions, 14 deletions
| diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 678460325..1a4c8c9ad 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -31,7 +31,69 @@ static void flush_fifo(void);  void i2c_init (int speed, int slaveadd)  { -	u16 scl; +	int psc, fsscll, fssclh; +	int hsscll = 0, hssclh = 0; +	u32 scll, sclh; + +	/* Only handle standard, fast and high speeds */ +	if ((speed != OMAP_I2C_STANDARD) && +	    (speed != OMAP_I2C_FAST_MODE) && +	    (speed != OMAP_I2C_HIGH_SPEED)) { +		printf("Error : I2C unsupported speed %d\n", speed); +		return; +	} + +	psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK; +	psc -= 1; +	if (psc < I2C_PSC_MIN) { +		printf("Error : I2C unsupported prescalar %d\n", psc); +		return; +	} + +	if (speed == OMAP_I2C_HIGH_SPEED) { +		/* High speed */ + +		/* For first phase of HS mode */ +		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / +			(2 * OMAP_I2C_FAST_MODE); + +		fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM; +		fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM; +		if (((fsscll < 0) || (fssclh < 0)) || +		    ((fsscll > 255) || (fssclh > 255))) { +			printf("Error : I2C initializing first phase clock\n"); +			return; +		} + +		/* For second phase of HS mode */ +		hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); + +		hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM; +		hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM; +		if (((fsscll < 0) || (fssclh < 0)) || +		    ((fsscll > 255) || (fssclh > 255))) { +			printf("Error : I2C initializing second phase clock\n"); +			return; +		} + +		scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll; +		sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh; + +	} else { +		/* Standard and fast speed */ +		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); + +		fsscll -= I2C_FASTSPEED_SCLL_TRIM; +		fssclh -= I2C_FASTSPEED_SCLH_TRIM; +		if (((fsscll < 0) || (fssclh < 0)) || +		    ((fsscll > 255) || (fssclh > 255))) { +			printf("Error : I2C initializing clock\n"); +			return; +		} + +		scll = (unsigned int)fsscll; +		sclh = (unsigned int)fssclh; +	}  	writew(0x2, I2C_SYSC); /* for ES2 after soft reset */  	udelay(1000); @@ -42,12 +104,10 @@ void i2c_init (int speed, int slaveadd)  		udelay (50000);  	} -	/* 12MHz I2C module clock */ -	writew (0, I2C_PSC); -	speed = speed/1000;		    /* 100 or 400 */ -	scl = ((12000/(speed*2)) - 7);	/* use 7 when PSC = 0 */ -	writew (scl, I2C_SCLL); -	writew (scl, I2C_SCLH); +	writew(psc, I2C_PSC); +	writew(scll, I2C_SCLL); +	writew(sclh, I2C_SCLH); +  	/* own address */  	writew (slaveadd, I2C_OA);  	writew (I2C_CON_EN, I2C_CON); diff --git a/include/asm-arm/arch-omap24xx/i2c.h b/include/asm-arm/arch-omap24xx/i2c.h index 7248950e5..44db7a2d4 100644 --- a/include/asm-arm/arch-omap24xx/i2c.h +++ b/include/asm-arm/arch-omap24xx/i2c.h @@ -104,4 +104,48 @@  #define I2C_SYSTEST_SDA_I       (1 << 1)        /* SDA line sense input value */  #define I2C_SYSTEST_SDA_O       (1 << 0)        /* SDA line drive output value */ +/* These values were copied from omap3, include/asm-arm/arch-omap3/i2c.h. */ +#define OMAP_I2C_STANDARD		100000 +#define OMAP_I2C_FAST_MODE		400000 +#define OMAP_I2C_HIGH_SPEED		3400000 + +#define SYSTEM_CLOCK_12			12000000 +#define SYSTEM_CLOCK_13			13000000 +#define SYSTEM_CLOCK_192		19200000 +#define SYSTEM_CLOCK_96			96000000 + +#ifndef I2C_IP_CLK +#define I2C_IP_CLK			SYSTEM_CLOCK_96 +#endif + +#ifndef I2C_INTERNAL_SAMPLING_CLK +#define I2C_INTERNAL_SAMPLING_CLK	19200000 +#endif + +/* These are the trim values for standard and fast speed */ +#ifndef I2C_FASTSPEED_SCLL_TRIM +#define I2C_FASTSPEED_SCLL_TRIM		6 +#endif +#ifndef I2C_FASTSPEED_SCLH_TRIM +#define I2C_FASTSPEED_SCLH_TRIM		6 +#endif + +/* These are the trim values for high speed */ +#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM +#define I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM +#endif +#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM +#define I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM +#endif +#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM +#define I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM +#endif +#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM +#define I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM +#endif + +#define I2C_PSC_MAX			0x0f +#define I2C_PSC_MIN			0x00 + +  #endif diff --git a/include/asm-arm/arch-omap3/i2c.h b/include/asm-arm/arch-omap3/i2c.h index 3937f3525..8b339cce9 100644 --- a/include/asm-arm/arch-omap3/i2c.h +++ b/include/asm-arm/arch-omap3/i2c.h @@ -112,16 +112,72 @@  #define I2C_SCLH_HSSCLH		8  #define I2C_SCLH_HSSCLH_M	0xFF -#define OMAP_I2C_STANDARD	100 -#define OMAP_I2C_FAST_MODE	400 -#define OMAP_I2C_HIGH_SPEED	3400 +#define OMAP_I2C_STANDARD	100000 +#define OMAP_I2C_FAST_MODE	400000 +#define OMAP_I2C_HIGH_SPEED	3400000 -#define SYSTEM_CLOCK_12		12000 -#define SYSTEM_CLOCK_13		13000 -#define SYSTEM_CLOCK_192	19200 -#define SYSTEM_CLOCK_96		96000 +#define SYSTEM_CLOCK_12		12000000 +#define SYSTEM_CLOCK_13		13000000 +#define SYSTEM_CLOCK_192	19200000 +#define SYSTEM_CLOCK_96		96000000 +/* Use the reference value of 96MHz if not explicitly set by the board */ +#ifndef I2C_IP_CLK  #define I2C_IP_CLK		SYSTEM_CLOCK_96 +#endif + +/* + * The reference minimum clock for high speed is 19.2MHz. + * The linux 2.6.30 kernel uses this value. + * The reference minimum clock for fast mode is 9.6MHz + * The reference minimum clock for standard mode is 4MHz + * In TRM, the value of 12MHz is used. + */ +#ifndef I2C_INTERNAL_SAMPLING_CLK +#define I2C_INTERNAL_SAMPLING_CLK	19200000 +#endif + +/* + * The equation for the low and high time is + * tlow = scll + scll_trim = (sampling clock * tlow_duty) / speed + * thigh = sclh + sclh_trim = (sampling clock * (1 - tlow_duty)) / speed + * + * If the duty cycle is 50% + * + * tlow = scll + scll_trim = sampling clock / (2 * speed) + * thigh = sclh + sclh_trim = sampling clock / (2 * speed) + * + * In TRM + * scll_trim = 7 + * sclh_trim = 5 + * + * The linux 2.6.30 kernel uses + * scll_trim = 6 + * sclh_trim = 6 + * + * These are the trim values for standard and fast speed + */ +#ifndef I2C_FASTSPEED_SCLL_TRIM +#define I2C_FASTSPEED_SCLL_TRIM		6 +#endif +#ifndef I2C_FASTSPEED_SCLH_TRIM +#define I2C_FASTSPEED_SCLH_TRIM		6 +#endif + +/* These are the trim values for high speed */ +#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM +#define I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM +#endif +#ifndef I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM +#define I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM +#endif +#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM +#define I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM	I2C_FASTSPEED_SCLL_TRIM +#endif +#ifndef I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM +#define I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM	I2C_FASTSPEED_SCLH_TRIM +#endif +  #define I2C_PSC_MAX		0x0f  #define I2C_PSC_MIN		0x00 |