aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx5/clock-mx51.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx5/clock-mx51.c')
-rw-r--r--arch/arm/mach-mx5/clock-mx51.c231
1 files changed, 204 insertions, 27 deletions
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 57c10a9926cc..21cecc040172 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -41,34 +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
44static int _clk_ccgr_enable(struct clk *clk) 44static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
45{ 45{
46 u32 reg; 46 u32 reg = __raw_readl(clk->enable_reg);
47
48 reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
49 reg |= mode << clk->enable_shift;
47 50
48 reg = __raw_readl(clk->enable_reg);
49 reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
50 __raw_writel(reg, clk->enable_reg); 51 __raw_writel(reg, clk->enable_reg);
52}
51 53
54static int _clk_ccgr_enable(struct clk *clk)
55{
56 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
52 return 0; 57 return 0;
53} 58}
54 59
55static void _clk_ccgr_disable(struct clk *clk) 60static void _clk_ccgr_disable(struct clk *clk)
56{ 61{
57 u32 reg; 62 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
58 reg = __raw_readl(clk->enable_reg); 63}
59 reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
60 __raw_writel(reg, clk->enable_reg);
61 64
65static int _clk_ccgr_enable_inrun(struct clk *clk)
66{
67 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
68 return 0;
62} 69}
63 70
64static void _clk_ccgr_disable_inwait(struct clk *clk) 71static void _clk_ccgr_disable_inwait(struct clk *clk)
65{ 72{
66 u32 reg; 73 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
67
68 reg = __raw_readl(clk->enable_reg);
69 reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
70 reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
71 __raw_writel(reg, clk->enable_reg);
72} 74}
73 75
74/* 76/*
@@ -571,6 +573,64 @@ static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
571 return 0; 573 return 0;
572} 574}
573 575
576#define clk_nfc_set_parent NULL
577
578static unsigned long clk_nfc_get_rate(struct clk *clk)
579{
580 unsigned long rate;
581 u32 reg, div;
582
583 reg = __raw_readl(MXC_CCM_CBCDR);
584 div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
585 MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
586 rate = clk_get_rate(clk->parent) / div;
587 WARN_ON(rate == 0);
588 return rate;
589}
590
591static unsigned long clk_nfc_round_rate(struct clk *clk,
592 unsigned long rate)
593{
594 u32 div;
595 unsigned long parent_rate = clk_get_rate(clk->parent);
596
597 if (!rate)
598 return -EINVAL;
599
600 div = parent_rate / rate;
601
602 if (parent_rate % rate)
603 div++;
604
605 if (div > 8)
606 return -EINVAL;
607
608 return parent_rate / div;
609
610}
611
612static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
613{
614 u32 reg, div;
615
616 div = clk_get_rate(clk->parent) / rate;
617 if (div == 0)
618 div++;
619 if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
620 return -EINVAL;
621
622 reg = __raw_readl(MXC_CCM_CBCDR);
623 reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
624 reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
625 __raw_writel(reg, MXC_CCM_CBCDR);
626
627 while (__raw_readl(MXC_CCM_CDHIPR) &
628 MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
629 }
630
631 return 0;
632}
633
574static unsigned long clk_usboh3_get_rate(struct clk *clk) 634static unsigned long clk_usboh3_get_rate(struct clk *clk)
575{ 635{
576 u32 reg, prediv, podf; 636 u32 reg, prediv, podf;
@@ -620,6 +680,17 @@ static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
620 return ckih2_reference; 680 return ckih2_reference;
621} 681}
622 682
683static unsigned long clk_emi_slow_get_rate(struct clk *clk)
684{
685 u32 reg, div;
686
687 reg = __raw_readl(MXC_CCM_CBCDR);
688 div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
689 MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
690
691 return clk_get_rate(clk->parent) / div;
692}
693
623/* External high frequency clock */ 694/* External high frequency clock */
624static struct clk ckih_clk = { 695static struct clk ckih_clk = {
625 .get_rate = get_high_reference_clock_rate, 696 .get_rate = get_high_reference_clock_rate,
@@ -762,45 +833,105 @@ static struct clk kpp_clk = {
762 .id = 0, 833 .id = 0,
763}; 834};
764 835
765#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \ 836static struct clk emi_slow_clk = {
837 .parent = &pll2_sw_clk,
838 .enable_reg = MXC_CCM_CCGR5,
839 .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
840 .enable = _clk_ccgr_enable,
841 .disable = _clk_ccgr_disable_inwait,
842 .get_rate = clk_emi_slow_get_rate,
843};
844
845#define DEFINE_CLOCK1(name, i, er, es, pfx, p, s) \
766 static struct clk name = { \ 846 static struct clk name = { \
767 .id = i, \ 847 .id = i, \
768 .enable_reg = er, \ 848 .enable_reg = er, \
769 .enable_shift = es, \ 849 .enable_shift = es, \
770 .get_rate = gr, \ 850 .get_rate = pfx##_get_rate, \
771 .set_rate = sr, \ 851 .set_rate = pfx##_set_rate, \
852 .round_rate = pfx##_round_rate, \
853 .set_parent = pfx##_set_parent, \
772 .enable = _clk_ccgr_enable, \ 854 .enable = _clk_ccgr_enable, \
773 .disable = _clk_ccgr_disable, \ 855 .disable = _clk_ccgr_disable, \
774 .parent = p, \ 856 .parent = p, \
775 .secondary = s, \ 857 .secondary = s, \
776 } 858 }
777 859
778/* DEFINE_CLOCK(name, id, enable_reg, enable_shift, 860/* eCSPI */
779 get_rate, set_rate, parent, secondary); */ 861static unsigned long clk_ecspi_get_rate(struct clk *clk)
862{
863 u32 reg, pred, podf;
864
865 reg = __raw_readl(MXC_CCM_CSCDR2);
866
867 pred = (reg & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) >>
868 MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET;
869 podf = (reg & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) >>
870 MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET;
871
872 return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),
873 (pred + 1) * (podf + 1));
874}
875
876static int clk_ecspi_set_parent(struct clk *clk, struct clk *parent)
877{
878 u32 reg, mux;
879
880 mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
881 &lp_apm_clk);
882
883 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK;
884 reg |= mux << MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
885 __raw_writel(reg, MXC_CCM_CSCMR1);
886
887 return 0;
888}
889
890static struct clk ecspi_main_clk = {
891 .parent = &pll3_sw_clk,
892 .get_rate = clk_ecspi_get_rate,
893 .set_parent = clk_ecspi_set_parent,
894};
895
896#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
897 static struct clk name = { \
898 .id = i, \
899 .enable_reg = er, \
900 .enable_shift = es, \
901 .get_rate = gr, \
902 .set_rate = sr, \
903 .enable = e, \
904 .disable = d, \
905 .parent = p, \
906 .secondary = s, \
907 }
908
909#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
910 DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
780 911
781/* Shared peripheral bus arbiter */ 912/* Shared peripheral bus arbiter */
782DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET, 913DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
783 NULL, NULL, &ipg_clk, NULL); 914 NULL, NULL, &ipg_clk, NULL);
784 915
785/* UART */ 916/* UART */
786DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
787 NULL, NULL, &uart_root_clk, NULL);
788DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
789 NULL, NULL, &uart_root_clk, NULL);
790DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
791 NULL, NULL, &uart_root_clk, NULL);
792DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET, 917DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
793 NULL, NULL, &ipg_clk, &aips_tz1_clk); 918 NULL, NULL, &ipg_clk, &aips_tz1_clk);
794DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET, 919DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
795 NULL, NULL, &ipg_clk, &aips_tz1_clk); 920 NULL, NULL, &ipg_clk, &aips_tz1_clk);
796DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET, 921DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
797 NULL, NULL, &ipg_clk, &spba_clk); 922 NULL, NULL, &ipg_clk, &spba_clk);
923DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
924 NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
925DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
926 NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
927DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
928 NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
798 929
799/* GPT */ 930/* GPT */
800DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
801 NULL, NULL, &ipg_clk, NULL);
802DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, 931DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
803 NULL, NULL, &ipg_clk, NULL); 932 NULL, NULL, &ipg_clk, NULL);
933DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
934 NULL, NULL, &ipg_clk, &gpt_ipg_clk);
804 935
805/* I2C */ 936/* I2C */
806DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET, 937DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -814,6 +945,42 @@ DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
814DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, 945DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
815 NULL, NULL, &ipg_clk, NULL); 946 NULL, NULL, &ipg_clk, NULL);
816 947
948/* NFC */
949DEFINE_CLOCK1(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
950 clk_nfc, &emi_slow_clk, NULL);
951
952/* SSI */
953DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
954 NULL, NULL, &ipg_clk, NULL);
955DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
956 NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
957DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
958 NULL, NULL, &ipg_clk, NULL);
959DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
960 NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
961
962/* eCSPI */
963DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
964 NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
965 &ipg_clk, &spba_clk);
966DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
967 NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
968DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
969 NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
970 &ipg_clk, &aips_tz2_clk);
971DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
972 NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
973
974/* CSPI */
975DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
976 NULL, NULL, &ipg_clk, &aips_tz2_clk);
977DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
978 NULL, NULL, &ipg_clk, &cspi_ipg_clk);
979
980/* SDMA */
981DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
982 NULL, NULL, &ahb_clk, NULL);
983
817#define _REGISTER_CLOCK(d, n, c) \ 984#define _REGISTER_CLOCK(d, n, c) \
818 { \ 985 { \
819 .dev_id = d, \ 986 .dev_id = d, \
@@ -837,6 +1004,16 @@ static struct clk_lookup lookups[] = {
837 _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk) 1004 _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
838 _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk) 1005 _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
839 _REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk) 1006 _REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
1007 _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
1008 _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
1009 _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
1010 _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
1011 _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
1012 _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
1013 _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
1014 _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
1015 _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
1016 _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
840}; 1017};
841 1018
842static void clk_tree_init(void) 1019static void clk_tree_init(void)