aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorSyed Mohammed Khasim <x0khasim@ti.com>2008-11-21 16:39:45 -0500
committerTony Lindgren <tony@atomide.com>2008-11-21 16:39:45 -0500
commit4574eb6892a13bc91aac8676457d46798935d653 (patch)
treea73fea64da35f918cc472aee00ac9a1fb59c60c6 /drivers/i2c
parent0cbbcffdf5f30ef60d918549014684eada4f5b3f (diff)
i2c-omap: Add high-speed support to omap-i2c
Omap2430 has additional support for high-speed I2C. This patch moves I2C speed parameter (from module) to platform data. Also added basic High Speed support based on I2C bus speed. This patch is tested for high speed I2C (with TWL4030 Keypad) and works as expected. Also change the 2430 i2chs_fck names to use the standard naming. Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Syed Mohammed Khasim <x0khasim@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c82
1 files changed, 60 insertions, 22 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 5ca0e0010a0e..b0aa0f8b564b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -83,6 +83,7 @@
83/* I2C Configuration Register (OMAP_I2C_CON): */ 83/* I2C Configuration Register (OMAP_I2C_CON): */
84#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */ 84#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
85#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */ 85#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
86#define OMAP_I2C_CON_OPMODE (1 << 12) /* High Speed support */
86#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */ 87#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
87#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */ 88#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
88#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */ 89#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -91,6 +92,10 @@
91#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */ 92#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
92#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */ 93#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
93 94
95/* I2C SCL time value when Master */
96#define OMAP_I2C_SCLL_HSSCLL 8
97#define OMAP_I2C_SCLH_HSSCLH 8
98
94/* I2C System Test Register (OMAP_I2C_SYSTEST): */ 99/* I2C System Test Register (OMAP_I2C_SYSTEST): */
95#ifdef DEBUG 100#ifdef DEBUG
96#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ 101#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
@@ -109,12 +114,6 @@
109/* I2C System Configuration Register (OMAP_I2C_SYSC): */ 114/* I2C System Configuration Register (OMAP_I2C_SYSC): */
110#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */ 115#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
111 116
112/* REVISIT: Use platform_data instead of module parameters */
113/* Fast Mode = 400 kHz, Standard = 100 kHz */
114static int clock = 100; /* Default: 100 kHz */
115module_param(clock, int, 0);
116MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
117
118struct omap_i2c_dev { 117struct omap_i2c_dev {
119 struct device *dev; 118 struct device *dev;
120 void __iomem *base; /* virtual */ 119 void __iomem *base; /* virtual */
@@ -123,6 +122,7 @@ struct omap_i2c_dev {
123 struct clk *fclk; /* Functional clock */ 122 struct clk *fclk; /* Functional clock */
124 struct completion cmd_complete; 123 struct completion cmd_complete;
125 struct resource *ioarea; 124 struct resource *ioarea;
125 u32 speed; /* Speed of bus in Khz */
126 u16 cmd_err; 126 u16 cmd_err;
127 u8 *buf; 127 u8 *buf;
128 size_t buf_len; 128 size_t buf_len;
@@ -208,9 +208,11 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
208 208
209static int omap_i2c_init(struct omap_i2c_dev *dev) 209static int omap_i2c_init(struct omap_i2c_dev *dev)
210{ 210{
211 u16 psc = 0; 211 u16 psc = 0, scll = 0, sclh = 0;
212 u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
212 unsigned long fclk_rate = 12000000; 213 unsigned long fclk_rate = 12000000;
213 unsigned long timeout; 214 unsigned long timeout;
215 unsigned long internal_clk = 0;
214 216
215 if (!dev->rev1) { 217 if (!dev->rev1) {
216 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST); 218 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
@@ -253,18 +255,47 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
253 psc = fclk_rate / 12000000; 255 psc = fclk_rate / 12000000;
254 } 256 }
255 257
258 if (cpu_is_omap2430()) {
259
260 /* HSI2C controller internal clk rate should be 19.2 Mhz */
261 internal_clk = 19200;
262 fclk_rate = clk_get_rate(dev->fclk) / 1000;
263
264 /* Compute prescaler divisor */
265 psc = fclk_rate / internal_clk;
266 psc = psc - 1;
267
268 /* If configured for High Speed */
269 if (dev->speed > 400) {
270 /* For first phase of HS mode */
271 fsscll = internal_clk / (400 * 2) - 6;
272 fssclh = internal_clk / (400 * 2) - 6;
273
274 /* For second phase of HS mode */
275 hsscll = fclk_rate / (dev->speed * 2) - 6;
276 hssclh = fclk_rate / (dev->speed * 2) - 6;
277 } else {
278 /* To handle F/S modes */
279 fsscll = internal_clk / (dev->speed * 2) - 6;
280 fssclh = internal_clk / (dev->speed * 2) - 6;
281 }
282 scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
283 sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
284 } else {
285 /* Program desired operating rate */
286 fclk_rate /= (psc + 1) * 1000;
287 if (psc > 2)
288 psc = 2;
289 scll = fclk_rate / (dev->speed * 2) - 7 + psc;
290 sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
291 }
292
256 /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ 293 /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
257 omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); 294 omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
258 295
259 /* Program desired operating rate */ 296 /* SCL low and high time values */
260 fclk_rate /= (psc + 1) * 1000; 297 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
261 if (psc > 2) 298 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
262 psc = 2;
263
264 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
265 fclk_rate / (clock * 2) - 7 + psc);
266 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
267 fclk_rate / (clock * 2) - 7 + psc);
268 299
269 /* Take the I2C module out of reset: */ 300 /* Take the I2C module out of reset: */
270 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); 301 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
@@ -324,6 +355,11 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
324 dev->cmd_err = 0; 355 dev->cmd_err = 0;
325 356
326 w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; 357 w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
358
359 /* High speed configuration */
360 if (dev->speed > 400)
361 w |= OMAP_I2C_CON_OPMODE;
362
327 if (msg->flags & I2C_M_TEN) 363 if (msg->flags & I2C_M_TEN)
328 w |= OMAP_I2C_CON_XA; 364 w |= OMAP_I2C_CON_XA;
329 if (!(msg->flags & I2C_M_RD)) 365 if (!(msg->flags & I2C_M_RD))
@@ -564,6 +600,7 @@ omap_i2c_probe(struct platform_device *pdev)
564 struct i2c_adapter *adap; 600 struct i2c_adapter *adap;
565 struct resource *mem, *irq, *ioarea; 601 struct resource *mem, *irq, *ioarea;
566 int r; 602 int r;
603 u32 *speed = NULL;
567 604
568 /* NOTE: driver uses the static register mapping */ 605 /* NOTE: driver uses the static register mapping */
569 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 606 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -584,17 +621,18 @@ omap_i2c_probe(struct platform_device *pdev)
584 return -EBUSY; 621 return -EBUSY;
585 } 622 }
586 623
587 if (clock > 200)
588 clock = 400; /* Fast mode */
589 else
590 clock = 100; /* Standard mode */
591
592 dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL); 624 dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
593 if (!dev) { 625 if (!dev) {
594 r = -ENOMEM; 626 r = -ENOMEM;
595 goto err_release_region; 627 goto err_release_region;
596 } 628 }
597 629
630 if (pdev->dev.platform_data != NULL)
631 speed = (u32 *) pdev->dev.platform_data;
632 else
633 *speed = 100; /* Defualt speed */
634
635 dev->speed = *speed;
598 dev->dev = &pdev->dev; 636 dev->dev = &pdev->dev;
599 dev->irq = irq->start; 637 dev->irq = irq->start;
600 dev->base = ioremap(mem->start, mem->end - mem->start + 1); 638 dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -625,7 +663,7 @@ omap_i2c_probe(struct platform_device *pdev)
625 } 663 }
626 r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; 664 r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
627 dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", 665 dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
628 pdev->id, r >> 4, r & 0xf, clock); 666 pdev->id, r >> 4, r & 0xf, dev->speed);
629 667
630 adap = &dev->adapter; 668 adap = &dev->adapter;
631 i2c_set_adapdata(adap, dev); 669 i2c_set_adapdata(adap, dev);