diff options
author | Chaithrika U S <chaithrika@ti.com> | 2010-01-06 04:25:00 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-08-05 12:38:32 -0400 |
commit | 82c0de11b734c5acec13c0f6007466da81cd16d9 (patch) | |
tree | c3e5c2a27ce5c67956040066ba0dbff7dca94e73 /drivers/i2c | |
parent | 68f15de976f8f90d3bc0d10160aa20b0528760d4 (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')
-rw-r--r-- | drivers/i2c/busses/i2c-davinci.c | 63 |
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 | ||
537 | static 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 | |||
554 | static 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 | |||
562 | static 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 | ||
568 | static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) | ||
569 | { | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) | ||
574 | { | ||
575 | } | ||
576 | #endif | ||
577 | |||
526 | static struct i2c_algorithm i2c_davinci_algo = { | 578 | static 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); |