diff options
author | Joseph Lo <josephl@nvidia.com> | 2012-10-29 06:25:29 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2012-11-05 13:36:22 -0500 |
commit | d534b5d4a530d2d1597c3ffb9e896a3499da6172 (patch) | |
tree | 0aea20ae49923d70ad7322fb5f5534386027e7c0 /arch/arm/mach-tegra | |
parent | 25804d8123e9c1657694844b10fcd7834493e41a (diff) |
ARM: tegra30: clocks: add AHB and APB clocks
Adding the AHB and APB bus clock for Tegra30.
Signed-off-by: Joseph Lo <josephl@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/common.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra30_clocks.c | 106 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra30_clocks.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra30_clocks_data.c | 46 |
4 files changed, 157 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index f688daa74978..3f55a3615413 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c | |||
@@ -104,6 +104,10 @@ static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = { | |||
104 | { "clk_m", NULL, 0, true }, | 104 | { "clk_m", NULL, 0, true }, |
105 | { "pll_p", "clk_m", 408000000, true }, | 105 | { "pll_p", "clk_m", 408000000, true }, |
106 | { "pll_p_out1", "pll_p", 9600000, true }, | 106 | { "pll_p_out1", "pll_p", 9600000, true }, |
107 | { "pll_p_out4", "pll_p", 102000000, true }, | ||
108 | { "sclk", "pll_p_out4", 102000000, true }, | ||
109 | { "hclk", "sclk", 102000000, true }, | ||
110 | { "pclk", "hclk", 51000000, true }, | ||
107 | { NULL, NULL, 0, 0}, | 111 | { NULL, NULL, 0, 0}, |
108 | }; | 112 | }; |
109 | #endif | 113 | #endif |
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c index 000239d68393..f5b453f4bf4d 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ b/arch/arm/mach-tegra/tegra30_clocks.c | |||
@@ -791,6 +791,112 @@ struct clk_ops tegra30_twd_ops = { | |||
791 | .recalc_rate = tegra30_twd_clk_recalc_rate, | 791 | .recalc_rate = tegra30_twd_clk_recalc_rate, |
792 | }; | 792 | }; |
793 | 793 | ||
794 | /* bus clock functions */ | ||
795 | static int tegra30_bus_clk_is_enabled(struct clk_hw *hw) | ||
796 | { | ||
797 | struct clk_tegra *c = to_clk_tegra(hw); | ||
798 | u32 val = clk_readl(c->reg); | ||
799 | |||
800 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; | ||
801 | return c->state; | ||
802 | } | ||
803 | |||
804 | static int tegra30_bus_clk_enable(struct clk_hw *hw) | ||
805 | { | ||
806 | struct clk_tegra *c = to_clk_tegra(hw); | ||
807 | u32 val; | ||
808 | |||
809 | val = clk_readl(c->reg); | ||
810 | val &= ~(BUS_CLK_DISABLE << c->reg_shift); | ||
811 | clk_writel(val, c->reg); | ||
812 | |||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static void tegra30_bus_clk_disable(struct clk_hw *hw) | ||
817 | { | ||
818 | struct clk_tegra *c = to_clk_tegra(hw); | ||
819 | u32 val; | ||
820 | |||
821 | val = clk_readl(c->reg); | ||
822 | val |= BUS_CLK_DISABLE << c->reg_shift; | ||
823 | clk_writel(val, c->reg); | ||
824 | } | ||
825 | |||
826 | static unsigned long tegra30_bus_clk_recalc_rate(struct clk_hw *hw, | ||
827 | unsigned long prate) | ||
828 | { | ||
829 | struct clk_tegra *c = to_clk_tegra(hw); | ||
830 | u32 val = clk_readl(c->reg); | ||
831 | u64 rate = prate; | ||
832 | |||
833 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; | ||
834 | c->mul = 1; | ||
835 | |||
836 | if (c->mul != 0 && c->div != 0) { | ||
837 | rate *= c->mul; | ||
838 | rate += c->div - 1; /* round up */ | ||
839 | do_div(rate, c->div); | ||
840 | } | ||
841 | return rate; | ||
842 | } | ||
843 | |||
844 | static int tegra30_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
845 | unsigned long parent_rate) | ||
846 | { | ||
847 | struct clk_tegra *c = to_clk_tegra(hw); | ||
848 | int ret = -EINVAL; | ||
849 | u32 val; | ||
850 | int i; | ||
851 | |||
852 | val = clk_readl(c->reg); | ||
853 | for (i = 1; i <= 4; i++) { | ||
854 | if (rate == parent_rate / i) { | ||
855 | val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); | ||
856 | val |= (i - 1) << c->reg_shift; | ||
857 | clk_writel(val, c->reg); | ||
858 | c->div = i; | ||
859 | c->mul = 1; | ||
860 | ret = 0; | ||
861 | break; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | static long tegra30_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
869 | unsigned long *prate) | ||
870 | { | ||
871 | unsigned long parent_rate = *prate; | ||
872 | s64 divider; | ||
873 | |||
874 | if (rate >= parent_rate) | ||
875 | return parent_rate; | ||
876 | |||
877 | divider = parent_rate; | ||
878 | divider += rate - 1; | ||
879 | do_div(divider, rate); | ||
880 | |||
881 | if (divider < 0) | ||
882 | return divider; | ||
883 | |||
884 | if (divider > 4) | ||
885 | divider = 4; | ||
886 | do_div(parent_rate, divider); | ||
887 | |||
888 | return parent_rate; | ||
889 | } | ||
890 | |||
891 | struct clk_ops tegra30_bus_ops = { | ||
892 | .is_enabled = tegra30_bus_clk_is_enabled, | ||
893 | .enable = tegra30_bus_clk_enable, | ||
894 | .disable = tegra30_bus_clk_disable, | ||
895 | .set_rate = tegra30_bus_clk_set_rate, | ||
896 | .round_rate = tegra30_bus_clk_round_rate, | ||
897 | .recalc_rate = tegra30_bus_clk_recalc_rate, | ||
898 | }; | ||
899 | |||
794 | /* Blink output functions */ | 900 | /* Blink output functions */ |
795 | static int tegra30_blink_clk_is_enabled(struct clk_hw *hw) | 901 | static int tegra30_blink_clk_is_enabled(struct clk_hw *hw) |
796 | { | 902 | { |
diff --git a/arch/arm/mach-tegra/tegra30_clocks.h b/arch/arm/mach-tegra/tegra30_clocks.h index f2f88fef6b8b..7a34adb2f72d 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.h +++ b/arch/arm/mach-tegra/tegra30_clocks.h | |||
@@ -34,6 +34,7 @@ extern struct clk_ops tegra_clk_out_ops; | |||
34 | extern struct clk_ops tegra30_super_ops; | 34 | extern struct clk_ops tegra30_super_ops; |
35 | extern struct clk_ops tegra30_blink_clk_ops; | 35 | extern struct clk_ops tegra30_blink_clk_ops; |
36 | extern struct clk_ops tegra30_twd_ops; | 36 | extern struct clk_ops tegra30_twd_ops; |
37 | extern struct clk_ops tegra30_bus_ops; | ||
37 | extern struct clk_ops tegra30_periph_clk_ops; | 38 | extern struct clk_ops tegra30_periph_clk_ops; |
38 | extern struct clk_ops tegra30_dsib_clk_ops; | 39 | extern struct clk_ops tegra30_dsib_clk_ops; |
39 | extern struct clk_ops tegra_nand_clk_ops; | 40 | extern struct clk_ops tegra_nand_clk_ops; |
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c index 3d2e5532a9ea..7bc8b1ddbe55 100644 --- a/arch/arm/mach-tegra/tegra30_clocks_data.c +++ b/arch/arm/mach-tegra/tegra30_clocks_data.c | |||
@@ -711,6 +711,50 @@ static struct clk tegra_clk_sclk = { | |||
711 | .num_parents = ARRAY_SIZE(mux_sclk), | 711 | .num_parents = ARRAY_SIZE(mux_sclk), |
712 | }; | 712 | }; |
713 | 713 | ||
714 | static const char *tegra_hclk_parent_names[] = { | ||
715 | "tegra_sclk", | ||
716 | }; | ||
717 | |||
718 | static struct clk *tegra_hclk_parents[] = { | ||
719 | &tegra_clk_sclk, | ||
720 | }; | ||
721 | |||
722 | static struct clk tegra_hclk; | ||
723 | static struct clk_tegra tegra_hclk_hw = { | ||
724 | .hw = { | ||
725 | .clk = &tegra_hclk, | ||
726 | }, | ||
727 | .flags = DIV_BUS, | ||
728 | .reg = 0x30, | ||
729 | .reg_shift = 4, | ||
730 | .max_rate = 378000000, | ||
731 | .min_rate = 12000000, | ||
732 | }; | ||
733 | DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names, | ||
734 | tegra_hclk_parents, &tegra_clk_sclk); | ||
735 | |||
736 | static const char *tegra_pclk_parent_names[] = { | ||
737 | "tegra_hclk", | ||
738 | }; | ||
739 | |||
740 | static struct clk *tegra_pclk_parents[] = { | ||
741 | &tegra_hclk, | ||
742 | }; | ||
743 | |||
744 | static struct clk tegra_pclk; | ||
745 | static struct clk_tegra tegra_pclk_hw = { | ||
746 | .hw = { | ||
747 | .clk = &tegra_pclk, | ||
748 | }, | ||
749 | .flags = DIV_BUS, | ||
750 | .reg = 0x30, | ||
751 | .reg_shift = 0, | ||
752 | .max_rate = 167000000, | ||
753 | .min_rate = 12000000, | ||
754 | }; | ||
755 | DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names, | ||
756 | tegra_pclk_parents, &tegra_hclk); | ||
757 | |||
714 | static const char *mux_blink[] = { | 758 | static const char *mux_blink[] = { |
715 | "clk_32k", | 759 | "clk_32k", |
716 | }; | 760 | }; |
@@ -1325,6 +1369,8 @@ struct clk *tegra_ptr_clks[] = { | |||
1325 | &tegra_cml1, | 1369 | &tegra_cml1, |
1326 | &tegra_pciex, | 1370 | &tegra_pciex, |
1327 | &tegra_clk_sclk, | 1371 | &tegra_clk_sclk, |
1372 | &tegra_hclk, | ||
1373 | &tegra_pclk, | ||
1328 | &tegra_clk_blink, | 1374 | &tegra_clk_blink, |
1329 | &tegra30_clk_twd, | 1375 | &tegra30_clk_twd, |
1330 | }; | 1376 | }; |