aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/i2c/mrvl-i2c.txt19
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c133
2 files changed, 146 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt b/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
index b891ee218354..0f7945019f6f 100644
--- a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
@@ -1,4 +1,4 @@
1* I2C 1* Marvell MMP I2C controller
2 2
3Required properties : 3Required properties :
4 4
@@ -32,3 +32,20 @@ Examples:
32 interrupts = <58>; 32 interrupts = <58>;
33 }; 33 };
34 34
35* Marvell MV64XXX I2C controller
36
37Required properties :
38
39 - reg : Offset and length of the register set for the device
40 - compatible : Should be "marvell,mv64xxx-i2c"
41 - interrupts : The interrupt number
42 - clock-frequency : Desired I2C bus clock frequency in Hz.
43
44Examples:
45
46 i2c@11000 {
47 compatible = "marvell,mv64xxx-i2c";
48 reg = <0x11000 0x20>;
49 interrupts = <29>;
50 clock-frequency = <100000>;
51 };
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 6e70eea0cd2f..2e9d56719e99 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -18,6 +18,11 @@
18#include <linux/mv643xx_i2c.h> 18#include <linux/mv643xx_i2c.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/of.h>
22#include <linux/of_irq.h>
23#include <linux/of_i2c.h>
24#include <linux/clk.h>
25#include <linux/err.h>
21 26
22/* Register defines */ 27/* Register defines */
23#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 28#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00
@@ -98,6 +103,9 @@ struct mv64xxx_i2c_data {
98 int rc; 103 int rc;
99 u32 freq_m; 104 u32 freq_m;
100 u32 freq_n; 105 u32 freq_n;
106#if defined(CONFIG_HAVE_CLK)
107 struct clk *clk;
108#endif
101 wait_queue_head_t waitq; 109 wait_queue_head_t waitq;
102 spinlock_t lock; 110 spinlock_t lock;
103 struct i2c_msg *msg; 111 struct i2c_msg *msg;
@@ -521,6 +529,82 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
521 drv_data->reg_base_p = 0; 529 drv_data->reg_base_p = 0;
522} 530}
523 531
532#ifdef CONFIG_OF
533static int __devinit
534mv64xxx_calc_freq(const int tclk, const int n, const int m)
535{
536 return tclk / (10 * (m + 1) * (2 << n));
537}
538
539static bool __devinit
540mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
541 u32 *best_m)
542{
543 int freq, delta, best_delta = INT_MAX;
544 int m, n;
545
546 for (n = 0; n <= 7; n++)
547 for (m = 0; m <= 15; m++) {
548 freq = mv64xxx_calc_freq(tclk, n, m);
549 delta = req_freq - freq;
550 if (delta >= 0 && delta < best_delta) {
551 *best_m = m;
552 *best_n = n;
553 best_delta = delta;
554 }
555 if (best_delta == 0)
556 return true;
557 }
558 if (best_delta == INT_MAX)
559 return false;
560 return true;
561}
562
563static int __devinit
564mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
565 struct device_node *np)
566{
567 u32 bus_freq, tclk;
568 int rc = 0;
569
570 /* CLK is mandatory when using DT to describe the i2c bus. We
571 * need to know tclk in order to calculate bus clock
572 * factors.
573 */
574#if !defined(CONFIG_HAVE_CLK)
575 /* Have OF but no CLK */
576 return -ENODEV;
577#else
578 if (IS_ERR(drv_data->clk)) {
579 rc = -ENODEV;
580 goto out;
581 }
582 tclk = clk_get_rate(drv_data->clk);
583 of_property_read_u32(np, "clock-frequency", &bus_freq);
584 if (!mv64xxx_find_baud_factors(bus_freq, tclk,
585 &drv_data->freq_n, &drv_data->freq_m)) {
586 rc = -EINVAL;
587 goto out;
588 }
589 drv_data->irq = irq_of_parse_and_map(np, 0);
590
591 /* Its not yet defined how timeouts will be specified in device tree.
592 * So hard code the value to 1 second.
593 */
594 drv_data->adapter.timeout = HZ;
595out:
596 return rc;
597#endif
598}
599#else /* CONFIG_OF */
600static int __devinit
601mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
602 struct device_node *np)
603{
604 return -ENODEV;
605}
606#endif /* CONFIG_OF */
607
524static int __devinit 608static int __devinit
525mv64xxx_i2c_probe(struct platform_device *pd) 609mv64xxx_i2c_probe(struct platform_device *pd)
526{ 610{
@@ -528,7 +612,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
528 struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; 612 struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data;
529 int rc; 613 int rc;
530 614
531 if (!pdata) 615 if ((!pdata && !pd->dev.of_node))
532 return -ENODEV; 616 return -ENODEV;
533 617
534 drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); 618 drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
@@ -546,19 +630,35 @@ mv64xxx_i2c_probe(struct platform_device *pd)
546 init_waitqueue_head(&drv_data->waitq); 630 init_waitqueue_head(&drv_data->waitq);
547 spin_lock_init(&drv_data->lock); 631 spin_lock_init(&drv_data->lock);
548 632
549 drv_data->freq_m = pdata->freq_m; 633#if defined(CONFIG_HAVE_CLK)
550 drv_data->freq_n = pdata->freq_n; 634 /* Not all platforms have a clk */
551 drv_data->irq = platform_get_irq(pd, 0); 635 drv_data->clk = clk_get(&pd->dev, NULL);
636 if (!IS_ERR(drv_data->clk)) {
637 clk_prepare(drv_data->clk);
638 clk_enable(drv_data->clk);
639 }
640#endif
641 if (pdata) {
642 drv_data->freq_m = pdata->freq_m;
643 drv_data->freq_n = pdata->freq_n;
644 drv_data->irq = platform_get_irq(pd, 0);
645 drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
646 } else if (pd->dev.of_node) {
647 rc = mv64xxx_of_config(drv_data, pd->dev.of_node);
648 if (rc)
649 goto exit_unmap_regs;
650 }
552 if (drv_data->irq < 0) { 651 if (drv_data->irq < 0) {
553 rc = -ENXIO; 652 rc = -ENXIO;
554 goto exit_unmap_regs; 653 goto exit_unmap_regs;
555 } 654 }
655
556 drv_data->adapter.dev.parent = &pd->dev; 656 drv_data->adapter.dev.parent = &pd->dev;
557 drv_data->adapter.algo = &mv64xxx_i2c_algo; 657 drv_data->adapter.algo = &mv64xxx_i2c_algo;
558 drv_data->adapter.owner = THIS_MODULE; 658 drv_data->adapter.owner = THIS_MODULE;
559 drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; 659 drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
560 drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
561 drv_data->adapter.nr = pd->id; 660 drv_data->adapter.nr = pd->id;
661 drv_data->adapter.dev.of_node = pd->dev.of_node;
562 platform_set_drvdata(pd, drv_data); 662 platform_set_drvdata(pd, drv_data);
563 i2c_set_adapdata(&drv_data->adapter, drv_data); 663 i2c_set_adapdata(&drv_data->adapter, drv_data);
564 664
@@ -577,11 +677,20 @@ mv64xxx_i2c_probe(struct platform_device *pd)
577 goto exit_free_irq; 677 goto exit_free_irq;
578 } 678 }
579 679
680 of_i2c_register_devices(&drv_data->adapter);
681
580 return 0; 682 return 0;
581 683
582 exit_free_irq: 684 exit_free_irq:
583 free_irq(drv_data->irq, drv_data); 685 free_irq(drv_data->irq, drv_data);
584 exit_unmap_regs: 686 exit_unmap_regs:
687#if defined(CONFIG_HAVE_CLK)
688 /* Not all platforms have a clk */
689 if (!IS_ERR(drv_data->clk)) {
690 clk_disable(drv_data->clk);
691 clk_unprepare(drv_data->clk);
692 }
693#endif
585 mv64xxx_i2c_unmap_regs(drv_data); 694 mv64xxx_i2c_unmap_regs(drv_data);
586 exit_kfree: 695 exit_kfree:
587 kfree(drv_data); 696 kfree(drv_data);
@@ -597,17 +706,31 @@ mv64xxx_i2c_remove(struct platform_device *dev)
597 rc = i2c_del_adapter(&drv_data->adapter); 706 rc = i2c_del_adapter(&drv_data->adapter);
598 free_irq(drv_data->irq, drv_data); 707 free_irq(drv_data->irq, drv_data);
599 mv64xxx_i2c_unmap_regs(drv_data); 708 mv64xxx_i2c_unmap_regs(drv_data);
709#if defined(CONFIG_HAVE_CLK)
710 /* Not all platforms have a clk */
711 if (!IS_ERR(drv_data->clk)) {
712 clk_disable(drv_data->clk);
713 clk_unprepare(drv_data->clk);
714 }
715#endif
600 kfree(drv_data); 716 kfree(drv_data);
601 717
602 return rc; 718 return rc;
603} 719}
604 720
721static const struct of_device_id mv64xxx_i2c_of_match_table[] __devinitdata = {
722 { .compatible = "marvell,mv64xxx-i2c", },
723 {}
724};
725MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
726
605static struct platform_driver mv64xxx_i2c_driver = { 727static struct platform_driver mv64xxx_i2c_driver = {
606 .probe = mv64xxx_i2c_probe, 728 .probe = mv64xxx_i2c_probe,
607 .remove = __devexit_p(mv64xxx_i2c_remove), 729 .remove = __devexit_p(mv64xxx_i2c_remove),
608 .driver = { 730 .driver = {
609 .owner = THIS_MODULE, 731 .owner = THIS_MODULE,
610 .name = MV64XXX_I2C_CTLR_NAME, 732 .name = MV64XXX_I2C_CTLR_NAME,
733 .of_match_table = of_match_ptr(mv64xxx_i2c_of_match_table),
611 }, 734 },
612}; 735};
613 736