diff options
Diffstat (limited to 'firmware/target/arm/imx233/clkctrl-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/clkctrl-imx233.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.c b/firmware/target/arm/imx233/clkctrl-imx233.c index 59c23c1a76..1a8f523d5a 100644 --- a/firmware/target/arm/imx233/clkctrl-imx233.c +++ b/firmware/target/arm/imx233/clkctrl-imx233.c | |||
@@ -87,7 +87,9 @@ void imx233_clkctrl_set_div(enum imx233_clock_t clk, int div) | |||
87 | case CLK_EMI: BF_WR(CLKCTRL_EMI, DIV(div)); break; | 87 | case CLK_EMI: BF_WR(CLKCTRL_EMI, DIV(div)); break; |
88 | #endif | 88 | #endif |
89 | case CLK_SSP: BF_WR(CLKCTRL_SSP, DIV(div)); break; | 89 | case CLK_SSP: BF_WR(CLKCTRL_SSP, DIV(div)); break; |
90 | case CLK_HBUS: BF_WR(CLKCTRL_HBUS, DIV(div)); break; | 90 | case CLK_HBUS: |
91 | /* make sure to switch to integer divide mode simulteanously */ | ||
92 | BF_WR(CLKCTRL_HBUS, DIV_FRAC_EN(0), DIV(div)); break; | ||
91 | case CLK_XBUS: BF_WR(CLKCTRL_XBUS, DIV(div)); break; | 93 | case CLK_XBUS: BF_WR(CLKCTRL_XBUS, DIV(div)); break; |
92 | default: return; | 94 | default: return; |
93 | } | 95 | } |
@@ -107,7 +109,12 @@ int imx233_clkctrl_get_div(enum imx233_clock_t clk) | |||
107 | case CLK_EMI: return BF_RD(CLKCTRL_EMI, DIV); | 109 | case CLK_EMI: return BF_RD(CLKCTRL_EMI, DIV); |
108 | #endif | 110 | #endif |
109 | case CLK_SSP: return BF_RD(CLKCTRL_SSP, DIV); | 111 | case CLK_SSP: return BF_RD(CLKCTRL_SSP, DIV); |
110 | case CLK_HBUS: return BF_RD(CLKCTRL_HBUS, DIV); | 112 | case CLK_HBUS: |
113 | /* since fractional and integer divider share the same field, clain it is disabled in frac mode */ | ||
114 | if(BF_RD(CLKCTRL_HBUS, DIV_FRAC_EN)) | ||
115 | return 0; | ||
116 | else | ||
117 | return BF_RD(CLKCTRL_HBUS, DIV); | ||
111 | case CLK_XBUS: return BF_RD(CLKCTRL_XBUS, DIV); | 118 | case CLK_XBUS: return BF_RD(CLKCTRL_XBUS, DIV); |
112 | default: return 0; | 119 | default: return 0; |
113 | } | 120 | } |
@@ -130,6 +137,14 @@ void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv) | |||
130 | handle_frac(IO) | 137 | handle_frac(IO) |
131 | handle_frac(CPU) | 138 | handle_frac(CPU) |
132 | handle_frac(EMI) | 139 | handle_frac(EMI) |
140 | case CLK_HBUS: | ||
141 | if(fracdiv == 0) | ||
142 | panicf("Don't set hbus fracdiv to 0!"); | ||
143 | /* value 0 is forbidden because we can't simply disabble the divider, it's always | ||
144 | * active but either in integer or fractional mode | ||
145 | * make sure we write both the value and frac_en bit at the same time */ | ||
146 | BF_WR(CLKCTRL_HBUS, DIV_FRAC_EN(1), DIV(fracdiv)); | ||
147 | break; | ||
133 | default: break; | 148 | default: break; |
134 | } | 149 | } |
135 | #undef handle_frac | 150 | #undef handle_frac |
@@ -151,6 +166,11 @@ int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk) | |||
151 | handle_frac(IO) | 166 | handle_frac(IO) |
152 | handle_frac(CPU) | 167 | handle_frac(CPU) |
153 | handle_frac(EMI) | 168 | handle_frac(EMI) |
169 | case CLK_HBUS: | ||
170 | if(BF_RD(CLKCTRL_HBUS, DIV_FRAC_EN)) | ||
171 | return BF_RD(CLKCTRL_HBUS, DIV); | ||
172 | else | ||
173 | return 0; | ||
154 | default: return 0; | 174 | default: return 0; |
155 | } | 175 | } |
156 | #undef handle_frac | 176 | #undef handle_frac |
@@ -303,8 +323,12 @@ unsigned imx233_clkctrl_get_freq(enum imx233_clock_t clk) | |||
303 | /* Derived from clk_p via integer/fractional div */ | 323 | /* Derived from clk_p via integer/fractional div */ |
304 | unsigned ref = imx233_clkctrl_get_freq(CLK_CPU); | 324 | unsigned ref = imx233_clkctrl_get_freq(CLK_CPU); |
305 | #if IMX233_SUBTARGET >= 3700 | 325 | #if IMX233_SUBTARGET >= 3700 |
326 | /* if divider is in fractional mode, integer divider does not take effect (in fact it's | ||
327 | * the same divider but in a different mode ). Also the fractiona value is encoded as | ||
328 | * a fraction, not a divider */ | ||
306 | if(imx233_clkctrl_get_frac_div(CLK_HBUS) != 0) | 329 | if(imx233_clkctrl_get_frac_div(CLK_HBUS) != 0) |
307 | ref = (ref * imx233_clkctrl_get_frac_div(CLK_HBUS)) / 32; | 330 | ref = (ref * imx233_clkctrl_get_frac_div(CLK_HBUS)) / 32; |
331 | else | ||
308 | #endif | 332 | #endif |
309 | if(imx233_clkctrl_get_div(CLK_HBUS) != 0) | 333 | if(imx233_clkctrl_get_div(CLK_HBUS) != 0) |
310 | ref /= imx233_clkctrl_get_div(CLK_HBUS); | 334 | ref /= imx233_clkctrl_get_div(CLK_HBUS); |