diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-mx2/clock_imx21.c | 77 |
1 files changed, 51 insertions, 26 deletions
diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c index 999d013e06e3..fa2b292d7b3c 100644 --- a/arch/arm/mach-mx2/clock_imx21.c +++ b/arch/arm/mach-mx2/clock_imx21.c | |||
@@ -48,6 +48,25 @@ static void _clk_disable(struct clk *clk) | |||
48 | __raw_writel(reg, clk->enable_reg); | 48 | __raw_writel(reg, clk->enable_reg); |
49 | } | 49 | } |
50 | 50 | ||
51 | static unsigned long _clk_generic_round_rate(struct clk *clk, | ||
52 | unsigned long rate, | ||
53 | u32 max_divisor) | ||
54 | { | ||
55 | u32 div; | ||
56 | unsigned long parent_rate; | ||
57 | |||
58 | parent_rate = clk_get_rate(clk->parent); | ||
59 | |||
60 | div = parent_rate / rate; | ||
61 | if (parent_rate % rate) | ||
62 | div++; | ||
63 | |||
64 | if (div > max_divisor) | ||
65 | div = max_divisor; | ||
66 | |||
67 | return parent_rate / div; | ||
68 | } | ||
69 | |||
51 | static int _clk_spll_enable(struct clk *clk) | 70 | static int _clk_spll_enable(struct clk *clk) |
52 | { | 71 | { |
53 | u32 reg; | 72 | u32 reg; |
@@ -78,19 +97,7 @@ static void _clk_spll_disable(struct clk *clk) | |||
78 | static unsigned long _clk_perclkx_round_rate(struct clk *clk, | 97 | static unsigned long _clk_perclkx_round_rate(struct clk *clk, |
79 | unsigned long rate) | 98 | unsigned long rate) |
80 | { | 99 | { |
81 | u32 div; | 100 | return _clk_generic_round_rate(clk, rate, 64); |
82 | unsigned long parent_rate; | ||
83 | |||
84 | parent_rate = clk_get_rate(clk->parent); | ||
85 | |||
86 | div = parent_rate / rate; | ||
87 | if (parent_rate % rate) | ||
88 | div++; | ||
89 | |||
90 | if (div > 64) | ||
91 | div = 64; | ||
92 | |||
93 | return parent_rate / div; | ||
94 | } | 101 | } |
95 | 102 | ||
96 | static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) | 103 | static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) |
@@ -130,6 +137,32 @@ static unsigned long _clk_usb_recalc(struct clk *clk) | |||
130 | return parent_rate / (usb_pdf + 1U); | 137 | return parent_rate / (usb_pdf + 1U); |
131 | } | 138 | } |
132 | 139 | ||
140 | static unsigned long _clk_usb_round_rate(struct clk *clk, | ||
141 | unsigned long rate) | ||
142 | { | ||
143 | return _clk_generic_round_rate(clk, rate, 8); | ||
144 | } | ||
145 | |||
146 | static int _clk_usb_set_rate(struct clk *clk, unsigned long rate) | ||
147 | { | ||
148 | u32 reg; | ||
149 | u32 div; | ||
150 | unsigned long parent_rate; | ||
151 | |||
152 | parent_rate = clk_get_rate(clk->parent); | ||
153 | |||
154 | div = parent_rate / rate; | ||
155 | if (div > 8 || div < 1 || ((parent_rate / div) != rate)) | ||
156 | return -EINVAL; | ||
157 | div--; | ||
158 | |||
159 | reg = CSCR() & ~CCM_CSCR_USB_MASK; | ||
160 | reg |= div << CCM_CSCR_USB_OFFSET; | ||
161 | __raw_writel(reg, CCM_CSCR); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
133 | static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf) | 166 | static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf) |
134 | { | 167 | { |
135 | unsigned long parent_rate; | 168 | unsigned long parent_rate; |
@@ -595,11 +628,14 @@ static struct clk csi_clk[] = { | |||
595 | static struct clk usb_clk[] = { | 628 | static struct clk usb_clk[] = { |
596 | { | 629 | { |
597 | .parent = &spll_clk, | 630 | .parent = &spll_clk, |
631 | .secondary = &usb_clk[1], | ||
598 | .get_rate = _clk_usb_recalc, | 632 | .get_rate = _clk_usb_recalc, |
599 | .enable = _clk_enable, | 633 | .enable = _clk_enable, |
600 | .enable_reg = CCM_PCCR_USBOTG_REG, | 634 | .enable_reg = CCM_PCCR_USBOTG_REG, |
601 | .enable_shift = CCM_PCCR_USBOTG_OFFSET, | 635 | .enable_shift = CCM_PCCR_USBOTG_OFFSET, |
602 | .disable = _clk_disable, | 636 | .disable = _clk_disable, |
637 | .round_rate = _clk_usb_round_rate, | ||
638 | .set_rate = _clk_usb_set_rate, | ||
603 | }, { | 639 | }, { |
604 | .parent = &hclk_clk, | 640 | .parent = &hclk_clk, |
605 | .enable = _clk_enable, | 641 | .enable = _clk_enable, |
@@ -768,18 +804,7 @@ static struct clk rtc_clk = { | |||
768 | 804 | ||
769 | static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate) | 805 | static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate) |
770 | { | 806 | { |
771 | u32 div; | 807 | return _clk_generic_round_rate(clk, rate, 8); |
772 | unsigned long parent_rate; | ||
773 | |||
774 | parent_rate = clk_get_rate(clk->parent); | ||
775 | div = parent_rate / rate; | ||
776 | if (parent_rate % rate) | ||
777 | div++; | ||
778 | |||
779 | if (div > 8) | ||
780 | div = 8; | ||
781 | |||
782 | return parent_rate / div; | ||
783 | } | 808 | } |
784 | 809 | ||
785 | static int _clk_clko_set_rate(struct clk *clk, unsigned long rate) | 810 | static int _clk_clko_set_rate(struct clk *clk, unsigned long rate) |
@@ -921,7 +946,7 @@ static struct clk_lookup lookups[] __initdata = { | |||
921 | _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2]) | 946 | _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2]) |
922 | _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0]) | 947 | _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0]) |
923 | _REGISTER_CLOCK(NULL, "csi", csi_clk[0]) | 948 | _REGISTER_CLOCK(NULL, "csi", csi_clk[0]) |
924 | _REGISTER_CLOCK(NULL, "usb", usb_clk[0]) | 949 | _REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0]) |
925 | _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0]) | 950 | _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0]) |
926 | _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1]) | 951 | _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1]) |
927 | _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) | 952 | _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) |