aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2012-10-29 06:25:29 -0400
committerStephen Warren <swarren@nvidia.com>2012-11-05 13:36:22 -0500
commitd534b5d4a530d2d1597c3ffb9e896a3499da6172 (patch)
tree0aea20ae49923d70ad7322fb5f5534386027e7c0 /arch/arm/mach-tegra
parent25804d8123e9c1657694844b10fcd7834493e41a (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.c4
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks.c106
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks.h1
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks_data.c46
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 */
795static 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
804static 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
816static 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
826static 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
844static 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
868static 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
891struct 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 */
795static int tegra30_blink_clk_is_enabled(struct clk_hw *hw) 901static 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;
34extern struct clk_ops tegra30_super_ops; 34extern struct clk_ops tegra30_super_ops;
35extern struct clk_ops tegra30_blink_clk_ops; 35extern struct clk_ops tegra30_blink_clk_ops;
36extern struct clk_ops tegra30_twd_ops; 36extern struct clk_ops tegra30_twd_ops;
37extern struct clk_ops tegra30_bus_ops;
37extern struct clk_ops tegra30_periph_clk_ops; 38extern struct clk_ops tegra30_periph_clk_ops;
38extern struct clk_ops tegra30_dsib_clk_ops; 39extern struct clk_ops tegra30_dsib_clk_ops;
39extern struct clk_ops tegra_nand_clk_ops; 40extern 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
714static const char *tegra_hclk_parent_names[] = {
715 "tegra_sclk",
716};
717
718static struct clk *tegra_hclk_parents[] = {
719 &tegra_clk_sclk,
720};
721
722static struct clk tegra_hclk;
723static 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};
733DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names,
734 tegra_hclk_parents, &tegra_clk_sclk);
735
736static const char *tegra_pclk_parent_names[] = {
737 "tegra_hclk",
738};
739
740static struct clk *tegra_pclk_parents[] = {
741 &tegra_hclk,
742};
743
744static struct clk tegra_pclk;
745static 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};
755DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names,
756 tegra_pclk_parents, &tegra_hclk);
757
714static const char *mux_blink[] = { 758static 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};