diff options
-rw-r--r-- | arch/arm/mach-omap2/clock24xx.h | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 82 |
2 files changed, 62 insertions, 24 deletions
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 242a19d86ccd..e5fc5bf5ceeb 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h | |||
@@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = { | |||
2321 | }; | 2321 | }; |
2322 | 2322 | ||
2323 | static struct clk i2chs2_fck = { | 2323 | static struct clk i2chs2_fck = { |
2324 | .name = "i2chs_fck", | 2324 | .name = "i2c_fck", |
2325 | .id = 2, | 2325 | .id = 2, |
2326 | .parent = &func_96m_ck, | 2326 | .parent = &func_96m_ck, |
2327 | .flags = CLOCK_IN_OMAP243X, | 2327 | .flags = CLOCK_IN_OMAP243X, |
@@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = { | |||
2354 | }; | 2354 | }; |
2355 | 2355 | ||
2356 | static struct clk i2chs1_fck = { | 2356 | static struct clk i2chs1_fck = { |
2357 | .name = "i2chs_fck", | 2357 | .name = "i2c_fck", |
2358 | .id = 1, | 2358 | .id = 1, |
2359 | .parent = &func_96m_ck, | 2359 | .parent = &func_96m_ck, |
2360 | .flags = CLOCK_IN_OMAP243X, | 2360 | .flags = CLOCK_IN_OMAP243X, |
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 */ | ||
114 | static int clock = 100; /* Default: 100 kHz */ | ||
115 | module_param(clock, int, 0); | ||
116 | MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)"); | ||
117 | |||
118 | struct omap_i2c_dev { | 117 | struct 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 | ||
209 | static int omap_i2c_init(struct omap_i2c_dev *dev) | 209 | static 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); |