diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-tegra.c')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 87d0371cebb7..efba1ebe16ba 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c | |||
@@ -380,34 +380,33 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) | |||
380 | { | 380 | { |
381 | int ret; | 381 | int ret; |
382 | if (!i2c_dev->hw->has_single_clk_source) { | 382 | if (!i2c_dev->hw->has_single_clk_source) { |
383 | ret = clk_prepare_enable(i2c_dev->fast_clk); | 383 | ret = clk_enable(i2c_dev->fast_clk); |
384 | if (ret < 0) { | 384 | if (ret < 0) { |
385 | dev_err(i2c_dev->dev, | 385 | dev_err(i2c_dev->dev, |
386 | "Enabling fast clk failed, err %d\n", ret); | 386 | "Enabling fast clk failed, err %d\n", ret); |
387 | return ret; | 387 | return ret; |
388 | } | 388 | } |
389 | } | 389 | } |
390 | ret = clk_prepare_enable(i2c_dev->div_clk); | 390 | ret = clk_enable(i2c_dev->div_clk); |
391 | if (ret < 0) { | 391 | if (ret < 0) { |
392 | dev_err(i2c_dev->dev, | 392 | dev_err(i2c_dev->dev, |
393 | "Enabling div clk failed, err %d\n", ret); | 393 | "Enabling div clk failed, err %d\n", ret); |
394 | clk_disable_unprepare(i2c_dev->fast_clk); | 394 | clk_disable(i2c_dev->fast_clk); |
395 | } | 395 | } |
396 | return ret; | 396 | return ret; |
397 | } | 397 | } |
398 | 398 | ||
399 | static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) | 399 | static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) |
400 | { | 400 | { |
401 | clk_disable_unprepare(i2c_dev->div_clk); | 401 | clk_disable(i2c_dev->div_clk); |
402 | if (!i2c_dev->hw->has_single_clk_source) | 402 | if (!i2c_dev->hw->has_single_clk_source) |
403 | clk_disable_unprepare(i2c_dev->fast_clk); | 403 | clk_disable(i2c_dev->fast_clk); |
404 | } | 404 | } |
405 | 405 | ||
406 | static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) | 406 | static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) |
407 | { | 407 | { |
408 | u32 val; | 408 | u32 val; |
409 | int err = 0; | 409 | int err = 0; |
410 | int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE; | ||
411 | u32 clk_divisor; | 410 | u32 clk_divisor; |
412 | 411 | ||
413 | err = tegra_i2c_clock_enable(i2c_dev); | 412 | err = tegra_i2c_clock_enable(i2c_dev); |
@@ -428,9 +427,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) | |||
428 | i2c_writel(i2c_dev, val, I2C_CNFG); | 427 | i2c_writel(i2c_dev, val, I2C_CNFG); |
429 | i2c_writel(i2c_dev, 0, I2C_INT_MASK); | 428 | i2c_writel(i2c_dev, 0, I2C_INT_MASK); |
430 | 429 | ||
431 | clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1); | ||
432 | clk_set_rate(i2c_dev->div_clk, i2c_dev->bus_clk_rate * clk_multiplier); | ||
433 | |||
434 | /* Make sure clock divisor programmed correctly */ | 430 | /* Make sure clock divisor programmed correctly */ |
435 | clk_divisor = i2c_dev->hw->clk_divisor_hs_mode; | 431 | clk_divisor = i2c_dev->hw->clk_divisor_hs_mode; |
436 | clk_divisor |= i2c_dev->hw->clk_divisor_std_fast_mode << | 432 | clk_divisor |= i2c_dev->hw->clk_divisor_std_fast_mode << |
@@ -712,6 +708,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) | |||
712 | void __iomem *base; | 708 | void __iomem *base; |
713 | int irq; | 709 | int irq; |
714 | int ret = 0; | 710 | int ret = 0; |
711 | int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE; | ||
715 | 712 | ||
716 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 713 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
717 | base = devm_ioremap_resource(&pdev->dev, res); | 714 | base = devm_ioremap_resource(&pdev->dev, res); |
@@ -777,17 +774,39 @@ static int tegra_i2c_probe(struct platform_device *pdev) | |||
777 | 774 | ||
778 | platform_set_drvdata(pdev, i2c_dev); | 775 | platform_set_drvdata(pdev, i2c_dev); |
779 | 776 | ||
777 | if (!i2c_dev->hw->has_single_clk_source) { | ||
778 | ret = clk_prepare(i2c_dev->fast_clk); | ||
779 | if (ret < 0) { | ||
780 | dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret); | ||
781 | return ret; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1); | ||
786 | ret = clk_set_rate(i2c_dev->div_clk, | ||
787 | i2c_dev->bus_clk_rate * clk_multiplier); | ||
788 | if (ret) { | ||
789 | dev_err(i2c_dev->dev, "Clock rate change failed %d\n", ret); | ||
790 | goto unprepare_fast_clk; | ||
791 | } | ||
792 | |||
793 | ret = clk_prepare(i2c_dev->div_clk); | ||
794 | if (ret < 0) { | ||
795 | dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret); | ||
796 | goto unprepare_fast_clk; | ||
797 | } | ||
798 | |||
780 | ret = tegra_i2c_init(i2c_dev); | 799 | ret = tegra_i2c_init(i2c_dev); |
781 | if (ret) { | 800 | if (ret) { |
782 | dev_err(&pdev->dev, "Failed to initialize i2c controller"); | 801 | dev_err(&pdev->dev, "Failed to initialize i2c controller"); |
783 | return ret; | 802 | goto unprepare_div_clk; |
784 | } | 803 | } |
785 | 804 | ||
786 | ret = devm_request_irq(&pdev->dev, i2c_dev->irq, | 805 | ret = devm_request_irq(&pdev->dev, i2c_dev->irq, |
787 | tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); | 806 | tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); |
788 | if (ret) { | 807 | if (ret) { |
789 | dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); | 808 | dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); |
790 | return ret; | 809 | goto unprepare_div_clk; |
791 | } | 810 | } |
792 | 811 | ||
793 | i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); | 812 | i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); |
@@ -803,16 +822,30 @@ static int tegra_i2c_probe(struct platform_device *pdev) | |||
803 | ret = i2c_add_numbered_adapter(&i2c_dev->adapter); | 822 | ret = i2c_add_numbered_adapter(&i2c_dev->adapter); |
804 | if (ret) { | 823 | if (ret) { |
805 | dev_err(&pdev->dev, "Failed to add I2C adapter\n"); | 824 | dev_err(&pdev->dev, "Failed to add I2C adapter\n"); |
806 | return ret; | 825 | goto unprepare_div_clk; |
807 | } | 826 | } |
808 | 827 | ||
809 | return 0; | 828 | return 0; |
829 | |||
830 | unprepare_div_clk: | ||
831 | clk_unprepare(i2c_dev->div_clk); | ||
832 | |||
833 | unprepare_fast_clk: | ||
834 | if (!i2c_dev->hw->has_single_clk_source) | ||
835 | clk_unprepare(i2c_dev->fast_clk); | ||
836 | |||
837 | return ret; | ||
810 | } | 838 | } |
811 | 839 | ||
812 | static int tegra_i2c_remove(struct platform_device *pdev) | 840 | static int tegra_i2c_remove(struct platform_device *pdev) |
813 | { | 841 | { |
814 | struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | 842 | struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); |
815 | i2c_del_adapter(&i2c_dev->adapter); | 843 | i2c_del_adapter(&i2c_dev->adapter); |
844 | |||
845 | clk_unprepare(i2c_dev->div_clk); | ||
846 | if (!i2c_dev->hw->has_single_clk_source) | ||
847 | clk_unprepare(i2c_dev->fast_clk); | ||
848 | |||
816 | return 0; | 849 | return 0; |
817 | } | 850 | } |
818 | 851 | ||