aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-davinci.c
diff options
context:
space:
mode:
authorChaithrika U S <chaithrika@ti.com>2010-01-06 04:25:00 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2010-08-05 12:38:32 -0400
commit82c0de11b734c5acec13c0f6007466da81cd16d9 (patch)
treec3e5c2a27ce5c67956040066ba0dbff7dca94e73 /drivers/i2c/busses/i2c-davinci.c
parent68f15de976f8f90d3bc0d10160aa20b0528760d4 (diff)
i2c: davinci: Add cpufreq support
Add cpufreq support for DaVinci I2C driver. Tested on DA850/OMAP-L138 EVM. Signed-off-by: Chaithrika U S <chaithrika@ti.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'drivers/i2c/busses/i2c-davinci.c')
-rw-r--r--drivers/i2c/busses/i2c-davinci.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 7afeb28d6d76..352b4e7bdd9e 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -36,6 +36,7 @@
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/io.h> 37#include <linux/io.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/cpufreq.h>
39 40
40#include <mach/hardware.h> 41#include <mach/hardware.h>
41#include <mach/i2c.h> 42#include <mach/i2c.h>
@@ -107,6 +108,10 @@ struct davinci_i2c_dev {
107 int stop; 108 int stop;
108 u8 terminate; 109 u8 terminate;
109 struct i2c_adapter adapter; 110 struct i2c_adapter adapter;
111#ifdef CONFIG_CPU_FREQ
112 struct completion xfr_complete;
113 struct notifier_block freq_transition;
114#endif
110}; 115};
111 116
112/* default platform data to use if not supplied in the platform_device */ 117/* default platform data to use if not supplied in the platform_device */
@@ -391,6 +396,11 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
391 if (ret < 0) 396 if (ret < 0)
392 return ret; 397 return ret;
393 } 398 }
399
400#ifdef CONFIG_CPU_FREQ
401 complete(&dev->xfr_complete);
402#endif
403
394 return num; 404 return num;
395} 405}
396 406
@@ -523,6 +533,48 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
523 return count ? IRQ_HANDLED : IRQ_NONE; 533 return count ? IRQ_HANDLED : IRQ_NONE;
524} 534}
525 535
536#ifdef CONFIG_CPU_FREQ
537static int i2c_davinci_cpufreq_transition(struct notifier_block *nb,
538 unsigned long val, void *data)
539{
540 struct davinci_i2c_dev *dev;
541
542 dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
543 if (val == CPUFREQ_PRECHANGE) {
544 wait_for_completion(&dev->xfr_complete);
545 davinci_i2c_reset_ctrl(dev, 0);
546 } else if (val == CPUFREQ_POSTCHANGE) {
547 i2c_davinci_calc_clk_dividers(dev);
548 davinci_i2c_reset_ctrl(dev, 1);
549 }
550
551 return 0;
552}
553
554static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev)
555{
556 dev->freq_transition.notifier_call = i2c_davinci_cpufreq_transition;
557
558 return cpufreq_register_notifier(&dev->freq_transition,
559 CPUFREQ_TRANSITION_NOTIFIER);
560}
561
562static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev)
563{
564 cpufreq_unregister_notifier(&dev->freq_transition,
565 CPUFREQ_TRANSITION_NOTIFIER);
566}
567#else
568static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev)
569{
570 return 0;
571}
572
573static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev)
574{
575}
576#endif
577
526static struct i2c_algorithm i2c_davinci_algo = { 578static struct i2c_algorithm i2c_davinci_algo = {
527 .master_xfer = i2c_davinci_xfer, 579 .master_xfer = i2c_davinci_xfer,
528 .functionality = i2c_davinci_func, 580 .functionality = i2c_davinci_func,
@@ -562,6 +614,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)
562 } 614 }
563 615
564 init_completion(&dev->cmd_complete); 616 init_completion(&dev->cmd_complete);
617#ifdef CONFIG_CPU_FREQ
618 init_completion(&dev->xfr_complete);
619#endif
565 dev->dev = get_device(&pdev->dev); 620 dev->dev = get_device(&pdev->dev);
566 dev->irq = irq->start; 621 dev->irq = irq->start;
567 platform_set_drvdata(pdev, dev); 622 platform_set_drvdata(pdev, dev);
@@ -587,6 +642,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)
587 goto err_unuse_clocks; 642 goto err_unuse_clocks;
588 } 643 }
589 644
645 r = i2c_davinci_cpufreq_register(dev);
646 if (r) {
647 dev_err(&pdev->dev, "failed to register cpufreq\n");
648 goto err_free_irq;
649 }
650
590 adap = &dev->adapter; 651 adap = &dev->adapter;
591 i2c_set_adapdata(adap, dev); 652 i2c_set_adapdata(adap, dev);
592 adap->owner = THIS_MODULE; 653 adap->owner = THIS_MODULE;
@@ -628,6 +689,8 @@ static int davinci_i2c_remove(struct platform_device *pdev)
628 struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); 689 struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
629 struct resource *mem; 690 struct resource *mem;
630 691
692 i2c_davinci_cpufreq_deregister(dev);
693
631 platform_set_drvdata(pdev, NULL); 694 platform_set_drvdata(pdev, NULL);
632 i2c_del_adapter(&dev->adapter); 695 i2c_del_adapter(&dev->adapter);
633 put_device(&pdev->dev); 696 put_device(&pdev->dev);