aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-sh_mobile.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-sh_mobile.c')
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 598c49acaeb5..f633a53b6dbe 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -32,6 +32,7 @@
32#include <linux/clk.h> 32#include <linux/clk.h>
33#include <linux/io.h> 33#include <linux/io.h>
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/i2c/i2c-sh_mobile.h>
35 36
36/* Transmit operation: */ 37/* Transmit operation: */
37/* */ 38/* */
@@ -117,7 +118,7 @@ struct sh_mobile_i2c_data {
117 struct device *dev; 118 struct device *dev;
118 void __iomem *reg; 119 void __iomem *reg;
119 struct i2c_adapter adap; 120 struct i2c_adapter adap;
120 121 unsigned long bus_speed;
121 struct clk *clk; 122 struct clk *clk;
122 u_int8_t icic; 123 u_int8_t icic;
123 u_int8_t iccl; 124 u_int8_t iccl;
@@ -205,7 +206,7 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
205 * We also round off the result. 206 * We also round off the result.
206 */ 207 */
207 num = i2c_clk * 5; 208 num = i2c_clk * 5;
208 denom = NORMAL_SPEED * 9; 209 denom = pd->bus_speed * 9;
209 tmp = num * 10 / denom; 210 tmp = num * 10 / denom;
210 if (tmp % 10 >= 5) 211 if (tmp % 10 >= 5)
211 pd->iccl = (u_int8_t)((num/denom) + 1); 212 pd->iccl = (u_int8_t)((num/denom) + 1);
@@ -538,15 +539,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
538{ 539{
539 struct resource *res; 540 struct resource *res;
540 int ret = -ENXIO; 541 int ret = -ENXIO;
541 int q, m; 542 int n, k = 0;
542 int k = 0;
543 int n = 0;
544 543
545 while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { 544 while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
546 for (n = res->start; hook && n <= res->end; n++) { 545 for (n = res->start; hook && n <= res->end; n++) {
547 if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, 546 if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
548 dev_name(&dev->dev), dev)) 547 dev_name(&dev->dev), dev)) {
548 for (n--; n >= res->start; n--)
549 free_irq(n, dev);
550
549 goto rollback; 551 goto rollback;
552 }
550 } 553 }
551 k++; 554 k++;
552 } 555 }
@@ -554,16 +557,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
554 if (hook) 557 if (hook)
555 return k > 0 ? 0 : -ENOENT; 558 return k > 0 ? 0 : -ENOENT;
556 559
557 k--;
558 ret = 0; 560 ret = 0;
559 561
560 rollback: 562 rollback:
561 for (q = k; k >= 0; k--) { 563 k--;
562 for (m = n; m >= res->start; m--) 564
563 free_irq(m, dev); 565 while (k >= 0) {
566 res = platform_get_resource(dev, IORESOURCE_IRQ, k);
567 for (n = res->start; n <= res->end; n++)
568 free_irq(n, dev);
564 569
565 res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1); 570 k--;
566 m = res->end;
567 } 571 }
568 572
569 return ret; 573 return ret;
@@ -571,10 +575,10 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
571 575
572static int sh_mobile_i2c_probe(struct platform_device *dev) 576static int sh_mobile_i2c_probe(struct platform_device *dev)
573{ 577{
578 struct i2c_sh_mobile_platform_data *pdata = dev->dev.platform_data;
574 struct sh_mobile_i2c_data *pd; 579 struct sh_mobile_i2c_data *pd;
575 struct i2c_adapter *adap; 580 struct i2c_adapter *adap;
576 struct resource *res; 581 struct resource *res;
577 char clk_name[8];
578 int size; 582 int size;
579 int ret; 583 int ret;
580 584
@@ -584,10 +588,9 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
584 return -ENOMEM; 588 return -ENOMEM;
585 } 589 }
586 590
587 snprintf(clk_name, sizeof(clk_name), "i2c%d", dev->id); 591 pd->clk = clk_get(&dev->dev, NULL);
588 pd->clk = clk_get(&dev->dev, clk_name);
589 if (IS_ERR(pd->clk)) { 592 if (IS_ERR(pd->clk)) {
590 dev_err(&dev->dev, "cannot get clock \"%s\"\n", clk_name); 593 dev_err(&dev->dev, "cannot get clock\n");
591 ret = PTR_ERR(pd->clk); 594 ret = PTR_ERR(pd->clk);
592 goto err; 595 goto err;
593 } 596 }
@@ -617,6 +620,11 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
617 goto err_irq; 620 goto err_irq;
618 } 621 }
619 622
623 /* Use platformd data bus speed or NORMAL_SPEED */
624 pd->bus_speed = NORMAL_SPEED;
625 if (pdata && pdata->bus_speed)
626 pd->bus_speed = pdata->bus_speed;
627
620 /* The IIC blocks on SH-Mobile ARM processors 628 /* The IIC blocks on SH-Mobile ARM processors
621 * come with two new bits in ICIC. 629 * come with two new bits in ICIC.
622 */ 630 */
@@ -657,6 +665,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
657 goto err_all; 665 goto err_all;
658 } 666 }
659 667
668 dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n",
669 adap->nr, pd->bus_speed);
660 return 0; 670 return 0;
661 671
662 err_all: 672 err_all:
@@ -726,3 +736,4 @@ module_exit(sh_mobile_i2c_adap_exit);
726MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); 736MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
727MODULE_AUTHOR("Magnus Damm"); 737MODULE_AUTHOR("Magnus Damm");
728MODULE_LICENSE("GPL v2"); 738MODULE_LICENSE("GPL v2");
739MODULE_ALIAS("platform:i2c-sh_mobile");