aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorFugang Duan <B38611@freescale.com>2014-05-19 22:21:45 -0400
committerWolfram Sang <wsa@the-dreams.de>2014-06-02 13:18:33 -0400
commit9b2a6da33ccb1bc0d68f4319cef7c7299727ac4d (patch)
tree7a8f88926c912c9f23d96432260cf23795703e60 /drivers/i2c/busses
parent054b62d9f25c903958749e4cea25261324a7a2a4 (diff)
i2c: imx: update i2c clock divider for each transaction
Since IMX serial SOCs support low bus freq mode, some clocks freq may change to save power. I2C needs to check the clock source and update the divider. For example: i.MX6SL I2C clk is from IPG_PERCLK which is sourced from IPG_CLK. Under normal operation, IPG_CLK is 66MHz, ipg_perclk is at 22MHz. In low bus freq mode, IPG_CLK is at 12MHz and IPG_PERCLK is down to 4MHz. So the I2C driver must update the divider register for each transaction when the current IPG_PERCLK is not equal to the clock of previous transaction. Signed-off-by: Fugang Duan <B38611@freescale.com> [wsa: removed an outdated comment and simplified debug output] Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r--drivers/i2c/busses/i2c-imx.c93
1 files changed, 49 insertions, 44 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 5f4bc7008251..fe53207a6ebb 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -183,6 +183,8 @@ struct imx_i2c_struct {
183 unsigned int disable_delay; 183 unsigned int disable_delay;
184 int stopped; 184 int stopped;
185 unsigned int ifdr; /* IMX_I2C_IFDR */ 185 unsigned int ifdr; /* IMX_I2C_IFDR */
186 unsigned int cur_clk;
187 unsigned int bitrate;
186 const struct imx_i2c_hwdata *hwdata; 188 const struct imx_i2c_hwdata *hwdata;
187}; 189};
188 190
@@ -305,6 +307,48 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
305 return 0; 307 return 0;
306} 308}
307 309
310static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
311{
312 struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
313 unsigned int i2c_clk_rate;
314 unsigned int div;
315 int i;
316
317 /* Divider value calculation */
318 i2c_clk_rate = clk_get_rate(i2c_imx->clk);
319 if (i2c_imx->cur_clk == i2c_clk_rate)
320 return;
321 else
322 i2c_imx->cur_clk = i2c_clk_rate;
323
324 div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate;
325 if (div < i2c_clk_div[0].div)
326 i = 0;
327 else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
328 i = i2c_imx->hwdata->ndivs - 1;
329 else
330 for (i = 0; i2c_clk_div[i].div < div; i++);
331
332 /* Store divider value */
333 i2c_imx->ifdr = i2c_clk_div[i].val;
334
335 /*
336 * There dummy delay is calculated.
337 * It should be about one I2C clock period long.
338 * This delay is used in I2C bus disable function
339 * to fix chip hardware bug.
340 */
341 i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
342 + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
343
344#ifdef CONFIG_I2C_DEBUG_BUS
345 dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n",
346 i2c_clk_rate, div);
347 dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
348 i2c_clk_div[i].val, i2c_clk_div[i].div);
349#endif
350}
351
308static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) 352static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
309{ 353{
310 unsigned int temp = 0; 354 unsigned int temp = 0;
@@ -312,6 +356,8 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
312 356
313 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); 357 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
314 358
359 i2c_imx_set_clk(i2c_imx);
360
315 result = clk_prepare_enable(i2c_imx->clk); 361 result = clk_prepare_enable(i2c_imx->clk);
316 if (result) 362 if (result)
317 return result; 363 return result;
@@ -367,45 +413,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
367 clk_disable_unprepare(i2c_imx->clk); 413 clk_disable_unprepare(i2c_imx->clk);
368} 414}
369 415
370static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
371 unsigned int rate)
372{
373 struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
374 unsigned int i2c_clk_rate;
375 unsigned int div;
376 int i;
377
378 /* Divider value calculation */
379 i2c_clk_rate = clk_get_rate(i2c_imx->clk);
380 div = (i2c_clk_rate + rate - 1) / rate;
381 if (div < i2c_clk_div[0].div)
382 i = 0;
383 else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
384 i = i2c_imx->hwdata->ndivs - 1;
385 else
386 for (i = 0; i2c_clk_div[i].div < div; i++);
387
388 /* Store divider value */
389 i2c_imx->ifdr = i2c_clk_div[i].val;
390
391 /*
392 * There dummy delay is calculated.
393 * It should be about one I2C clock period long.
394 * This delay is used in I2C bus disable function
395 * to fix chip hardware bug.
396 */
397 i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
398 + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
399
400 /* dev_dbg() can't be used, because adapter is not yet registered */
401#ifdef CONFIG_I2C_DEBUG_BUS
402 dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
403 __func__, i2c_clk_rate, div);
404 dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
405 __func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
406#endif
407}
408
409static irqreturn_t i2c_imx_isr(int irq, void *dev_id) 416static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
410{ 417{
411 struct imx_i2c_struct *i2c_imx = dev_id; 418 struct imx_i2c_struct *i2c_imx = dev_id;
@@ -644,7 +651,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
644 struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); 651 struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
645 void __iomem *base; 652 void __iomem *base;
646 int irq, ret; 653 int irq, ret;
647 u32 bitrate;
648 654
649 dev_dbg(&pdev->dev, "<%s>\n", __func__); 655 dev_dbg(&pdev->dev, "<%s>\n", __func__);
650 656
@@ -708,12 +714,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
708 i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); 714 i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
709 715
710 /* Set up clock divider */ 716 /* Set up clock divider */
711 bitrate = IMX_I2C_BIT_RATE; 717 i2c_imx->bitrate = IMX_I2C_BIT_RATE;
712 ret = of_property_read_u32(pdev->dev.of_node, 718 ret = of_property_read_u32(pdev->dev.of_node,
713 "clock-frequency", &bitrate); 719 "clock-frequency", &i2c_imx->bitrate);
714 if (ret < 0 && pdata && pdata->bitrate) 720 if (ret < 0 && pdata && pdata->bitrate)
715 bitrate = pdata->bitrate; 721 i2c_imx->bitrate = pdata->bitrate;
716 i2c_imx_set_clk(i2c_imx, bitrate);
717 722
718 /* Set up chip registers to defaults */ 723 /* Set up chip registers to defaults */
719 imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, 724 imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,