diff options
Diffstat (limited to 'arch/arm/mach-mx5/clock-mx51.c')
-rw-r--r-- | arch/arm/mach-mx5/clock-mx51.c | 244 |
1 files changed, 151 insertions, 93 deletions
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index 21cecc040172..f2aae92cf0e2 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c | |||
@@ -41,6 +41,36 @@ static struct clk usboh3_clk; | |||
41 | 41 | ||
42 | #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ | 42 | #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ |
43 | 43 | ||
44 | /* calculate best pre and post dividers to get the required divider */ | ||
45 | static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post, | ||
46 | u32 max_pre, u32 max_post) | ||
47 | { | ||
48 | if (div >= max_pre * max_post) { | ||
49 | *pre = max_pre; | ||
50 | *post = max_post; | ||
51 | } else if (div >= max_pre) { | ||
52 | u32 min_pre, temp_pre, old_err, err; | ||
53 | min_pre = DIV_ROUND_UP(div, max_post); | ||
54 | old_err = max_pre; | ||
55 | for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) { | ||
56 | err = div % temp_pre; | ||
57 | if (err == 0) { | ||
58 | *pre = temp_pre; | ||
59 | break; | ||
60 | } | ||
61 | err = temp_pre - err; | ||
62 | if (err < old_err) { | ||
63 | old_err = err; | ||
64 | *pre = temp_pre; | ||
65 | } | ||
66 | } | ||
67 | *post = DIV_ROUND_UP(div, *pre); | ||
68 | } else { | ||
69 | *pre = div; | ||
70 | *post = 1; | ||
71 | } | ||
72 | } | ||
73 | |||
44 | static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) | 74 | static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) |
45 | { | 75 | { |
46 | u32 reg = __raw_readl(clk->enable_reg); | 76 | u32 reg = __raw_readl(clk->enable_reg); |
@@ -544,35 +574,6 @@ static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent) | |||
544 | return 0; | 574 | return 0; |
545 | } | 575 | } |
546 | 576 | ||
547 | static unsigned long clk_uart_get_rate(struct clk *clk) | ||
548 | { | ||
549 | u32 reg, prediv, podf; | ||
550 | unsigned long parent_rate; | ||
551 | |||
552 | parent_rate = clk_get_rate(clk->parent); | ||
553 | |||
554 | reg = __raw_readl(MXC_CCM_CSCDR1); | ||
555 | prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >> | ||
556 | MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1; | ||
557 | podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> | ||
558 | MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1; | ||
559 | |||
560 | return parent_rate / (prediv * podf); | ||
561 | } | ||
562 | |||
563 | static int _clk_uart_set_parent(struct clk *clk, struct clk *parent) | ||
564 | { | ||
565 | u32 reg, mux; | ||
566 | |||
567 | mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, | ||
568 | &lp_apm_clk); | ||
569 | reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK; | ||
570 | reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET; | ||
571 | __raw_writel(reg, MXC_CCM_CSCMR1); | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | #define clk_nfc_set_parent NULL | 577 | #define clk_nfc_set_parent NULL |
577 | 578 | ||
578 | static unsigned long clk_nfc_get_rate(struct clk *clk) | 579 | static unsigned long clk_nfc_get_rate(struct clk *clk) |
@@ -631,35 +632,6 @@ static int clk_nfc_set_rate(struct clk *clk, unsigned long rate) | |||
631 | return 0; | 632 | return 0; |
632 | } | 633 | } |
633 | 634 | ||
634 | static unsigned long clk_usboh3_get_rate(struct clk *clk) | ||
635 | { | ||
636 | u32 reg, prediv, podf; | ||
637 | unsigned long parent_rate; | ||
638 | |||
639 | parent_rate = clk_get_rate(clk->parent); | ||
640 | |||
641 | reg = __raw_readl(MXC_CCM_CSCDR1); | ||
642 | prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >> | ||
643 | MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1; | ||
644 | podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >> | ||
645 | MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1; | ||
646 | |||
647 | return parent_rate / (prediv * podf); | ||
648 | } | ||
649 | |||
650 | static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent) | ||
651 | { | ||
652 | u32 reg, mux; | ||
653 | |||
654 | mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, | ||
655 | &lp_apm_clk); | ||
656 | reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK; | ||
657 | reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET; | ||
658 | __raw_writel(reg, MXC_CCM_CSCMR1); | ||
659 | |||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | static unsigned long get_high_reference_clock_rate(struct clk *clk) | 635 | static unsigned long get_high_reference_clock_rate(struct clk *clk) |
664 | { | 636 | { |
665 | return external_high_reference; | 637 | return external_high_reference; |
@@ -786,18 +758,6 @@ static struct clk ipg_perclk = { | |||
786 | .set_parent = _clk_ipg_per_set_parent, | 758 | .set_parent = _clk_ipg_per_set_parent, |
787 | }; | 759 | }; |
788 | 760 | ||
789 | static struct clk uart_root_clk = { | ||
790 | .parent = &pll2_sw_clk, | ||
791 | .get_rate = clk_uart_get_rate, | ||
792 | .set_parent = _clk_uart_set_parent, | ||
793 | }; | ||
794 | |||
795 | static struct clk usboh3_clk = { | ||
796 | .parent = &pll2_sw_clk, | ||
797 | .get_rate = clk_usboh3_get_rate, | ||
798 | .set_parent = _clk_usboh3_set_parent, | ||
799 | }; | ||
800 | |||
801 | static struct clk ahb_max_clk = { | 761 | static struct clk ahb_max_clk = { |
802 | .parent = &ahb_clk, | 762 | .parent = &ahb_clk, |
803 | .enable_reg = MXC_CCM_CCGR0, | 763 | .enable_reg = MXC_CCM_CCGR0, |
@@ -842,7 +802,7 @@ static struct clk emi_slow_clk = { | |||
842 | .get_rate = clk_emi_slow_get_rate, | 802 | .get_rate = clk_emi_slow_get_rate, |
843 | }; | 803 | }; |
844 | 804 | ||
845 | #define DEFINE_CLOCK1(name, i, er, es, pfx, p, s) \ | 805 | #define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \ |
846 | static struct clk name = { \ | 806 | static struct clk name = { \ |
847 | .id = i, \ | 807 | .id = i, \ |
848 | .enable_reg = er, \ | 808 | .enable_reg = er, \ |
@@ -857,35 +817,104 @@ static struct clk emi_slow_clk = { | |||
857 | .secondary = s, \ | 817 | .secondary = s, \ |
858 | } | 818 | } |
859 | 819 | ||
860 | /* eCSPI */ | 820 | #define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \ |
861 | static unsigned long clk_ecspi_get_rate(struct clk *clk) | 821 | static struct clk name = { \ |
862 | { | 822 | .id = i, \ |
863 | u32 reg, pred, podf; | 823 | .enable_reg = er, \ |
824 | .enable_shift = es, \ | ||
825 | .get_rate = pfx##_get_rate, \ | ||
826 | .set_rate = pfx##_set_rate, \ | ||
827 | .set_parent = pfx##_set_parent, \ | ||
828 | .enable = _clk_max_enable, \ | ||
829 | .disable = _clk_max_disable, \ | ||
830 | .parent = p, \ | ||
831 | .secondary = s, \ | ||
832 | } | ||
864 | 833 | ||
865 | reg = __raw_readl(MXC_CCM_CSCDR2); | 834 | #define CLK_GET_RATE(name, nr, bitsname) \ |
835 | static unsigned long clk_##name##_get_rate(struct clk *clk) \ | ||
836 | { \ | ||
837 | u32 reg, pred, podf; \ | ||
838 | \ | ||
839 | reg = __raw_readl(MXC_CCM_CSCDR##nr); \ | ||
840 | pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \ | ||
841 | >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ | ||
842 | podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \ | ||
843 | >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ | ||
844 | \ | ||
845 | return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \ | ||
846 | (pred + 1) * (podf + 1)); \ | ||
847 | } | ||
866 | 848 | ||
867 | pred = (reg & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) >> | 849 | #define CLK_SET_PARENT(name, nr, bitsname) \ |
868 | MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET; | 850 | static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \ |
869 | podf = (reg & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) >> | 851 | { \ |
870 | MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET; | 852 | u32 reg, mux; \ |
853 | \ | ||
854 | mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \ | ||
855 | &pll3_sw_clk, &lp_apm_clk); \ | ||
856 | reg = __raw_readl(MXC_CCM_CSCMR##nr) & \ | ||
857 | ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \ | ||
858 | reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \ | ||
859 | __raw_writel(reg, MXC_CCM_CSCMR##nr); \ | ||
860 | \ | ||
861 | return 0; \ | ||
862 | } | ||
871 | 863 | ||
872 | return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), | 864 | #define CLK_SET_RATE(name, nr, bitsname) \ |
873 | (pred + 1) * (podf + 1)); | 865 | static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \ |
866 | { \ | ||
867 | u32 reg, div, parent_rate; \ | ||
868 | u32 pre = 0, post = 0; \ | ||
869 | \ | ||
870 | parent_rate = clk_get_rate(clk->parent); \ | ||
871 | div = parent_rate / rate; \ | ||
872 | \ | ||
873 | if ((parent_rate / div) != rate) \ | ||
874 | return -EINVAL; \ | ||
875 | \ | ||
876 | __calc_pre_post_dividers(div, &pre, &post, \ | ||
877 | (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \ | ||
878 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \ | ||
879 | (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \ | ||
880 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\ | ||
881 | \ | ||
882 | /* Set sdhc1 clock divider */ \ | ||
883 | reg = __raw_readl(MXC_CCM_CSCDR##nr) & \ | ||
884 | ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \ | ||
885 | | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \ | ||
886 | reg |= (post - 1) << \ | ||
887 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ | ||
888 | reg |= (pre - 1) << \ | ||
889 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ | ||
890 | __raw_writel(reg, MXC_CCM_CSCDR##nr); \ | ||
891 | \ | ||
892 | return 0; \ | ||
874 | } | 893 | } |
875 | 894 | ||
876 | static int clk_ecspi_set_parent(struct clk *clk, struct clk *parent) | 895 | /* UART */ |
877 | { | 896 | CLK_GET_RATE(uart, 1, UART) |
878 | u32 reg, mux; | 897 | CLK_SET_PARENT(uart, 1, UART) |
879 | 898 | ||
880 | mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, | 899 | static struct clk uart_root_clk = { |
881 | &lp_apm_clk); | 900 | .parent = &pll2_sw_clk, |
901 | .get_rate = clk_uart_get_rate, | ||
902 | .set_parent = clk_uart_set_parent, | ||
903 | }; | ||
882 | 904 | ||
883 | reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK; | 905 | /* USBOH3 */ |
884 | reg |= mux << MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET; | 906 | CLK_GET_RATE(usboh3, 1, USBOH3) |
885 | __raw_writel(reg, MXC_CCM_CSCMR1); | 907 | CLK_SET_PARENT(usboh3, 1, USBOH3) |
886 | 908 | ||
887 | return 0; | 909 | static struct clk usboh3_clk = { |
888 | } | 910 | .parent = &pll2_sw_clk, |
911 | .get_rate = clk_usboh3_get_rate, | ||
912 | .set_parent = clk_usboh3_set_parent, | ||
913 | }; | ||
914 | |||
915 | /* eCSPI */ | ||
916 | CLK_GET_RATE(ecspi, 2, CSPI) | ||
917 | CLK_SET_PARENT(ecspi, 1, CSPI) | ||
889 | 918 | ||
890 | static struct clk ecspi_main_clk = { | 919 | static struct clk ecspi_main_clk = { |
891 | .parent = &pll3_sw_clk, | 920 | .parent = &pll3_sw_clk, |
@@ -893,6 +922,15 @@ static struct clk ecspi_main_clk = { | |||
893 | .set_parent = clk_ecspi_set_parent, | 922 | .set_parent = clk_ecspi_set_parent, |
894 | }; | 923 | }; |
895 | 924 | ||
925 | /* eSDHC */ | ||
926 | CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1) | ||
927 | CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1) | ||
928 | CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1) | ||
929 | |||
930 | CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2) | ||
931 | CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2) | ||
932 | CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2) | ||
933 | |||
896 | #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ | 934 | #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ |
897 | static struct clk name = { \ | 935 | static struct clk name = { \ |
898 | .id = i, \ | 936 | .id = i, \ |
@@ -946,7 +984,7 @@ DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, | |||
946 | NULL, NULL, &ipg_clk, NULL); | 984 | NULL, NULL, &ipg_clk, NULL); |
947 | 985 | ||
948 | /* NFC */ | 986 | /* NFC */ |
949 | DEFINE_CLOCK1(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET, | 987 | DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET, |
950 | clk_nfc, &emi_slow_clk, NULL); | 988 | clk_nfc, &emi_slow_clk, NULL); |
951 | 989 | ||
952 | /* SSI */ | 990 | /* SSI */ |
@@ -981,6 +1019,16 @@ DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET, | |||
981 | DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, | 1019 | DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, |
982 | NULL, NULL, &ahb_clk, NULL); | 1020 | NULL, NULL, &ahb_clk, NULL); |
983 | 1021 | ||
1022 | /* eSDHC */ | ||
1023 | DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET, | ||
1024 | NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); | ||
1025 | DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET, | ||
1026 | clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk); | ||
1027 | DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET, | ||
1028 | NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); | ||
1029 | DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET, | ||
1030 | clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk); | ||
1031 | |||
984 | #define _REGISTER_CLOCK(d, n, c) \ | 1032 | #define _REGISTER_CLOCK(d, n, c) \ |
985 | { \ | 1033 | { \ |
986 | .dev_id = d, \ | 1034 | .dev_id = d, \ |
@@ -1014,6 +1062,8 @@ static struct clk_lookup lookups[] = { | |||
1014 | _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) | 1062 | _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) |
1015 | _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) | 1063 | _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) |
1016 | _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) | 1064 | _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) |
1065 | _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk) | ||
1066 | _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk) | ||
1017 | }; | 1067 | }; |
1018 | 1068 | ||
1019 | static void clk_tree_init(void) | 1069 | static void clk_tree_init(void) |
@@ -1057,6 +1107,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, | |||
1057 | /* set the usboh3_clk parent to pll2_sw_clk */ | 1107 | /* set the usboh3_clk parent to pll2_sw_clk */ |
1058 | clk_set_parent(&usboh3_clk, &pll2_sw_clk); | 1108 | clk_set_parent(&usboh3_clk, &pll2_sw_clk); |
1059 | 1109 | ||
1110 | /* Set SDHC parents to be PLL2 */ | ||
1111 | clk_set_parent(&esdhc1_clk, &pll2_sw_clk); | ||
1112 | clk_set_parent(&esdhc2_clk, &pll2_sw_clk); | ||
1113 | |||
1114 | /* set SDHC root clock as 166.25MHZ*/ | ||
1115 | clk_set_rate(&esdhc1_clk, 166250000); | ||
1116 | clk_set_rate(&esdhc2_clk, 166250000); | ||
1117 | |||
1060 | /* System timer */ | 1118 | /* System timer */ |
1061 | mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), | 1119 | mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), |
1062 | MX51_MXC_INT_GPT); | 1120 | MX51_MXC_INT_GPT); |