diff options
| author | viresh kumar <viresh.kumar@st.com> | 2011-02-16 01:40:39 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-03-09 04:49:45 -0500 |
| commit | af89fd812b00a52c54a3b9b2290fae4d31c7be9a (patch) | |
| tree | 3892de4165b23e98424f672c23b7a6d456ad235d | |
| parent | cf285434ac0880f94bf4afdd90b06a4655f56570 (diff) | |
ARM: 6703/1: SPEAr: update clk API support
- Add support for divisor per parent clock
- Add ENABLED_ON_INIT feature in clk
- Add clk_set_rate(), round_rate_index & clk_round_rate()
- Simplify clk_recalc functions
- Add/update clock definitions
Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/arm/mach-spear3xx/clock.c | 431 | ||||
| -rw-r--r-- | arch/arm/mach-spear3xx/include/mach/misc_regs.h | 5 | ||||
| -rw-r--r-- | arch/arm/mach-spear6xx/clock.c | 331 | ||||
| -rw-r--r-- | arch/arm/mach-spear6xx/include/mach/misc_regs.h | 5 | ||||
| -rw-r--r-- | arch/arm/plat-spear/clock.c | 705 | ||||
| -rw-r--r-- | arch/arm/plat-spear/include/plat/clock.h | 94 |
6 files changed, 1259 insertions, 312 deletions
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c index 7ea8749ddf28..8ae4ad0326a9 100644 --- a/arch/arm/mach-spear3xx/clock.c +++ b/arch/arm/mach-spear3xx/clock.c | |||
| @@ -60,12 +60,22 @@ static struct pll_clk_config pll1_config = { | |||
| 60 | .masks = &pll1_masks, | 60 | .masks = &pll1_masks, |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | /* pll rate configuration table, in ascending order of rates */ | ||
| 64 | struct pll_rate_tbl pll_rtbl[] = { | ||
| 65 | {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */ | ||
| 66 | {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */ | ||
| 67 | }; | ||
| 68 | |||
| 63 | /* PLL1 clock */ | 69 | /* PLL1 clock */ |
| 64 | static struct clk pll1_clk = { | 70 | static struct clk pll1_clk = { |
| 71 | .flags = ENABLED_ON_INIT, | ||
| 65 | .pclk = &osc_24m_clk, | 72 | .pclk = &osc_24m_clk, |
| 66 | .en_reg = PLL1_CTR, | 73 | .en_reg = PLL1_CTR, |
| 67 | .en_reg_bit = PLL_ENABLE, | 74 | .en_reg_bit = PLL_ENABLE, |
| 75 | .calc_rate = &pll_calc_rate, | ||
| 68 | .recalc = &pll_clk_recalc, | 76 | .recalc = &pll_clk_recalc, |
| 77 | .set_rate = &pll_clk_set_rate, | ||
| 78 | .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1}, | ||
| 69 | .private_data = &pll1_config, | 79 | .private_data = &pll1_config, |
| 70 | }; | 80 | }; |
| 71 | 81 | ||
| @@ -103,11 +113,22 @@ static struct bus_clk_config ahb_config = { | |||
| 103 | .masks = &ahb_masks, | 113 | .masks = &ahb_masks, |
| 104 | }; | 114 | }; |
| 105 | 115 | ||
| 116 | /* ahb rate configuration table, in ascending order of rates */ | ||
| 117 | struct bus_rate_tbl bus_rtbl[] = { | ||
| 118 | {.div = 3}, /* == parent divided by 4 */ | ||
| 119 | {.div = 2}, /* == parent divided by 3 */ | ||
| 120 | {.div = 1}, /* == parent divided by 2 */ | ||
| 121 | {.div = 0}, /* == parent divided by 1 */ | ||
| 122 | }; | ||
| 123 | |||
| 106 | /* ahb clock */ | 124 | /* ahb clock */ |
| 107 | static struct clk ahb_clk = { | 125 | static struct clk ahb_clk = { |
| 108 | .flags = ALWAYS_ENABLED, | 126 | .flags = ALWAYS_ENABLED, |
| 109 | .pclk = &pll1_clk, | 127 | .pclk = &pll1_clk, |
| 128 | .calc_rate = &bus_calc_rate, | ||
| 110 | .recalc = &bus_clk_recalc, | 129 | .recalc = &bus_clk_recalc, |
| 130 | .set_rate = &bus_clk_set_rate, | ||
| 131 | .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, | ||
| 111 | .private_data = &ahb_config, | 132 | .private_data = &ahb_config, |
| 112 | }; | 133 | }; |
| 113 | 134 | ||
| @@ -123,22 +144,40 @@ static struct aux_clk_masks aux_masks = { | |||
| 123 | .yscale_sel_shift = AUX_YSCALE_SHIFT, | 144 | .yscale_sel_shift = AUX_YSCALE_SHIFT, |
| 124 | }; | 145 | }; |
| 125 | 146 | ||
| 126 | /* uart configurations */ | 147 | /* uart synth configurations */ |
| 127 | static struct aux_clk_config uart_config = { | 148 | static struct aux_clk_config uart_synth_config = { |
| 128 | .synth_reg = UART_CLK_SYNT, | 149 | .synth_reg = UART_CLK_SYNT, |
| 129 | .masks = &aux_masks, | 150 | .masks = &aux_masks, |
| 130 | }; | 151 | }; |
| 131 | 152 | ||
| 153 | /* aux rate configuration table, in ascending order of rates */ | ||
| 154 | struct aux_rate_tbl aux_rtbl[] = { | ||
| 155 | /* For PLL1 = 332 MHz */ | ||
| 156 | {.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */ | ||
| 157 | {.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */ | ||
| 158 | {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */ | ||
| 159 | }; | ||
| 160 | |||
| 161 | /* uart synth clock */ | ||
| 162 | static struct clk uart_synth_clk = { | ||
| 163 | .en_reg = UART_CLK_SYNT, | ||
| 164 | .en_reg_bit = AUX_SYNT_ENB, | ||
| 165 | .pclk = &pll1_clk, | ||
| 166 | .calc_rate = &aux_calc_rate, | ||
| 167 | .recalc = &aux_clk_recalc, | ||
| 168 | .set_rate = &aux_clk_set_rate, | ||
| 169 | .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1}, | ||
| 170 | .private_data = &uart_synth_config, | ||
| 171 | }; | ||
| 172 | |||
| 132 | /* uart parents */ | 173 | /* uart parents */ |
| 133 | static struct pclk_info uart_pclk_info[] = { | 174 | static struct pclk_info uart_pclk_info[] = { |
| 134 | { | 175 | { |
| 135 | .pclk = &pll1_clk, | 176 | .pclk = &uart_synth_clk, |
| 136 | .pclk_mask = AUX_CLK_PLL1_MASK, | 177 | .pclk_val = AUX_CLK_PLL1_VAL, |
| 137 | .scalable = 1, | ||
| 138 | }, { | 178 | }, { |
| 139 | .pclk = &pll3_48m_clk, | 179 | .pclk = &pll3_48m_clk, |
| 140 | .pclk_mask = AUX_CLK_PLL3_MASK, | 180 | .pclk_val = AUX_CLK_PLL3_VAL, |
| 141 | .scalable = 0, | ||
| 142 | }, | 181 | }, |
| 143 | }; | 182 | }; |
| 144 | 183 | ||
| @@ -156,26 +195,35 @@ static struct clk uart_clk = { | |||
| 156 | .en_reg_bit = UART_CLK_ENB, | 195 | .en_reg_bit = UART_CLK_ENB, |
| 157 | .pclk_sel = &uart_pclk_sel, | 196 | .pclk_sel = &uart_pclk_sel, |
| 158 | .pclk_sel_shift = UART_CLK_SHIFT, | 197 | .pclk_sel_shift = UART_CLK_SHIFT, |
| 159 | .recalc = &aux_clk_recalc, | 198 | .recalc = &follow_parent, |
| 160 | .private_data = &uart_config, | ||
| 161 | }; | 199 | }; |
| 162 | 200 | ||
| 163 | /* firda configurations */ | 201 | /* firda configurations */ |
| 164 | static struct aux_clk_config firda_config = { | 202 | static struct aux_clk_config firda_synth_config = { |
| 165 | .synth_reg = FIRDA_CLK_SYNT, | 203 | .synth_reg = FIRDA_CLK_SYNT, |
| 166 | .masks = &aux_masks, | 204 | .masks = &aux_masks, |
| 167 | }; | 205 | }; |
| 168 | 206 | ||
| 207 | /* firda synth clock */ | ||
| 208 | static struct clk firda_synth_clk = { | ||
| 209 | .en_reg = FIRDA_CLK_SYNT, | ||
| 210 | .en_reg_bit = AUX_SYNT_ENB, | ||
| 211 | .pclk = &pll1_clk, | ||
| 212 | .calc_rate = &aux_calc_rate, | ||
| 213 | .recalc = &aux_clk_recalc, | ||
| 214 | .set_rate = &aux_clk_set_rate, | ||
| 215 | .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1}, | ||
| 216 | .private_data = &firda_synth_config, | ||
| 217 | }; | ||
| 218 | |||
| 169 | /* firda parents */ | 219 | /* firda parents */ |
| 170 | static struct pclk_info firda_pclk_info[] = { | 220 | static struct pclk_info firda_pclk_info[] = { |
| 171 | { | 221 | { |
| 172 | .pclk = &pll1_clk, | 222 | .pclk = &firda_synth_clk, |
| 173 | .pclk_mask = AUX_CLK_PLL1_MASK, | 223 | .pclk_val = AUX_CLK_PLL1_VAL, |
| 174 | .scalable = 1, | ||
| 175 | }, { | 224 | }, { |
| 176 | .pclk = &pll3_48m_clk, | 225 | .pclk = &pll3_48m_clk, |
| 177 | .pclk_mask = AUX_CLK_PLL3_MASK, | 226 | .pclk_val = AUX_CLK_PLL3_VAL, |
| 178 | .scalable = 0, | ||
| 179 | }, | 227 | }, |
| 180 | }; | 228 | }; |
| 181 | 229 | ||
| @@ -193,84 +241,155 @@ static struct clk firda_clk = { | |||
| 193 | .en_reg_bit = FIRDA_CLK_ENB, | 241 | .en_reg_bit = FIRDA_CLK_ENB, |
| 194 | .pclk_sel = &firda_pclk_sel, | 242 | .pclk_sel = &firda_pclk_sel, |
| 195 | .pclk_sel_shift = FIRDA_CLK_SHIFT, | 243 | .pclk_sel_shift = FIRDA_CLK_SHIFT, |
| 196 | .recalc = &aux_clk_recalc, | 244 | .recalc = &follow_parent, |
| 197 | .private_data = &firda_config, | 245 | }; |
| 246 | |||
| 247 | /* gpt synthesizer masks */ | ||
| 248 | static struct gpt_clk_masks gpt_masks = { | ||
| 249 | .mscale_sel_mask = GPT_MSCALE_MASK, | ||
| 250 | .mscale_sel_shift = GPT_MSCALE_SHIFT, | ||
| 251 | .nscale_sel_mask = GPT_NSCALE_MASK, | ||
| 252 | .nscale_sel_shift = GPT_NSCALE_SHIFT, | ||
| 253 | }; | ||
| 254 | |||
| 255 | /* gpt rate configuration table, in ascending order of rates */ | ||
| 256 | struct gpt_rate_tbl gpt_rtbl[] = { | ||
| 257 | /* For pll1 = 332 MHz */ | ||
| 258 | {.mscale = 4, .nscale = 0}, /* 41.5 MHz */ | ||
| 259 | {.mscale = 2, .nscale = 0}, /* 55.3 MHz */ | ||
| 260 | {.mscale = 1, .nscale = 0}, /* 83 MHz */ | ||
| 261 | }; | ||
| 262 | |||
| 263 | /* gpt0 synth clk config*/ | ||
| 264 | static struct gpt_clk_config gpt0_synth_config = { | ||
| 265 | .synth_reg = PRSC1_CLK_CFG, | ||
| 266 | .masks = &gpt_masks, | ||
| 267 | }; | ||
| 268 | |||
| 269 | /* gpt synth clock */ | ||
| 270 | static struct clk gpt0_synth_clk = { | ||
| 271 | .flags = ALWAYS_ENABLED, | ||
| 272 | .pclk = &pll1_clk, | ||
| 273 | .calc_rate = &gpt_calc_rate, | ||
| 274 | .recalc = &gpt_clk_recalc, | ||
| 275 | .set_rate = &gpt_clk_set_rate, | ||
| 276 | .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, | ||
| 277 | .private_data = &gpt0_synth_config, | ||
| 198 | }; | 278 | }; |
| 199 | 279 | ||
| 200 | /* gpt parents */ | 280 | /* gpt parents */ |
| 201 | static struct pclk_info gpt_pclk_info[] = { | 281 | static struct pclk_info gpt0_pclk_info[] = { |
| 202 | { | 282 | { |
| 203 | .pclk = &pll1_clk, | 283 | .pclk = &gpt0_synth_clk, |
| 204 | .pclk_mask = AUX_CLK_PLL1_MASK, | 284 | .pclk_val = AUX_CLK_PLL1_VAL, |
| 205 | .scalable = 1, | ||
| 206 | }, { | 285 | }, { |
| 207 | .pclk = &pll3_48m_clk, | 286 | .pclk = &pll3_48m_clk, |
| 208 | .pclk_mask = AUX_CLK_PLL3_MASK, | 287 | .pclk_val = AUX_CLK_PLL3_VAL, |
| 209 | .scalable = 0, | ||
| 210 | }, | 288 | }, |
| 211 | }; | 289 | }; |
| 212 | 290 | ||
| 213 | /* gpt parent select structure */ | 291 | /* gpt parent select structure */ |
| 214 | static struct pclk_sel gpt_pclk_sel = { | 292 | static struct pclk_sel gpt0_pclk_sel = { |
| 215 | .pclk_info = gpt_pclk_info, | 293 | .pclk_info = gpt0_pclk_info, |
| 216 | .pclk_count = ARRAY_SIZE(gpt_pclk_info), | 294 | .pclk_count = ARRAY_SIZE(gpt0_pclk_info), |
| 217 | .pclk_sel_reg = PERIP_CLK_CFG, | 295 | .pclk_sel_reg = PERIP_CLK_CFG, |
| 218 | .pclk_sel_mask = GPT_CLK_MASK, | 296 | .pclk_sel_mask = GPT_CLK_MASK, |
| 219 | }; | 297 | }; |
| 220 | 298 | ||
| 221 | /* gpt synthesizer masks */ | 299 | /* gpt0 timer clock */ |
| 222 | static struct gpt_clk_masks gpt_masks = { | 300 | static struct clk gpt0_clk = { |
| 223 | .mscale_sel_mask = GPT_MSCALE_MASK, | 301 | .flags = ALWAYS_ENABLED, |
| 224 | .mscale_sel_shift = GPT_MSCALE_SHIFT, | 302 | .pclk_sel = &gpt0_pclk_sel, |
| 225 | .nscale_sel_mask = GPT_NSCALE_MASK, | 303 | .pclk_sel_shift = GPT0_CLK_SHIFT, |
| 226 | .nscale_sel_shift = GPT_NSCALE_SHIFT, | 304 | .recalc = &follow_parent, |
| 227 | }; | 305 | }; |
| 228 | 306 | ||
| 229 | /* gpt0 configurations */ | 307 | /* gpt1 synth clk configurations */ |
| 230 | static struct gpt_clk_config gpt0_config = { | 308 | static struct gpt_clk_config gpt1_synth_config = { |
| 231 | .synth_reg = PRSC1_CLK_CFG, | 309 | .synth_reg = PRSC2_CLK_CFG, |
| 232 | .masks = &gpt_masks, | 310 | .masks = &gpt_masks, |
| 233 | }; | 311 | }; |
| 234 | 312 | ||
| 235 | /* gpt0 timer clock */ | 313 | /* gpt1 synth clock */ |
| 236 | static struct clk gpt0_clk = { | 314 | static struct clk gpt1_synth_clk = { |
| 237 | .flags = ALWAYS_ENABLED, | 315 | .flags = ALWAYS_ENABLED, |
| 238 | .pclk_sel = &gpt_pclk_sel, | 316 | .pclk = &pll1_clk, |
| 239 | .pclk_sel_shift = GPT0_CLK_SHIFT, | 317 | .calc_rate = &gpt_calc_rate, |
| 240 | .recalc = &gpt_clk_recalc, | 318 | .recalc = &gpt_clk_recalc, |
| 241 | .private_data = &gpt0_config, | 319 | .set_rate = &gpt_clk_set_rate, |
| 320 | .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, | ||
| 321 | .private_data = &gpt1_synth_config, | ||
| 242 | }; | 322 | }; |
| 243 | 323 | ||
| 244 | /* gpt1 configurations */ | 324 | static struct pclk_info gpt1_pclk_info[] = { |
| 245 | static struct gpt_clk_config gpt1_config = { | 325 | { |
| 246 | .synth_reg = PRSC2_CLK_CFG, | 326 | .pclk = &gpt1_synth_clk, |
| 247 | .masks = &gpt_masks, | 327 | .pclk_val = AUX_CLK_PLL1_VAL, |
| 328 | }, { | ||
| 329 | .pclk = &pll3_48m_clk, | ||
| 330 | .pclk_val = AUX_CLK_PLL3_VAL, | ||
| 331 | }, | ||
| 332 | }; | ||
| 333 | |||
| 334 | /* gpt parent select structure */ | ||
| 335 | static struct pclk_sel gpt1_pclk_sel = { | ||
| 336 | .pclk_info = gpt1_pclk_info, | ||
| 337 | .pclk_count = ARRAY_SIZE(gpt1_pclk_info), | ||
| 338 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 339 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 248 | }; | 340 | }; |
| 249 | 341 | ||
| 250 | /* gpt1 timer clock */ | 342 | /* gpt1 timer clock */ |
| 251 | static struct clk gpt1_clk = { | 343 | static struct clk gpt1_clk = { |
| 252 | .en_reg = PERIP1_CLK_ENB, | 344 | .en_reg = PERIP1_CLK_ENB, |
| 253 | .en_reg_bit = GPT1_CLK_ENB, | 345 | .en_reg_bit = GPT1_CLK_ENB, |
| 254 | .pclk_sel = &gpt_pclk_sel, | 346 | .pclk_sel = &gpt1_pclk_sel, |
| 255 | .pclk_sel_shift = GPT1_CLK_SHIFT, | 347 | .pclk_sel_shift = GPT1_CLK_SHIFT, |
| 256 | .recalc = &gpt_clk_recalc, | 348 | .recalc = &follow_parent, |
| 257 | .private_data = &gpt1_config, | ||
| 258 | }; | 349 | }; |
| 259 | 350 | ||
| 260 | /* gpt2 configurations */ | 351 | /* gpt2 synth clk configurations */ |
| 261 | static struct gpt_clk_config gpt2_config = { | 352 | static struct gpt_clk_config gpt2_synth_config = { |
| 262 | .synth_reg = PRSC3_CLK_CFG, | 353 | .synth_reg = PRSC3_CLK_CFG, |
| 263 | .masks = &gpt_masks, | 354 | .masks = &gpt_masks, |
| 264 | }; | 355 | }; |
| 265 | 356 | ||
| 357 | /* gpt1 synth clock */ | ||
| 358 | static struct clk gpt2_synth_clk = { | ||
| 359 | .flags = ALWAYS_ENABLED, | ||
| 360 | .pclk = &pll1_clk, | ||
| 361 | .calc_rate = &gpt_calc_rate, | ||
| 362 | .recalc = &gpt_clk_recalc, | ||
| 363 | .set_rate = &gpt_clk_set_rate, | ||
| 364 | .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, | ||
| 365 | .private_data = &gpt2_synth_config, | ||
| 366 | }; | ||
| 367 | |||
| 368 | static struct pclk_info gpt2_pclk_info[] = { | ||
| 369 | { | ||
| 370 | .pclk = &gpt2_synth_clk, | ||
| 371 | .pclk_val = AUX_CLK_PLL1_VAL, | ||
| 372 | }, { | ||
| 373 | .pclk = &pll3_48m_clk, | ||
| 374 | .pclk_val = AUX_CLK_PLL3_VAL, | ||
| 375 | }, | ||
| 376 | }; | ||
| 377 | |||
| 378 | /* gpt parent select structure */ | ||
| 379 | static struct pclk_sel gpt2_pclk_sel = { | ||
| 380 | .pclk_info = gpt2_pclk_info, | ||
| 381 | .pclk_count = ARRAY_SIZE(gpt2_pclk_info), | ||
| 382 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 383 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 384 | }; | ||
| 385 | |||
| 266 | /* gpt2 timer clock */ | 386 | /* gpt2 timer clock */ |
| 267 | static struct clk gpt2_clk = { | 387 | static struct clk gpt2_clk = { |
| 268 | .en_reg = PERIP1_CLK_ENB, | 388 | .en_reg = PERIP1_CLK_ENB, |
| 269 | .en_reg_bit = GPT2_CLK_ENB, | 389 | .en_reg_bit = GPT2_CLK_ENB, |
| 270 | .pclk_sel = &gpt_pclk_sel, | 390 | .pclk_sel = &gpt2_pclk_sel, |
| 271 | .pclk_sel_shift = GPT2_CLK_SHIFT, | 391 | .pclk_sel_shift = GPT2_CLK_SHIFT, |
| 272 | .recalc = &gpt_clk_recalc, | 392 | .recalc = &follow_parent, |
| 273 | .private_data = &gpt2_config, | ||
| 274 | }; | 393 | }; |
| 275 | 394 | ||
| 276 | /* clock derived from pll3 clk */ | 395 | /* clock derived from pll3 clk */ |
| @@ -290,13 +409,6 @@ static struct clk usbd_clk = { | |||
| 290 | .recalc = &follow_parent, | 409 | .recalc = &follow_parent, |
| 291 | }; | 410 | }; |
| 292 | 411 | ||
| 293 | /* clcd clock */ | ||
| 294 | static struct clk clcd_clk = { | ||
| 295 | .flags = ALWAYS_ENABLED, | ||
| 296 | .pclk = &pll3_48m_clk, | ||
| 297 | .recalc = &follow_parent, | ||
| 298 | }; | ||
| 299 | |||
| 300 | /* clock derived from ahb clk */ | 412 | /* clock derived from ahb clk */ |
| 301 | /* apb masks structure */ | 413 | /* apb masks structure */ |
| 302 | static struct bus_clk_masks apb_masks = { | 414 | static struct bus_clk_masks apb_masks = { |
| @@ -314,7 +426,10 @@ static struct bus_clk_config apb_config = { | |||
| 314 | static struct clk apb_clk = { | 426 | static struct clk apb_clk = { |
| 315 | .flags = ALWAYS_ENABLED, | 427 | .flags = ALWAYS_ENABLED, |
| 316 | .pclk = &ahb_clk, | 428 | .pclk = &ahb_clk, |
| 429 | .calc_rate = &bus_calc_rate, | ||
| 317 | .recalc = &bus_clk_recalc, | 430 | .recalc = &bus_clk_recalc, |
| 431 | .set_rate = &bus_clk_set_rate, | ||
| 432 | .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, | ||
| 318 | .private_data = &apb_config, | 433 | .private_data = &apb_config, |
| 319 | }; | 434 | }; |
| 320 | 435 | ||
| @@ -375,8 +490,17 @@ static struct clk adc_clk = { | |||
| 375 | .recalc = &follow_parent, | 490 | .recalc = &follow_parent, |
| 376 | }; | 491 | }; |
| 377 | 492 | ||
| 493 | #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) | ||
| 494 | /* emi clock */ | ||
| 495 | static struct clk emi_clk = { | ||
| 496 | .flags = ALWAYS_ENABLED, | ||
| 497 | .pclk = &ahb_clk, | ||
| 498 | .recalc = &follow_parent, | ||
| 499 | }; | ||
| 500 | #endif | ||
| 501 | |||
| 378 | /* ssp clock */ | 502 | /* ssp clock */ |
| 379 | static struct clk ssp_clk = { | 503 | static struct clk ssp0_clk = { |
| 380 | .pclk = &apb_clk, | 504 | .pclk = &apb_clk, |
| 381 | .en_reg = PERIP1_CLK_ENB, | 505 | .en_reg = PERIP1_CLK_ENB, |
| 382 | .en_reg_bit = SSP_CLK_ENB, | 506 | .en_reg_bit = SSP_CLK_ENB, |
| @@ -393,6 +517,137 @@ static struct clk gpio_clk = { | |||
| 393 | 517 | ||
| 394 | static struct clk dummy_apb_pclk; | 518 | static struct clk dummy_apb_pclk; |
| 395 | 519 | ||
| 520 | #if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \ | ||
| 521 | defined(CONFIG_MACH_SPEAR320) | ||
| 522 | /* fsmc clock */ | ||
| 523 | static struct clk fsmc_clk = { | ||
| 524 | .flags = ALWAYS_ENABLED, | ||
| 525 | .pclk = &ahb_clk, | ||
| 526 | .recalc = &follow_parent, | ||
| 527 | }; | ||
| 528 | #endif | ||
| 529 | |||
| 530 | /* common clocks to spear310 and spear320 */ | ||
| 531 | #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) | ||
| 532 | /* uart1 clock */ | ||
| 533 | static struct clk uart1_clk = { | ||
| 534 | .flags = ALWAYS_ENABLED, | ||
| 535 | .pclk = &apb_clk, | ||
| 536 | .recalc = &follow_parent, | ||
| 537 | }; | ||
| 538 | |||
| 539 | /* uart2 clock */ | ||
| 540 | static struct clk uart2_clk = { | ||
| 541 | .flags = ALWAYS_ENABLED, | ||
| 542 | .pclk = &apb_clk, | ||
| 543 | .recalc = &follow_parent, | ||
| 544 | }; | ||
| 545 | #endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */ | ||
| 546 | |||
| 547 | /* common clocks to spear300 and spear320 */ | ||
| 548 | #if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320) | ||
| 549 | /* clcd clock */ | ||
| 550 | static struct clk clcd_clk = { | ||
| 551 | .flags = ALWAYS_ENABLED, | ||
| 552 | .pclk = &pll3_48m_clk, | ||
| 553 | .recalc = &follow_parent, | ||
| 554 | }; | ||
| 555 | |||
| 556 | /* sdhci clock */ | ||
| 557 | static struct clk sdhci_clk = { | ||
| 558 | .flags = ALWAYS_ENABLED, | ||
| 559 | .pclk = &ahb_clk, | ||
| 560 | .recalc = &follow_parent, | ||
| 561 | }; | ||
| 562 | #endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */ | ||
| 563 | |||
| 564 | /* spear300 machine specific clock structures */ | ||
| 565 | #ifdef CONFIG_MACH_SPEAR300 | ||
| 566 | /* gpio1 clock */ | ||
| 567 | static struct clk gpio1_clk = { | ||
| 568 | .flags = ALWAYS_ENABLED, | ||
| 569 | .pclk = &apb_clk, | ||
| 570 | .recalc = &follow_parent, | ||
| 571 | }; | ||
| 572 | |||
| 573 | /* keyboard clock */ | ||
| 574 | static struct clk kbd_clk = { | ||
| 575 | .flags = ALWAYS_ENABLED, | ||
| 576 | .pclk = &apb_clk, | ||
| 577 | .recalc = &follow_parent, | ||
| 578 | }; | ||
| 579 | |||
| 580 | #endif | ||
| 581 | |||
| 582 | /* spear310 machine specific clock structures */ | ||
| 583 | #ifdef CONFIG_MACH_SPEAR310 | ||
| 584 | /* uart3 clock */ | ||
| 585 | static struct clk uart3_clk = { | ||
| 586 | .flags = ALWAYS_ENABLED, | ||
| 587 | .pclk = &apb_clk, | ||
| 588 | .recalc = &follow_parent, | ||
| 589 | }; | ||
| 590 | |||
| 591 | /* uart4 clock */ | ||
| 592 | static struct clk uart4_clk = { | ||
| 593 | .flags = ALWAYS_ENABLED, | ||
| 594 | .pclk = &apb_clk, | ||
| 595 | .recalc = &follow_parent, | ||
| 596 | }; | ||
| 597 | |||
| 598 | /* uart5 clock */ | ||
| 599 | static struct clk uart5_clk = { | ||
| 600 | .flags = ALWAYS_ENABLED, | ||
| 601 | .pclk = &apb_clk, | ||
| 602 | .recalc = &follow_parent, | ||
| 603 | }; | ||
| 604 | #endif | ||
| 605 | |||
| 606 | /* spear320 machine specific clock structures */ | ||
| 607 | #ifdef CONFIG_MACH_SPEAR320 | ||
| 608 | /* can0 clock */ | ||
| 609 | static struct clk can0_clk = { | ||
| 610 | .flags = ALWAYS_ENABLED, | ||
| 611 | .pclk = &apb_clk, | ||
| 612 | .recalc = &follow_parent, | ||
| 613 | }; | ||
| 614 | |||
| 615 | /* can1 clock */ | ||
| 616 | static struct clk can1_clk = { | ||
| 617 | .flags = ALWAYS_ENABLED, | ||
| 618 | .pclk = &apb_clk, | ||
| 619 | .recalc = &follow_parent, | ||
| 620 | }; | ||
| 621 | |||
| 622 | /* i2c1 clock */ | ||
| 623 | static struct clk i2c1_clk = { | ||
| 624 | .flags = ALWAYS_ENABLED, | ||
| 625 | .pclk = &ahb_clk, | ||
| 626 | .recalc = &follow_parent, | ||
| 627 | }; | ||
| 628 | |||
| 629 | /* ssp1 clock */ | ||
| 630 | static struct clk ssp1_clk = { | ||
| 631 | .flags = ALWAYS_ENABLED, | ||
| 632 | .pclk = &apb_clk, | ||
| 633 | .recalc = &follow_parent, | ||
| 634 | }; | ||
| 635 | |||
| 636 | /* ssp2 clock */ | ||
| 637 | static struct clk ssp2_clk = { | ||
| 638 | .flags = ALWAYS_ENABLED, | ||
| 639 | .pclk = &apb_clk, | ||
| 640 | .recalc = &follow_parent, | ||
| 641 | }; | ||
| 642 | |||
| 643 | /* pwm clock */ | ||
| 644 | static struct clk pwm_clk = { | ||
| 645 | .flags = ALWAYS_ENABLED, | ||
| 646 | .pclk = &apb_clk, | ||
| 647 | .recalc = &follow_parent, | ||
| 648 | }; | ||
| 649 | #endif | ||
| 650 | |||
| 396 | /* array of all spear 3xx clock lookups */ | 651 | /* array of all spear 3xx clock lookups */ |
| 397 | static struct clk_lookup spear_clk_lookups[] = { | 652 | static struct clk_lookup spear_clk_lookups[] = { |
| 398 | { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, | 653 | { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, |
| @@ -400,7 +655,7 @@ static struct clk_lookup spear_clk_lookups[] = { | |||
| 400 | { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, | 655 | { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, |
| 401 | { .con_id = "osc_24m_clk", .clk = &osc_24m_clk}, | 656 | { .con_id = "osc_24m_clk", .clk = &osc_24m_clk}, |
| 402 | /* clock derived from 32 KHz osc clk */ | 657 | /* clock derived from 32 KHz osc clk */ |
| 403 | { .dev_id = "rtc", .clk = &rtc_clk}, | 658 | { .dev_id = "rtc-spear", .clk = &rtc_clk}, |
| 404 | /* clock derived from 24 MHz osc clk */ | 659 | /* clock derived from 24 MHz osc clk */ |
| 405 | { .con_id = "pll1_clk", .clk = &pll1_clk}, | 660 | { .con_id = "pll1_clk", .clk = &pll1_clk}, |
| 406 | { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, | 661 | { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, |
| @@ -408,18 +663,22 @@ static struct clk_lookup spear_clk_lookups[] = { | |||
| 408 | /* clock derived from pll1 clk */ | 663 | /* clock derived from pll1 clk */ |
| 409 | { .con_id = "cpu_clk", .clk = &cpu_clk}, | 664 | { .con_id = "cpu_clk", .clk = &cpu_clk}, |
| 410 | { .con_id = "ahb_clk", .clk = &ahb_clk}, | 665 | { .con_id = "ahb_clk", .clk = &ahb_clk}, |
| 666 | { .con_id = "uart_synth_clk", .clk = &uart_synth_clk}, | ||
| 667 | { .con_id = "firda_synth_clk", .clk = &firda_synth_clk}, | ||
| 668 | { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk}, | ||
| 669 | { .con_id = "gpt1_synth_clk", .clk = &gpt1_synth_clk}, | ||
| 670 | { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk}, | ||
| 411 | { .dev_id = "uart", .clk = &uart_clk}, | 671 | { .dev_id = "uart", .clk = &uart_clk}, |
| 412 | { .dev_id = "firda", .clk = &firda_clk}, | 672 | { .dev_id = "firda", .clk = &firda_clk}, |
| 413 | { .dev_id = "gpt0", .clk = &gpt0_clk}, | 673 | { .dev_id = "gpt0", .clk = &gpt0_clk}, |
| 414 | { .dev_id = "gpt1", .clk = &gpt1_clk}, | 674 | { .dev_id = "gpt1", .clk = &gpt1_clk}, |
| 415 | { .dev_id = "gpt2", .clk = &gpt2_clk}, | 675 | { .dev_id = "gpt2", .clk = &gpt2_clk}, |
| 416 | /* clock derived from pll3 clk */ | 676 | /* clock derived from pll3 clk */ |
| 417 | { .dev_id = "usbh", .clk = &usbh_clk}, | 677 | { .con_id = "usbh_clk", .clk = &usbh_clk}, |
| 418 | { .dev_id = "usbd", .clk = &usbd_clk}, | 678 | { .dev_id = "usbd", .clk = &usbd_clk}, |
| 419 | { .dev_id = "clcd", .clk = &clcd_clk}, | ||
| 420 | /* clock derived from ahb clk */ | 679 | /* clock derived from ahb clk */ |
| 421 | { .con_id = "apb_clk", .clk = &apb_clk}, | 680 | { .con_id = "apb_clk", .clk = &apb_clk}, |
| 422 | { .dev_id = "i2c", .clk = &i2c_clk}, | 681 | { .dev_id = "i2c_designware.0", .clk = &i2c_clk}, |
| 423 | { .dev_id = "dma", .clk = &dma_clk}, | 682 | { .dev_id = "dma", .clk = &dma_clk}, |
| 424 | { .dev_id = "jpeg", .clk = &jpeg_clk}, | 683 | { .dev_id = "jpeg", .clk = &jpeg_clk}, |
| 425 | { .dev_id = "gmac", .clk = &gmac_clk}, | 684 | { .dev_id = "gmac", .clk = &gmac_clk}, |
| @@ -427,8 +686,50 @@ static struct clk_lookup spear_clk_lookups[] = { | |||
| 427 | { .dev_id = "c3", .clk = &c3_clk}, | 686 | { .dev_id = "c3", .clk = &c3_clk}, |
| 428 | /* clock derived from apb clk */ | 687 | /* clock derived from apb clk */ |
| 429 | { .dev_id = "adc", .clk = &adc_clk}, | 688 | { .dev_id = "adc", .clk = &adc_clk}, |
| 430 | { .dev_id = "ssp", .clk = &ssp_clk}, | 689 | { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk}, |
| 431 | { .dev_id = "gpio", .clk = &gpio_clk}, | 690 | { .dev_id = "gpio", .clk = &gpio_clk}, |
| 691 | #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) | ||
| 692 | { .dev_id = "physmap-flash", .clk = &emi_clk}, | ||
| 693 | #endif | ||
| 694 | #if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \ | ||
| 695 | defined(CONFIG_MACH_SPEAR320) | ||
| 696 | { .con_id = "fsmc", .clk = &fsmc_clk}, | ||
| 697 | #endif | ||
| 698 | |||
| 699 | /* common clocks to spear310 and spear320 */ | ||
| 700 | #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) | ||
| 701 | { .dev_id = "uart1", .clk = &uart1_clk}, | ||
| 702 | { .dev_id = "uart2", .clk = &uart2_clk}, | ||
| 703 | #endif | ||
| 704 | |||
| 705 | /* common clock to spear300 and spear320 */ | ||
| 706 | #if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320) | ||
| 707 | { .dev_id = "clcd", .clk = &clcd_clk}, | ||
| 708 | { .dev_id = "sdhci", .clk = &sdhci_clk}, | ||
| 709 | #endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */ | ||
| 710 | |||
| 711 | /* spear300 machine specific clock structures */ | ||
| 712 | #ifdef CONFIG_MACH_SPEAR300 | ||
| 713 | { .dev_id = "gpio1", .clk = &gpio1_clk}, | ||
| 714 | { .dev_id = "keyboard", .clk = &kbd_clk}, | ||
| 715 | #endif | ||
| 716 | |||
| 717 | /* spear310 machine specific clock structures */ | ||
| 718 | #ifdef CONFIG_MACH_SPEAR310 | ||
| 719 | { .dev_id = "uart3", .clk = &uart3_clk}, | ||
| 720 | { .dev_id = "uart4", .clk = &uart4_clk}, | ||
| 721 | { .dev_id = "uart5", .clk = &uart5_clk}, | ||
| 722 | |||
| 723 | #endif | ||
| 724 | /* spear320 machine specific clock structures */ | ||
| 725 | #ifdef CONFIG_MACH_SPEAR320 | ||
| 726 | { .dev_id = "c_can_platform.0", .clk = &can0_clk}, | ||
| 727 | { .dev_id = "c_can_platform.1", .clk = &can1_clk}, | ||
| 728 | { .dev_id = "i2c_designware.1", .clk = &i2c1_clk}, | ||
| 729 | { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk}, | ||
| 730 | { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk}, | ||
| 731 | { .dev_id = "pwm", .clk = &pwm_clk}, | ||
| 732 | #endif | ||
| 432 | }; | 733 | }; |
| 433 | 734 | ||
| 434 | void __init clk_init(void) | 735 | void __init clk_init(void) |
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h index 6c919e1f9c43..0b93347c0f11 100644 --- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h +++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h | |||
| @@ -63,8 +63,8 @@ | |||
| 63 | #define GPT1_CLK_SHIFT 11 | 63 | #define GPT1_CLK_SHIFT 11 |
| 64 | #define GPT2_CLK_SHIFT 12 | 64 | #define GPT2_CLK_SHIFT 12 |
| 65 | #define GPT_CLK_MASK 0x1 | 65 | #define GPT_CLK_MASK 0x1 |
| 66 | #define AUX_CLK_PLL3_MASK 0 | 66 | #define AUX_CLK_PLL3_VAL 0 |
| 67 | #define AUX_CLK_PLL1_MASK 1 | 67 | #define AUX_CLK_PLL1_VAL 1 |
| 68 | 68 | ||
| 69 | #define PERIP1_CLK_ENB (MISC_BASE + 0x02C) | 69 | #define PERIP1_CLK_ENB (MISC_BASE + 0x02C) |
| 70 | /* PERIP1_CLK_ENB register masks */ | 70 | /* PERIP1_CLK_ENB register masks */ |
| @@ -113,6 +113,7 @@ | |||
| 113 | #define RAS3_CLK_SYNT (MISC_BASE + 0x074) | 113 | #define RAS3_CLK_SYNT (MISC_BASE + 0x074) |
| 114 | #define RAS4_CLK_SYNT (MISC_BASE + 0x078) | 114 | #define RAS4_CLK_SYNT (MISC_BASE + 0x078) |
| 115 | /* aux clk synthesiser register masks for irda to ras4 */ | 115 | /* aux clk synthesiser register masks for irda to ras4 */ |
| 116 | #define AUX_SYNT_ENB 31 | ||
| 116 | #define AUX_EQ_SEL_SHIFT 30 | 117 | #define AUX_EQ_SEL_SHIFT 30 |
| 117 | #define AUX_EQ_SEL_MASK 1 | 118 | #define AUX_EQ_SEL_MASK 1 |
| 118 | #define AUX_EQ1_SEL 0 | 119 | #define AUX_EQ1_SEL 0 |
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c index ef88922986e0..91719524766b 100644 --- a/arch/arm/mach-spear6xx/clock.c +++ b/arch/arm/mach-spear6xx/clock.c | |||
| @@ -60,12 +60,22 @@ static struct pll_clk_config pll1_config = { | |||
| 60 | .masks = &pll1_masks, | 60 | .masks = &pll1_masks, |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | /* pll rate configuration table, in ascending order of rates */ | ||
| 64 | struct pll_rate_tbl pll_rtbl[] = { | ||
| 65 | {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */ | ||
| 66 | {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */ | ||
| 67 | }; | ||
| 68 | |||
| 63 | /* PLL1 clock */ | 69 | /* PLL1 clock */ |
| 64 | static struct clk pll1_clk = { | 70 | static struct clk pll1_clk = { |
| 71 | .flags = ENABLED_ON_INIT, | ||
| 65 | .pclk = &osc_30m_clk, | 72 | .pclk = &osc_30m_clk, |
| 66 | .en_reg = PLL1_CTR, | 73 | .en_reg = PLL1_CTR, |
| 67 | .en_reg_bit = PLL_ENABLE, | 74 | .en_reg_bit = PLL_ENABLE, |
| 75 | .calc_rate = &pll_calc_rate, | ||
| 68 | .recalc = &pll_clk_recalc, | 76 | .recalc = &pll_clk_recalc, |
| 77 | .set_rate = &pll_clk_set_rate, | ||
| 78 | .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1}, | ||
| 69 | .private_data = &pll1_config, | 79 | .private_data = &pll1_config, |
| 70 | }; | 80 | }; |
| 71 | 81 | ||
| @@ -103,35 +113,25 @@ static struct bus_clk_config ahb_config = { | |||
| 103 | .masks = &ahb_masks, | 113 | .masks = &ahb_masks, |
| 104 | }; | 114 | }; |
| 105 | 115 | ||
| 116 | /* ahb rate configuration table, in ascending order of rates */ | ||
| 117 | struct bus_rate_tbl bus_rtbl[] = { | ||
| 118 | {.div = 3}, /* == parent divided by 4 */ | ||
| 119 | {.div = 2}, /* == parent divided by 3 */ | ||
| 120 | {.div = 1}, /* == parent divided by 2 */ | ||
| 121 | {.div = 0}, /* == parent divided by 1 */ | ||
| 122 | }; | ||
| 123 | |||
| 106 | /* ahb clock */ | 124 | /* ahb clock */ |
| 107 | static struct clk ahb_clk = { | 125 | static struct clk ahb_clk = { |
| 108 | .flags = ALWAYS_ENABLED, | 126 | .flags = ALWAYS_ENABLED, |
| 109 | .pclk = &pll1_clk, | 127 | .pclk = &pll1_clk, |
| 128 | .calc_rate = &bus_calc_rate, | ||
| 110 | .recalc = &bus_clk_recalc, | 129 | .recalc = &bus_clk_recalc, |
| 130 | .set_rate = &bus_clk_set_rate, | ||
| 131 | .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, | ||
| 111 | .private_data = &ahb_config, | 132 | .private_data = &ahb_config, |
| 112 | }; | 133 | }; |
| 113 | 134 | ||
| 114 | /* uart parents */ | ||
| 115 | static struct pclk_info uart_pclk_info[] = { | ||
| 116 | { | ||
| 117 | .pclk = &pll1_clk, | ||
| 118 | .pclk_mask = AUX_CLK_PLL1_MASK, | ||
| 119 | .scalable = 1, | ||
| 120 | }, { | ||
| 121 | .pclk = &pll3_48m_clk, | ||
| 122 | .pclk_mask = AUX_CLK_PLL3_MASK, | ||
| 123 | .scalable = 0, | ||
| 124 | }, | ||
| 125 | }; | ||
| 126 | |||
| 127 | /* uart parent select structure */ | ||
| 128 | static struct pclk_sel uart_pclk_sel = { | ||
| 129 | .pclk_info = uart_pclk_info, | ||
| 130 | .pclk_count = ARRAY_SIZE(uart_pclk_info), | ||
| 131 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 132 | .pclk_sel_mask = UART_CLK_MASK, | ||
| 133 | }; | ||
| 134 | |||
| 135 | /* auxiliary synthesizers masks */ | 135 | /* auxiliary synthesizers masks */ |
| 136 | static struct aux_clk_masks aux_masks = { | 136 | static struct aux_clk_masks aux_masks = { |
| 137 | .eq_sel_mask = AUX_EQ_SEL_MASK, | 137 | .eq_sel_mask = AUX_EQ_SEL_MASK, |
| @@ -145,19 +145,57 @@ static struct aux_clk_masks aux_masks = { | |||
| 145 | }; | 145 | }; |
| 146 | 146 | ||
| 147 | /* uart configurations */ | 147 | /* uart configurations */ |
| 148 | static struct aux_clk_config uart_config = { | 148 | static struct aux_clk_config uart_synth_config = { |
| 149 | .synth_reg = UART_CLK_SYNT, | 149 | .synth_reg = UART_CLK_SYNT, |
| 150 | .masks = &aux_masks, | 150 | .masks = &aux_masks, |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | /* aux rate configuration table, in ascending order of rates */ | ||
| 154 | struct aux_rate_tbl aux_rtbl[] = { | ||
| 155 | /* For PLL1 = 332 MHz */ | ||
| 156 | {.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */ | ||
| 157 | {.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */ | ||
| 158 | {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */ | ||
| 159 | }; | ||
| 160 | |||
| 161 | /* uart synth clock */ | ||
| 162 | static struct clk uart_synth_clk = { | ||
| 163 | .en_reg = UART_CLK_SYNT, | ||
| 164 | .en_reg_bit = AUX_SYNT_ENB, | ||
| 165 | .pclk = &pll1_clk, | ||
| 166 | .calc_rate = &aux_calc_rate, | ||
| 167 | .recalc = &aux_clk_recalc, | ||
| 168 | .set_rate = &aux_clk_set_rate, | ||
| 169 | .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2}, | ||
| 170 | .private_data = &uart_synth_config, | ||
| 171 | }; | ||
| 172 | |||
| 173 | /* uart parents */ | ||
| 174 | static struct pclk_info uart_pclk_info[] = { | ||
| 175 | { | ||
| 176 | .pclk = &uart_synth_clk, | ||
| 177 | .pclk_val = AUX_CLK_PLL1_VAL, | ||
| 178 | }, { | ||
| 179 | .pclk = &pll3_48m_clk, | ||
| 180 | .pclk_val = AUX_CLK_PLL3_VAL, | ||
| 181 | }, | ||
| 182 | }; | ||
| 183 | |||
| 184 | /* uart parent select structure */ | ||
| 185 | static struct pclk_sel uart_pclk_sel = { | ||
| 186 | .pclk_info = uart_pclk_info, | ||
| 187 | .pclk_count = ARRAY_SIZE(uart_pclk_info), | ||
| 188 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 189 | .pclk_sel_mask = UART_CLK_MASK, | ||
| 190 | }; | ||
| 191 | |||
| 153 | /* uart0 clock */ | 192 | /* uart0 clock */ |
| 154 | static struct clk uart0_clk = { | 193 | static struct clk uart0_clk = { |
| 155 | .en_reg = PERIP1_CLK_ENB, | 194 | .en_reg = PERIP1_CLK_ENB, |
| 156 | .en_reg_bit = UART0_CLK_ENB, | 195 | .en_reg_bit = UART0_CLK_ENB, |
| 157 | .pclk_sel = &uart_pclk_sel, | 196 | .pclk_sel = &uart_pclk_sel, |
| 158 | .pclk_sel_shift = UART_CLK_SHIFT, | 197 | .pclk_sel_shift = UART_CLK_SHIFT, |
| 159 | .recalc = &aux_clk_recalc, | 198 | .recalc = &follow_parent, |
| 160 | .private_data = &uart_config, | ||
| 161 | }; | 199 | }; |
| 162 | 200 | ||
| 163 | /* uart1 clock */ | 201 | /* uart1 clock */ |
| @@ -166,26 +204,35 @@ static struct clk uart1_clk = { | |||
| 166 | .en_reg_bit = UART1_CLK_ENB, | 204 | .en_reg_bit = UART1_CLK_ENB, |
| 167 | .pclk_sel = &uart_pclk_sel, | 205 | .pclk_sel = &uart_pclk_sel, |
| 168 | .pclk_sel_shift = UART_CLK_SHIFT, | 206 | .pclk_sel_shift = UART_CLK_SHIFT, |
| 169 | .recalc = &aux_clk_recalc, | 207 | .recalc = &follow_parent, |
| 170 | .private_data = &uart_config, | ||
| 171 | }; | 208 | }; |
| 172 | 209 | ||
| 173 | /* firda configurations */ | 210 | /* firda configurations */ |
| 174 | static struct aux_clk_config firda_config = { | 211 | static struct aux_clk_config firda_synth_config = { |
| 175 | .synth_reg = FIRDA_CLK_SYNT, | 212 | .synth_reg = FIRDA_CLK_SYNT, |
| 176 | .masks = &aux_masks, | 213 | .masks = &aux_masks, |
| 177 | }; | 214 | }; |
| 178 | 215 | ||
| 216 | /* firda synth clock */ | ||
| 217 | static struct clk firda_synth_clk = { | ||
| 218 | .en_reg = FIRDA_CLK_SYNT, | ||
| 219 | .en_reg_bit = AUX_SYNT_ENB, | ||
| 220 | .pclk = &pll1_clk, | ||
| 221 | .calc_rate = &aux_calc_rate, | ||
| 222 | .recalc = &aux_clk_recalc, | ||
| 223 | .set_rate = &aux_clk_set_rate, | ||
| 224 | .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2}, | ||
| 225 | .private_data = &firda_synth_config, | ||
| 226 | }; | ||
| 227 | |||
| 179 | /* firda parents */ | 228 | /* firda parents */ |
| 180 | static struct pclk_info firda_pclk_info[] = { | 229 | static struct pclk_info firda_pclk_info[] = { |
| 181 | { | 230 | { |
| 182 | .pclk = &pll1_clk, | 231 | .pclk = &firda_synth_clk, |
| 183 | .pclk_mask = AUX_CLK_PLL1_MASK, | 232 | .pclk_val = AUX_CLK_PLL1_VAL, |
| 184 | .scalable = 1, | ||
| 185 | }, { | 233 | }, { |
| 186 | .pclk = &pll3_48m_clk, | 234 | .pclk = &pll3_48m_clk, |
| 187 | .pclk_mask = AUX_CLK_PLL3_MASK, | 235 | .pclk_val = AUX_CLK_PLL3_VAL, |
| 188 | .scalable = 0, | ||
| 189 | }, | 236 | }, |
| 190 | }; | 237 | }; |
| 191 | 238 | ||
| @@ -203,26 +250,35 @@ static struct clk firda_clk = { | |||
| 203 | .en_reg_bit = FIRDA_CLK_ENB, | 250 | .en_reg_bit = FIRDA_CLK_ENB, |
| 204 | .pclk_sel = &firda_pclk_sel, | 251 | .pclk_sel = &firda_pclk_sel, |
| 205 | .pclk_sel_shift = FIRDA_CLK_SHIFT, | 252 | .pclk_sel_shift = FIRDA_CLK_SHIFT, |
| 206 | .recalc = &aux_clk_recalc, | 253 | .recalc = &follow_parent, |
| 207 | .private_data = &firda_config, | ||
| 208 | }; | 254 | }; |
| 209 | 255 | ||
| 210 | /* clcd configurations */ | 256 | /* clcd configurations */ |
| 211 | static struct aux_clk_config clcd_config = { | 257 | static struct aux_clk_config clcd_synth_config = { |
| 212 | .synth_reg = CLCD_CLK_SYNT, | 258 | .synth_reg = CLCD_CLK_SYNT, |
| 213 | .masks = &aux_masks, | 259 | .masks = &aux_masks, |
| 214 | }; | 260 | }; |
| 215 | 261 | ||
| 262 | /* firda synth clock */ | ||
| 263 | static struct clk clcd_synth_clk = { | ||
| 264 | .en_reg = CLCD_CLK_SYNT, | ||
| 265 | .en_reg_bit = AUX_SYNT_ENB, | ||
| 266 | .pclk = &pll1_clk, | ||
| 267 | .calc_rate = &aux_calc_rate, | ||
| 268 | .recalc = &aux_clk_recalc, | ||
| 269 | .set_rate = &aux_clk_set_rate, | ||
| 270 | .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2}, | ||
| 271 | .private_data = &clcd_synth_config, | ||
| 272 | }; | ||
| 273 | |||
| 216 | /* clcd parents */ | 274 | /* clcd parents */ |
| 217 | static struct pclk_info clcd_pclk_info[] = { | 275 | static struct pclk_info clcd_pclk_info[] = { |
| 218 | { | 276 | { |
| 219 | .pclk = &pll1_clk, | 277 | .pclk = &clcd_synth_clk, |
| 220 | .pclk_mask = AUX_CLK_PLL1_MASK, | 278 | .pclk_val = AUX_CLK_PLL1_VAL, |
| 221 | .scalable = 1, | ||
| 222 | }, { | 279 | }, { |
| 223 | .pclk = &pll3_48m_clk, | 280 | .pclk = &pll3_48m_clk, |
| 224 | .pclk_mask = AUX_CLK_PLL3_MASK, | 281 | .pclk_val = AUX_CLK_PLL3_VAL, |
| 225 | .scalable = 0, | ||
| 226 | }, | 282 | }, |
| 227 | }; | 283 | }; |
| 228 | 284 | ||
| @@ -240,29 +296,7 @@ static struct clk clcd_clk = { | |||
| 240 | .en_reg_bit = CLCD_CLK_ENB, | 296 | .en_reg_bit = CLCD_CLK_ENB, |
| 241 | .pclk_sel = &clcd_pclk_sel, | 297 | .pclk_sel = &clcd_pclk_sel, |
| 242 | .pclk_sel_shift = CLCD_CLK_SHIFT, | 298 | .pclk_sel_shift = CLCD_CLK_SHIFT, |
| 243 | .recalc = &aux_clk_recalc, | 299 | .recalc = &follow_parent, |
| 244 | .private_data = &clcd_config, | ||
| 245 | }; | ||
| 246 | |||
| 247 | /* gpt parents */ | ||
| 248 | static struct pclk_info gpt_pclk_info[] = { | ||
| 249 | { | ||
| 250 | .pclk = &pll1_clk, | ||
| 251 | .pclk_mask = AUX_CLK_PLL1_MASK, | ||
| 252 | .scalable = 1, | ||
| 253 | }, { | ||
| 254 | .pclk = &pll3_48m_clk, | ||
| 255 | .pclk_mask = AUX_CLK_PLL3_MASK, | ||
| 256 | .scalable = 0, | ||
| 257 | }, | ||
| 258 | }; | ||
| 259 | |||
| 260 | /* gpt parent select structure */ | ||
| 261 | static struct pclk_sel gpt_pclk_sel = { | ||
| 262 | .pclk_info = gpt_pclk_info, | ||
| 263 | .pclk_count = ARRAY_SIZE(gpt_pclk_info), | ||
| 264 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 265 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 266 | }; | 300 | }; |
| 267 | 301 | ||
| 268 | /* gpt synthesizer masks */ | 302 | /* gpt synthesizer masks */ |
| @@ -273,60 +307,162 @@ static struct gpt_clk_masks gpt_masks = { | |||
| 273 | .nscale_sel_shift = GPT_NSCALE_SHIFT, | 307 | .nscale_sel_shift = GPT_NSCALE_SHIFT, |
| 274 | }; | 308 | }; |
| 275 | 309 | ||
| 276 | /* gpt0_1 configurations */ | 310 | /* gpt rate configuration table, in ascending order of rates */ |
| 277 | static struct gpt_clk_config gpt0_1_config = { | 311 | struct gpt_rate_tbl gpt_rtbl[] = { |
| 312 | /* For pll1 = 332 MHz */ | ||
| 313 | {.mscale = 4, .nscale = 0}, /* 41.5 MHz */ | ||
| 314 | {.mscale = 2, .nscale = 0}, /* 55.3 MHz */ | ||
| 315 | {.mscale = 1, .nscale = 0}, /* 83 MHz */ | ||
| 316 | }; | ||
| 317 | |||
| 318 | /* gpt0 synth clk config*/ | ||
| 319 | static struct gpt_clk_config gpt0_synth_config = { | ||
| 278 | .synth_reg = PRSC1_CLK_CFG, | 320 | .synth_reg = PRSC1_CLK_CFG, |
| 279 | .masks = &gpt_masks, | 321 | .masks = &gpt_masks, |
| 280 | }; | 322 | }; |
| 281 | 323 | ||
| 324 | /* gpt synth clock */ | ||
| 325 | static struct clk gpt0_synth_clk = { | ||
| 326 | .flags = ALWAYS_ENABLED, | ||
| 327 | .pclk = &pll1_clk, | ||
| 328 | .calc_rate = &gpt_calc_rate, | ||
| 329 | .recalc = &gpt_clk_recalc, | ||
| 330 | .set_rate = &gpt_clk_set_rate, | ||
| 331 | .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, | ||
| 332 | .private_data = &gpt0_synth_config, | ||
| 333 | }; | ||
| 334 | |||
| 335 | /* gpt parents */ | ||
| 336 | static struct pclk_info gpt0_pclk_info[] = { | ||
| 337 | { | ||
| 338 | .pclk = &gpt0_synth_clk, | ||
| 339 | .pclk_val = AUX_CLK_PLL1_VAL, | ||
| 340 | }, { | ||
| 341 | .pclk = &pll3_48m_clk, | ||
| 342 | .pclk_val = AUX_CLK_PLL3_VAL, | ||
| 343 | }, | ||
| 344 | }; | ||
| 345 | |||
| 346 | /* gpt parent select structure */ | ||
| 347 | static struct pclk_sel gpt0_pclk_sel = { | ||
| 348 | .pclk_info = gpt0_pclk_info, | ||
| 349 | .pclk_count = ARRAY_SIZE(gpt0_pclk_info), | ||
| 350 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 351 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 352 | }; | ||
| 353 | |||
| 282 | /* gpt0 ARM1 subsystem timer clock */ | 354 | /* gpt0 ARM1 subsystem timer clock */ |
| 283 | static struct clk gpt0_clk = { | 355 | static struct clk gpt0_clk = { |
| 284 | .flags = ALWAYS_ENABLED, | 356 | .flags = ALWAYS_ENABLED, |
| 285 | .pclk_sel = &gpt_pclk_sel, | 357 | .pclk_sel = &gpt0_pclk_sel, |
| 286 | .pclk_sel_shift = GPT0_CLK_SHIFT, | 358 | .pclk_sel_shift = GPT0_CLK_SHIFT, |
| 287 | .recalc = &gpt_clk_recalc, | 359 | .recalc = &follow_parent, |
| 288 | .private_data = &gpt0_1_config, | 360 | }; |
| 361 | |||
| 362 | |||
| 363 | /* Note: gpt0 and gpt1 share same parent clocks */ | ||
| 364 | /* gpt parent select structure */ | ||
| 365 | static struct pclk_sel gpt1_pclk_sel = { | ||
| 366 | .pclk_info = gpt0_pclk_info, | ||
| 367 | .pclk_count = ARRAY_SIZE(gpt0_pclk_info), | ||
| 368 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 369 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 289 | }; | 370 | }; |
| 290 | 371 | ||
| 291 | /* gpt1 timer clock */ | 372 | /* gpt1 timer clock */ |
| 292 | static struct clk gpt1_clk = { | 373 | static struct clk gpt1_clk = { |
| 293 | .flags = ALWAYS_ENABLED, | 374 | .flags = ALWAYS_ENABLED, |
| 294 | .pclk_sel = &gpt_pclk_sel, | 375 | .pclk_sel = &gpt1_pclk_sel, |
| 295 | .pclk_sel_shift = GPT1_CLK_SHIFT, | 376 | .pclk_sel_shift = GPT1_CLK_SHIFT, |
| 296 | .recalc = &gpt_clk_recalc, | 377 | .recalc = &follow_parent, |
| 297 | .private_data = &gpt0_1_config, | ||
| 298 | }; | 378 | }; |
| 299 | 379 | ||
| 300 | /* gpt2 configurations */ | 380 | /* gpt2 synth clk config*/ |
| 301 | static struct gpt_clk_config gpt2_config = { | 381 | static struct gpt_clk_config gpt2_synth_config = { |
| 302 | .synth_reg = PRSC2_CLK_CFG, | 382 | .synth_reg = PRSC2_CLK_CFG, |
| 303 | .masks = &gpt_masks, | 383 | .masks = &gpt_masks, |
| 304 | }; | 384 | }; |
| 305 | 385 | ||
| 386 | /* gpt synth clock */ | ||
| 387 | static struct clk gpt2_synth_clk = { | ||
| 388 | .flags = ALWAYS_ENABLED, | ||
| 389 | .pclk = &pll1_clk, | ||
| 390 | .calc_rate = &gpt_calc_rate, | ||
| 391 | .recalc = &gpt_clk_recalc, | ||
| 392 | .set_rate = &gpt_clk_set_rate, | ||
| 393 | .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, | ||
| 394 | .private_data = &gpt2_synth_config, | ||
| 395 | }; | ||
| 396 | |||
| 397 | /* gpt parents */ | ||
| 398 | static struct pclk_info gpt2_pclk_info[] = { | ||
| 399 | { | ||
| 400 | .pclk = &gpt2_synth_clk, | ||
| 401 | .pclk_val = AUX_CLK_PLL1_VAL, | ||
| 402 | }, { | ||
| 403 | .pclk = &pll3_48m_clk, | ||
| 404 | .pclk_val = AUX_CLK_PLL3_VAL, | ||
| 405 | }, | ||
| 406 | }; | ||
| 407 | |||
| 408 | /* gpt parent select structure */ | ||
| 409 | static struct pclk_sel gpt2_pclk_sel = { | ||
| 410 | .pclk_info = gpt2_pclk_info, | ||
| 411 | .pclk_count = ARRAY_SIZE(gpt2_pclk_info), | ||
| 412 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 413 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 414 | }; | ||
| 415 | |||
| 306 | /* gpt2 timer clock */ | 416 | /* gpt2 timer clock */ |
| 307 | static struct clk gpt2_clk = { | 417 | static struct clk gpt2_clk = { |
| 308 | .en_reg = PERIP1_CLK_ENB, | 418 | .flags = ALWAYS_ENABLED, |
| 309 | .en_reg_bit = GPT2_CLK_ENB, | 419 | .pclk_sel = &gpt2_pclk_sel, |
| 310 | .pclk_sel = &gpt_pclk_sel, | ||
| 311 | .pclk_sel_shift = GPT2_CLK_SHIFT, | 420 | .pclk_sel_shift = GPT2_CLK_SHIFT, |
| 312 | .recalc = &gpt_clk_recalc, | 421 | .recalc = &follow_parent, |
| 313 | .private_data = &gpt2_config, | ||
| 314 | }; | 422 | }; |
| 315 | 423 | ||
| 316 | /* gpt3 configurations */ | 424 | /* gpt3 synth clk config*/ |
| 317 | static struct gpt_clk_config gpt3_config = { | 425 | static struct gpt_clk_config gpt3_synth_config = { |
| 318 | .synth_reg = PRSC3_CLK_CFG, | 426 | .synth_reg = PRSC3_CLK_CFG, |
| 319 | .masks = &gpt_masks, | 427 | .masks = &gpt_masks, |
| 320 | }; | 428 | }; |
| 321 | 429 | ||
| 430 | /* gpt synth clock */ | ||
| 431 | static struct clk gpt3_synth_clk = { | ||
| 432 | .flags = ALWAYS_ENABLED, | ||
| 433 | .pclk = &pll1_clk, | ||
| 434 | .calc_rate = &gpt_calc_rate, | ||
| 435 | .recalc = &gpt_clk_recalc, | ||
| 436 | .set_rate = &gpt_clk_set_rate, | ||
| 437 | .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, | ||
| 438 | .private_data = &gpt3_synth_config, | ||
| 439 | }; | ||
| 440 | |||
| 441 | /* gpt parents */ | ||
| 442 | static struct pclk_info gpt3_pclk_info[] = { | ||
| 443 | { | ||
| 444 | .pclk = &gpt3_synth_clk, | ||
| 445 | .pclk_val = AUX_CLK_PLL1_VAL, | ||
| 446 | }, { | ||
| 447 | .pclk = &pll3_48m_clk, | ||
| 448 | .pclk_val = AUX_CLK_PLL3_VAL, | ||
| 449 | }, | ||
| 450 | }; | ||
| 451 | |||
| 452 | /* gpt parent select structure */ | ||
| 453 | static struct pclk_sel gpt3_pclk_sel = { | ||
| 454 | .pclk_info = gpt3_pclk_info, | ||
| 455 | .pclk_count = ARRAY_SIZE(gpt3_pclk_info), | ||
| 456 | .pclk_sel_reg = PERIP_CLK_CFG, | ||
| 457 | .pclk_sel_mask = GPT_CLK_MASK, | ||
| 458 | }; | ||
| 459 | |||
| 322 | /* gpt3 timer clock */ | 460 | /* gpt3 timer clock */ |
| 323 | static struct clk gpt3_clk = { | 461 | static struct clk gpt3_clk = { |
| 324 | .en_reg = PERIP1_CLK_ENB, | 462 | .flags = ALWAYS_ENABLED, |
| 325 | .en_reg_bit = GPT3_CLK_ENB, | 463 | .pclk_sel = &gpt3_pclk_sel, |
| 326 | .pclk_sel = &gpt_pclk_sel, | ||
| 327 | .pclk_sel_shift = GPT3_CLK_SHIFT, | 464 | .pclk_sel_shift = GPT3_CLK_SHIFT, |
| 328 | .recalc = &gpt_clk_recalc, | 465 | .recalc = &follow_parent, |
| 329 | .private_data = &gpt3_config, | ||
| 330 | }; | 466 | }; |
| 331 | 467 | ||
| 332 | /* clock derived from pll3 clk */ | 468 | /* clock derived from pll3 clk */ |
| @@ -371,7 +507,10 @@ static struct bus_clk_config apb_config = { | |||
| 371 | static struct clk apb_clk = { | 507 | static struct clk apb_clk = { |
| 372 | .flags = ALWAYS_ENABLED, | 508 | .flags = ALWAYS_ENABLED, |
| 373 | .pclk = &ahb_clk, | 509 | .pclk = &ahb_clk, |
| 510 | .calc_rate = &bus_calc_rate, | ||
| 374 | .recalc = &bus_clk_recalc, | 511 | .recalc = &bus_clk_recalc, |
| 512 | .set_rate = &bus_clk_set_rate, | ||
| 513 | .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, | ||
| 375 | .private_data = &apb_config, | 514 | .private_data = &apb_config, |
| 376 | }; | 515 | }; |
| 377 | 516 | ||
| @@ -488,7 +627,7 @@ static struct clk_lookup spear_clk_lookups[] = { | |||
| 488 | { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, | 627 | { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, |
| 489 | { .con_id = "osc_30m_clk", .clk = &osc_30m_clk}, | 628 | { .con_id = "osc_30m_clk", .clk = &osc_30m_clk}, |
| 490 | /* clock derived from 32 KHz os clk */ | 629 | /* clock derived from 32 KHz os clk */ |
| 491 | { .dev_id = "rtc", .clk = &rtc_clk}, | 630 | { .dev_id = "rtc-spear", .clk = &rtc_clk}, |
| 492 | /* clock derived from 30 MHz os clk */ | 631 | /* clock derived from 30 MHz os clk */ |
| 493 | { .con_id = "pll1_clk", .clk = &pll1_clk}, | 632 | { .con_id = "pll1_clk", .clk = &pll1_clk}, |
| 494 | { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, | 633 | { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, |
| @@ -496,6 +635,12 @@ static struct clk_lookup spear_clk_lookups[] = { | |||
| 496 | /* clock derived from pll1 clk */ | 635 | /* clock derived from pll1 clk */ |
| 497 | { .con_id = "cpu_clk", .clk = &cpu_clk}, | 636 | { .con_id = "cpu_clk", .clk = &cpu_clk}, |
| 498 | { .con_id = "ahb_clk", .clk = &ahb_clk}, | 637 | { .con_id = "ahb_clk", .clk = &ahb_clk}, |
| 638 | { .con_id = "uart_synth_clk", .clk = &uart_synth_clk}, | ||
| 639 | { .con_id = "firda_synth_clk", .clk = &firda_synth_clk}, | ||
| 640 | { .con_id = "clcd_synth_clk", .clk = &clcd_synth_clk}, | ||
| 641 | { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk}, | ||
| 642 | { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk}, | ||
| 643 | { .con_id = "gpt3_synth_clk", .clk = &gpt3_synth_clk}, | ||
| 499 | { .dev_id = "uart0", .clk = &uart0_clk}, | 644 | { .dev_id = "uart0", .clk = &uart0_clk}, |
| 500 | { .dev_id = "uart1", .clk = &uart1_clk}, | 645 | { .dev_id = "uart1", .clk = &uart1_clk}, |
| 501 | { .dev_id = "firda", .clk = &firda_clk}, | 646 | { .dev_id = "firda", .clk = &firda_clk}, |
| @@ -505,22 +650,22 @@ static struct clk_lookup spear_clk_lookups[] = { | |||
| 505 | { .dev_id = "gpt2", .clk = &gpt2_clk}, | 650 | { .dev_id = "gpt2", .clk = &gpt2_clk}, |
| 506 | { .dev_id = "gpt3", .clk = &gpt3_clk}, | 651 | { .dev_id = "gpt3", .clk = &gpt3_clk}, |
| 507 | /* clock derived from pll3 clk */ | 652 | /* clock derived from pll3 clk */ |
| 508 | { .dev_id = "usbh0", .clk = &usbh0_clk}, | 653 | { .con_id = "usbh.0_clk", .clk = &usbh0_clk}, |
| 509 | { .dev_id = "usbh1", .clk = &usbh1_clk}, | 654 | { .con_id = "usbh.1_clk", .clk = &usbh1_clk}, |
| 510 | { .dev_id = "usbd", .clk = &usbd_clk}, | 655 | { .dev_id = "usbd", .clk = &usbd_clk}, |
| 511 | /* clock derived from ahb clk */ | 656 | /* clock derived from ahb clk */ |
| 512 | { .con_id = "apb_clk", .clk = &apb_clk}, | 657 | { .con_id = "apb_clk", .clk = &apb_clk}, |
| 513 | { .dev_id = "i2c", .clk = &i2c_clk}, | 658 | { .dev_id = "i2c_designware.0", .clk = &i2c_clk}, |
| 514 | { .dev_id = "dma", .clk = &dma_clk}, | 659 | { .dev_id = "dma", .clk = &dma_clk}, |
| 515 | { .dev_id = "jpeg", .clk = &jpeg_clk}, | 660 | { .dev_id = "jpeg", .clk = &jpeg_clk}, |
| 516 | { .dev_id = "gmac", .clk = &gmac_clk}, | 661 | { .dev_id = "gmac", .clk = &gmac_clk}, |
| 517 | { .dev_id = "smi", .clk = &smi_clk}, | 662 | { .dev_id = "smi", .clk = &smi_clk}, |
| 518 | { .dev_id = "fsmc", .clk = &fsmc_clk}, | 663 | { .con_id = "fsmc", .clk = &fsmc_clk}, |
| 519 | /* clock derived from apb clk */ | 664 | /* clock derived from apb clk */ |
| 520 | { .dev_id = "adc", .clk = &adc_clk}, | 665 | { .dev_id = "adc", .clk = &adc_clk}, |
| 521 | { .dev_id = "ssp0", .clk = &ssp0_clk}, | 666 | { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk}, |
| 522 | { .dev_id = "ssp1", .clk = &ssp1_clk}, | 667 | { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk}, |
| 523 | { .dev_id = "ssp2", .clk = &ssp2_clk}, | 668 | { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk}, |
| 524 | { .dev_id = "gpio0", .clk = &gpio0_clk}, | 669 | { .dev_id = "gpio0", .clk = &gpio0_clk}, |
| 525 | { .dev_id = "gpio1", .clk = &gpio1_clk}, | 670 | { .dev_id = "gpio1", .clk = &gpio1_clk}, |
| 526 | { .dev_id = "gpio2", .clk = &gpio2_clk}, | 671 | { .dev_id = "gpio2", .clk = &gpio2_clk}, |
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h index d15317788d0d..45571c13227a 100644 --- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h +++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h | |||
| @@ -66,8 +66,8 @@ | |||
| 66 | #define GPT2_CLK_SHIFT 11 | 66 | #define GPT2_CLK_SHIFT 11 |
| 67 | #define GPT3_CLK_SHIFT 12 | 67 | #define GPT3_CLK_SHIFT 12 |
| 68 | #define GPT_CLK_MASK 0x1 | 68 | #define GPT_CLK_MASK 0x1 |
| 69 | #define AUX_CLK_PLL3_MASK 0 | 69 | #define AUX_CLK_PLL3_VAL 0 |
| 70 | #define AUX_CLK_PLL1_MASK 1 | 70 | #define AUX_CLK_PLL1_VAL 1 |
| 71 | 71 | ||
| 72 | #define PERIP1_CLK_ENB (MISC_BASE + 0x02C) | 72 | #define PERIP1_CLK_ENB (MISC_BASE + 0x02C) |
| 73 | /* PERIP1_CLK_ENB register masks */ | 73 | /* PERIP1_CLK_ENB register masks */ |
| @@ -123,6 +123,7 @@ | |||
| 123 | #define RAS3_CLK_SYNT (MISC_BASE + 0x074) | 123 | #define RAS3_CLK_SYNT (MISC_BASE + 0x074) |
| 124 | #define RAS4_CLK_SYNT (MISC_BASE + 0x078) | 124 | #define RAS4_CLK_SYNT (MISC_BASE + 0x078) |
| 125 | /* aux clk synthesiser register masks for irda to ras4 */ | 125 | /* aux clk synthesiser register masks for irda to ras4 */ |
| 126 | #define AUX_SYNT_ENB 31 | ||
| 126 | #define AUX_EQ_SEL_SHIFT 30 | 127 | #define AUX_EQ_SEL_SHIFT 30 |
| 127 | #define AUX_EQ_SEL_MASK 1 | 128 | #define AUX_EQ_SEL_MASK 1 |
| 128 | #define AUX_EQ1_SEL 0 | 129 | #define AUX_EQ1_SEL 0 |
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c index f1cf832e4e3b..7e7ab606dc49 100644 --- a/arch/arm/plat-spear/clock.c +++ b/arch/arm/plat-spear/clock.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/bug.h> | 14 | #include <linux/bug.h> |
| 15 | #include <linux/clk.h> | ||
| 15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 16 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 17 | #include <linux/list.h> | 18 | #include <linux/list.h> |
| @@ -22,7 +23,7 @@ | |||
| 22 | static DEFINE_SPINLOCK(clocks_lock); | 23 | static DEFINE_SPINLOCK(clocks_lock); |
| 23 | static LIST_HEAD(root_clks); | 24 | static LIST_HEAD(root_clks); |
| 24 | 25 | ||
| 25 | static void propagate_rate(struct list_head *); | 26 | static void propagate_rate(struct clk *, int on_init); |
| 26 | 27 | ||
| 27 | static int generic_clk_enable(struct clk *clk) | 28 | static int generic_clk_enable(struct clk *clk) |
| 28 | { | 29 | { |
| @@ -64,6 +65,100 @@ static struct clkops generic_clkops = { | |||
| 64 | .disable = generic_clk_disable, | 65 | .disable = generic_clk_disable, |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 68 | /* returns current programmed clocks clock info structure */ | ||
| 69 | static struct pclk_info *pclk_info_get(struct clk *clk) | ||
| 70 | { | ||
| 71 | unsigned int val, i; | ||
| 72 | struct pclk_info *info = NULL; | ||
| 73 | |||
| 74 | val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) | ||
| 75 | & clk->pclk_sel->pclk_sel_mask; | ||
| 76 | |||
| 77 | for (i = 0; i < clk->pclk_sel->pclk_count; i++) { | ||
| 78 | if (clk->pclk_sel->pclk_info[i].pclk_val == val) | ||
| 79 | info = &clk->pclk_sel->pclk_info[i]; | ||
| 80 | } | ||
| 81 | |||
| 82 | return info; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Set Update pclk, and pclk_info of clk and add clock sibling node to current | ||
| 87 | * parents children list | ||
| 88 | */ | ||
| 89 | static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info) | ||
| 90 | { | ||
| 91 | unsigned long flags; | ||
| 92 | |||
| 93 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 94 | list_del(&clk->sibling); | ||
| 95 | list_add(&clk->sibling, &pclk_info->pclk->children); | ||
| 96 | |||
| 97 | clk->pclk = pclk_info->pclk; | ||
| 98 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
| 99 | } | ||
| 100 | |||
| 101 | static void do_clk_disable(struct clk *clk) | ||
| 102 | { | ||
| 103 | if (!clk) | ||
| 104 | return; | ||
| 105 | |||
| 106 | if (!clk->usage_count) { | ||
| 107 | WARN_ON(1); | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | |||
| 111 | clk->usage_count--; | ||
| 112 | |||
| 113 | if (clk->usage_count == 0) { | ||
| 114 | /* | ||
| 115 | * Surely, there are no active childrens or direct users | ||
| 116 | * of this clock | ||
| 117 | */ | ||
| 118 | if (clk->pclk) | ||
| 119 | do_clk_disable(clk->pclk); | ||
| 120 | |||
| 121 | if (clk->ops && clk->ops->disable) | ||
| 122 | clk->ops->disable(clk); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | static int do_clk_enable(struct clk *clk) | ||
| 127 | { | ||
| 128 | int ret = 0; | ||
| 129 | |||
| 130 | if (!clk) | ||
| 131 | return -EFAULT; | ||
| 132 | |||
| 133 | if (clk->usage_count == 0) { | ||
| 134 | if (clk->pclk) { | ||
| 135 | ret = do_clk_enable(clk->pclk); | ||
| 136 | if (ret) | ||
| 137 | goto err; | ||
| 138 | } | ||
| 139 | if (clk->ops && clk->ops->enable) { | ||
| 140 | ret = clk->ops->enable(clk); | ||
| 141 | if (ret) { | ||
| 142 | if (clk->pclk) | ||
| 143 | do_clk_disable(clk->pclk); | ||
| 144 | goto err; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | /* | ||
| 148 | * Since the clock is going to be used for the first | ||
| 149 | * time please reclac | ||
| 150 | */ | ||
| 151 | if (clk->recalc) { | ||
| 152 | ret = clk->recalc(clk); | ||
| 153 | if (ret) | ||
| 154 | goto err; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | clk->usage_count++; | ||
| 158 | err: | ||
| 159 | return ret; | ||
| 160 | } | ||
| 161 | |||
| 67 | /* | 162 | /* |
| 68 | * clk_enable - inform the system when the clock source should be running. | 163 | * clk_enable - inform the system when the clock source should be running. |
| 69 | * @clk: clock source | 164 | * @clk: clock source |
| @@ -77,17 +172,9 @@ int clk_enable(struct clk *clk) | |||
| 77 | unsigned long flags; | 172 | unsigned long flags; |
| 78 | int ret = 0; | 173 | int ret = 0; |
| 79 | 174 | ||
| 80 | if (!clk || IS_ERR(clk)) | ||
| 81 | return -EFAULT; | ||
| 82 | |||
| 83 | spin_lock_irqsave(&clocks_lock, flags); | 175 | spin_lock_irqsave(&clocks_lock, flags); |
| 84 | if (clk->usage_count == 0) { | 176 | ret = do_clk_enable(clk); |
| 85 | if (clk->ops && clk->ops->enable) | ||
| 86 | ret = clk->ops->enable(clk); | ||
| 87 | } | ||
| 88 | clk->usage_count++; | ||
| 89 | spin_unlock_irqrestore(&clocks_lock, flags); | 177 | spin_unlock_irqrestore(&clocks_lock, flags); |
| 90 | |||
| 91 | return ret; | 178 | return ret; |
| 92 | } | 179 | } |
| 93 | EXPORT_SYMBOL(clk_enable); | 180 | EXPORT_SYMBOL(clk_enable); |
| @@ -108,17 +195,8 @@ void clk_disable(struct clk *clk) | |||
| 108 | { | 195 | { |
| 109 | unsigned long flags; | 196 | unsigned long flags; |
| 110 | 197 | ||
| 111 | if (!clk || IS_ERR(clk)) | ||
| 112 | return; | ||
| 113 | |||
| 114 | WARN_ON(clk->usage_count == 0); | ||
| 115 | |||
| 116 | spin_lock_irqsave(&clocks_lock, flags); | 198 | spin_lock_irqsave(&clocks_lock, flags); |
| 117 | clk->usage_count--; | 199 | do_clk_disable(clk); |
| 118 | if (clk->usage_count == 0) { | ||
| 119 | if (clk->ops && clk->ops->disable) | ||
| 120 | clk->ops->disable(clk); | ||
| 121 | } | ||
| 122 | spin_unlock_irqrestore(&clocks_lock, flags); | 200 | spin_unlock_irqrestore(&clocks_lock, flags); |
| 123 | } | 201 | } |
| 124 | EXPORT_SYMBOL(clk_disable); | 202 | EXPORT_SYMBOL(clk_disable); |
| @@ -152,15 +230,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
| 152 | int i, found = 0, val = 0; | 230 | int i, found = 0, val = 0; |
| 153 | unsigned long flags; | 231 | unsigned long flags; |
| 154 | 232 | ||
| 155 | if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent)) | 233 | if (!clk || !parent) |
| 156 | return -EFAULT; | 234 | return -EFAULT; |
| 157 | if (clk->usage_count) | ||
| 158 | return -EBUSY; | ||
| 159 | if (!clk->pclk_sel) | ||
| 160 | return -EPERM; | ||
| 161 | if (clk->pclk == parent) | 235 | if (clk->pclk == parent) |
| 162 | return 0; | 236 | return 0; |
| 237 | if (!clk->pclk_sel) | ||
| 238 | return -EPERM; | ||
| 163 | 239 | ||
| 240 | /* check if requested parent is in clk parent list */ | ||
| 164 | for (i = 0; i < clk->pclk_sel->pclk_count; i++) { | 241 | for (i = 0; i < clk->pclk_sel->pclk_count; i++) { |
| 165 | if (clk->pclk_sel->pclk_info[i].pclk == parent) { | 242 | if (clk->pclk_sel->pclk_info[i].pclk == parent) { |
| 166 | found = 1; | 243 | found = 1; |
| @@ -175,13 +252,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
| 175 | /* reflect parent change in hardware */ | 252 | /* reflect parent change in hardware */ |
| 176 | val = readl(clk->pclk_sel->pclk_sel_reg); | 253 | val = readl(clk->pclk_sel->pclk_sel_reg); |
| 177 | val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift); | 254 | val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift); |
| 178 | val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift; | 255 | val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift; |
| 179 | writel(val, clk->pclk_sel->pclk_sel_reg); | 256 | writel(val, clk->pclk_sel->pclk_sel_reg); |
| 180 | spin_unlock_irqrestore(&clocks_lock, flags); | 257 | spin_unlock_irqrestore(&clocks_lock, flags); |
| 181 | 258 | ||
| 182 | /* reflect parent change in software */ | 259 | /* reflect parent change in software */ |
| 183 | clk->recalc(clk); | 260 | clk_reparent(clk, &clk->pclk_sel->pclk_info[i]); |
| 184 | propagate_rate(&clk->children); | 261 | |
| 262 | propagate_rate(clk, 0); | ||
| 185 | return 0; | 263 | return 0; |
| 186 | } | 264 | } |
| 187 | EXPORT_SYMBOL(clk_set_parent); | 265 | EXPORT_SYMBOL(clk_set_parent); |
| @@ -195,19 +273,37 @@ EXPORT_SYMBOL(clk_set_parent); | |||
| 195 | */ | 273 | */ |
| 196 | int clk_set_rate(struct clk *clk, unsigned long rate) | 274 | int clk_set_rate(struct clk *clk, unsigned long rate) |
| 197 | { | 275 | { |
| 198 | /* TODO */ | 276 | unsigned long flags; |
| 199 | return -EINVAL; | 277 | int ret = -EINVAL; |
| 278 | |||
| 279 | if (!clk || !rate) | ||
| 280 | return -EFAULT; | ||
| 281 | |||
| 282 | if (clk->set_rate) { | ||
| 283 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 284 | ret = clk->set_rate(clk, rate); | ||
| 285 | if (!ret) | ||
| 286 | /* if successful -> propagate */ | ||
| 287 | propagate_rate(clk, 0); | ||
| 288 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
| 289 | } else if (clk->pclk) { | ||
| 290 | u32 mult = clk->div_factor ? clk->div_factor : 1; | ||
| 291 | ret = clk_set_rate(clk->pclk, mult * rate); | ||
| 292 | } | ||
| 293 | |||
| 294 | return ret; | ||
| 200 | } | 295 | } |
| 201 | EXPORT_SYMBOL(clk_set_rate); | 296 | EXPORT_SYMBOL(clk_set_rate); |
| 202 | 297 | ||
| 203 | /* registers clock in platform clock framework */ | 298 | /* registers clock in platform clock framework */ |
| 204 | void clk_register(struct clk_lookup *cl) | 299 | void clk_register(struct clk_lookup *cl) |
| 205 | { | 300 | { |
| 206 | struct clk *clk = cl->clk; | 301 | struct clk *clk; |
| 207 | unsigned long flags; | 302 | unsigned long flags; |
| 208 | 303 | ||
| 209 | if (!clk || IS_ERR(clk)) | 304 | if (!cl || !cl->clk) |
| 210 | return; | 305 | return; |
| 306 | clk = cl->clk; | ||
| 211 | 307 | ||
| 212 | spin_lock_irqsave(&clocks_lock, flags); | 308 | spin_lock_irqsave(&clocks_lock, flags); |
| 213 | 309 | ||
| @@ -220,15 +316,24 @@ void clk_register(struct clk_lookup *cl) | |||
| 220 | /* root clock don't have any parents */ | 316 | /* root clock don't have any parents */ |
| 221 | if (!clk->pclk && !clk->pclk_sel) { | 317 | if (!clk->pclk && !clk->pclk_sel) { |
| 222 | list_add(&clk->sibling, &root_clks); | 318 | list_add(&clk->sibling, &root_clks); |
| 223 | /* add clocks with only one parent to parent's children list */ | ||
| 224 | } else if (clk->pclk && !clk->pclk_sel) { | 319 | } else if (clk->pclk && !clk->pclk_sel) { |
| 320 | /* add clocks with only one parent to parent's children list */ | ||
| 225 | list_add(&clk->sibling, &clk->pclk->children); | 321 | list_add(&clk->sibling, &clk->pclk->children); |
| 226 | } else { | 322 | } else { |
| 227 | /* add clocks with > 1 parent to 1st parent's children list */ | 323 | /* clocks with more than one parent */ |
| 228 | clk->pclk = clk->pclk_sel->pclk_info[0].pclk; | 324 | struct pclk_info *pclk_info; |
| 229 | list_add(&clk->sibling, | 325 | |
| 230 | &clk->pclk_sel->pclk_info[0].pclk->children); | 326 | pclk_info = pclk_info_get(clk); |
| 327 | if (!pclk_info) { | ||
| 328 | pr_err("CLKDEV: invalid pclk info of clk with" | ||
| 329 | " %s dev_id and %s con_id\n", | ||
| 330 | cl->dev_id, cl->con_id); | ||
| 331 | } else { | ||
| 332 | clk->pclk = pclk_info->pclk; | ||
| 333 | list_add(&clk->sibling, &pclk_info->pclk->children); | ||
| 334 | } | ||
| 231 | } | 335 | } |
| 336 | |||
| 232 | spin_unlock_irqrestore(&clocks_lock, flags); | 337 | spin_unlock_irqrestore(&clocks_lock, flags); |
| 233 | 338 | ||
| 234 | /* add clock to arm clockdev framework */ | 339 | /* add clock to arm clockdev framework */ |
| @@ -236,56 +341,142 @@ void clk_register(struct clk_lookup *cl) | |||
| 236 | } | 341 | } |
| 237 | 342 | ||
| 238 | /** | 343 | /** |
| 239 | * propagate_rate - recalculate and propagate all clocks in list head | 344 | * propagate_rate - recalculate and propagate all clocks to children |
| 345 | * @pclk: parent clock required to be propogated | ||
| 346 | * @on_init: flag for enabling clocks which are ENABLED_ON_INIT. | ||
| 240 | * | 347 | * |
| 241 | * Recalculates all root clocks in list head, which if the clock's .recalc is | 348 | * Recalculates all children clocks |
| 242 | * set correctly, should also propagate their rates. | ||
| 243 | */ | 349 | */ |
| 244 | static void propagate_rate(struct list_head *lhead) | 350 | void propagate_rate(struct clk *pclk, int on_init) |
| 245 | { | 351 | { |
| 246 | struct clk *clkp, *_temp; | 352 | struct clk *clk, *_temp; |
| 353 | int ret = 0; | ||
| 354 | |||
| 355 | list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) { | ||
| 356 | if (clk->recalc) { | ||
| 357 | ret = clk->recalc(clk); | ||
| 358 | /* | ||
| 359 | * recalc will return error if clk out is not programmed | ||
| 360 | * In this case configure default rate. | ||
| 361 | */ | ||
| 362 | if (ret && clk->set_rate) | ||
| 363 | clk->set_rate(clk, 0); | ||
| 364 | } | ||
| 365 | propagate_rate(clk, on_init); | ||
| 366 | |||
| 367 | if (!on_init) | ||
| 368 | continue; | ||
| 247 | 369 | ||
| 248 | list_for_each_entry_safe(clkp, _temp, lhead, sibling) { | 370 | /* Enable clks enabled on init, in software view */ |
| 249 | if (clkp->recalc) | 371 | if (clk->flags & ENABLED_ON_INIT) |
| 250 | clkp->recalc(clkp); | 372 | do_clk_enable(clk); |
| 251 | propagate_rate(&clkp->children); | ||
| 252 | } | 373 | } |
| 253 | } | 374 | } |
| 254 | 375 | ||
| 255 | /* returns current programmed clocks clock info structure */ | 376 | /** |
| 256 | static struct pclk_info *pclk_info_get(struct clk *clk) | 377 | * round_rate_index - return closest programmable rate index in rate_config tbl |
| 378 | * @clk: ptr to clock structure | ||
| 379 | * @drate: desired rate | ||
| 380 | * @rate: final rate will be returned in this variable only. | ||
| 381 | * | ||
| 382 | * Finds index in rate_config for highest clk rate which is less than | ||
| 383 | * requested rate. If there is no clk rate lesser than requested rate then | ||
| 384 | * -EINVAL is returned. This routine assumes that rate_config is written | ||
| 385 | * in incrementing order of clk rates. | ||
| 386 | * If drate passed is zero then default rate is programmed. | ||
| 387 | */ | ||
| 388 | static int | ||
| 389 | round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate) | ||
| 257 | { | 390 | { |
| 258 | unsigned int mask, i; | 391 | unsigned long tmp = 0, prev_rate = 0; |
| 259 | unsigned long flags; | 392 | int index; |
| 260 | struct pclk_info *info = NULL; | ||
| 261 | 393 | ||
| 262 | spin_lock_irqsave(&clocks_lock, flags); | 394 | if (!clk->calc_rate) |
| 263 | mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) | 395 | return -EFAULT; |
| 264 | & clk->pclk_sel->pclk_sel_mask; | ||
| 265 | 396 | ||
| 266 | for (i = 0; i < clk->pclk_sel->pclk_count; i++) { | 397 | if (!drate) |
| 267 | if (clk->pclk_sel->pclk_info[i].pclk_mask == mask) | 398 | return -EINVAL; |
| 268 | info = &clk->pclk_sel->pclk_info[i]; | 399 | |
| 400 | /* | ||
| 401 | * This loops ends on two conditions: | ||
| 402 | * - as soon as clk is found with rate greater than requested rate. | ||
| 403 | * - if all clks in rate_config are smaller than requested rate. | ||
| 404 | */ | ||
| 405 | for (index = 0; index < clk->rate_config.count; index++) { | ||
| 406 | prev_rate = tmp; | ||
| 407 | tmp = clk->calc_rate(clk, index); | ||
| 408 | if (drate < tmp) { | ||
| 409 | index--; | ||
| 410 | break; | ||
| 411 | } | ||
| 269 | } | 412 | } |
| 270 | spin_unlock_irqrestore(&clocks_lock, flags); | 413 | /* return if can't find suitable clock */ |
| 414 | if (index < 0) { | ||
| 415 | index = -EINVAL; | ||
| 416 | *rate = 0; | ||
| 417 | } else if (index == clk->rate_config.count) { | ||
| 418 | /* program with highest clk rate possible */ | ||
| 419 | index = clk->rate_config.count - 1; | ||
| 420 | *rate = tmp; | ||
| 421 | } else | ||
| 422 | *rate = prev_rate; | ||
| 271 | 423 | ||
| 272 | return info; | 424 | return index; |
| 273 | } | 425 | } |
| 274 | 426 | ||
| 275 | /* | 427 | /** |
| 276 | * Set pclk as cclk's parent and add clock sibling node to current parents | 428 | * clk_round_rate - adjust a rate to the exact rate a clock can provide |
| 277 | * children list | 429 | * @clk: clock source |
| 430 | * @rate: desired clock rate in Hz | ||
| 431 | * | ||
| 432 | * Returns rounded clock rate in Hz, or negative errno. | ||
| 278 | */ | 433 | */ |
| 279 | static void change_parent(struct clk *cclk, struct clk *pclk) | 434 | long clk_round_rate(struct clk *clk, unsigned long drate) |
| 280 | { | 435 | { |
| 281 | unsigned long flags; | 436 | long rate = 0; |
| 437 | int index; | ||
| 438 | |||
| 439 | /* | ||
| 440 | * propagate call to parent who supports calc_rate. Similar approach is | ||
| 441 | * used in clk_set_rate. | ||
| 442 | */ | ||
| 443 | if (!clk->calc_rate) { | ||
| 444 | u32 mult; | ||
| 445 | if (!clk->pclk) | ||
| 446 | return clk->rate; | ||
| 447 | |||
| 448 | mult = clk->div_factor ? clk->div_factor : 1; | ||
| 449 | return clk_round_rate(clk->pclk, mult * drate) / mult; | ||
| 450 | } | ||
| 282 | 451 | ||
| 283 | spin_lock_irqsave(&clocks_lock, flags); | 452 | index = round_rate_index(clk, drate, &rate); |
| 284 | list_del(&cclk->sibling); | 453 | if (index >= 0) |
| 285 | list_add(&cclk->sibling, &pclk->children); | 454 | return rate; |
| 455 | else | ||
| 456 | return index; | ||
| 457 | } | ||
| 458 | EXPORT_SYMBOL(clk_round_rate); | ||
| 286 | 459 | ||
| 287 | cclk->pclk = pclk; | 460 | /*All below functions are called with lock held */ |
| 288 | spin_unlock_irqrestore(&clocks_lock, flags); | 461 | |
| 462 | /* | ||
| 463 | * Calculates pll clk rate for specific value of mode, m, n and p | ||
| 464 | * | ||
| 465 | * In normal mode | ||
| 466 | * rate = (2 * M[15:8] * Fin)/(N * 2^P) | ||
| 467 | * | ||
| 468 | * In Dithered mode | ||
| 469 | * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) | ||
| 470 | */ | ||
| 471 | unsigned long pll_calc_rate(struct clk *clk, int index) | ||
| 472 | { | ||
| 473 | unsigned long rate = clk->pclk->rate; | ||
| 474 | struct pll_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 475 | unsigned int mode; | ||
| 476 | |||
| 477 | mode = tbls[index].mode ? 256 : 1; | ||
| 478 | return (((2 * rate / 10000) * tbls[index].m) / | ||
| 479 | (mode * tbls[index].n * (1 << tbls[index].p))) * 10000; | ||
| 289 | } | 480 | } |
| 290 | 481 | ||
| 291 | /* | 482 | /* |
| @@ -297,13 +488,11 @@ static void change_parent(struct clk *cclk, struct clk *pclk) | |||
| 297 | * In Dithered mode | 488 | * In Dithered mode |
| 298 | * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) | 489 | * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) |
| 299 | */ | 490 | */ |
| 300 | void pll_clk_recalc(struct clk *clk) | 491 | int pll_clk_recalc(struct clk *clk) |
| 301 | { | 492 | { |
| 302 | struct pll_clk_config *config = clk->private_data; | 493 | struct pll_clk_config *config = clk->private_data; |
| 303 | unsigned int num = 2, den = 0, val, mode = 0; | 494 | unsigned int num = 2, den = 0, val, mode = 0; |
| 304 | unsigned long flags; | ||
| 305 | 495 | ||
| 306 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 307 | mode = (readl(config->mode_reg) >> config->masks->mode_shift) & | 496 | mode = (readl(config->mode_reg) >> config->masks->mode_shift) & |
| 308 | config->masks->mode_mask; | 497 | config->masks->mode_mask; |
| 309 | 498 | ||
| @@ -325,22 +514,120 @@ void pll_clk_recalc(struct clk *clk) | |||
| 325 | den *= 256; | 514 | den *= 256; |
| 326 | } | 515 | } |
| 327 | 516 | ||
| 517 | if (!den) | ||
| 518 | return -EINVAL; | ||
| 519 | |||
| 328 | clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; | 520 | clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; |
| 329 | spin_unlock_irqrestore(&clocks_lock, flags); | 521 | return 0; |
| 522 | } | ||
| 523 | |||
| 524 | /* | ||
| 525 | * Configures new clock rate of pll | ||
| 526 | */ | ||
| 527 | int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate) | ||
| 528 | { | ||
| 529 | struct pll_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 530 | struct pll_clk_config *config = clk->private_data; | ||
| 531 | unsigned long val, rate; | ||
| 532 | int i; | ||
| 533 | |||
| 534 | i = round_rate_index(clk, desired_rate, &rate); | ||
| 535 | if (i < 0) | ||
| 536 | return i; | ||
| 537 | |||
| 538 | val = readl(config->mode_reg) & | ||
| 539 | ~(config->masks->mode_mask << config->masks->mode_shift); | ||
| 540 | val |= (tbls[i].mode & config->masks->mode_mask) << | ||
| 541 | config->masks->mode_shift; | ||
| 542 | writel(val, config->mode_reg); | ||
| 543 | |||
| 544 | val = readl(config->cfg_reg) & | ||
| 545 | ~(config->masks->div_p_mask << config->masks->div_p_shift); | ||
| 546 | val |= (tbls[i].p & config->masks->div_p_mask) << | ||
| 547 | config->masks->div_p_shift; | ||
| 548 | val &= ~(config->masks->div_n_mask << config->masks->div_n_shift); | ||
| 549 | val |= (tbls[i].n & config->masks->div_n_mask) << | ||
| 550 | config->masks->div_n_shift; | ||
| 551 | val &= ~(config->masks->dith_fdbk_m_mask << | ||
| 552 | config->masks->dith_fdbk_m_shift); | ||
| 553 | if (tbls[i].mode) | ||
| 554 | val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) << | ||
| 555 | config->masks->dith_fdbk_m_shift; | ||
| 556 | else | ||
| 557 | val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) << | ||
| 558 | config->masks->norm_fdbk_m_shift; | ||
| 559 | |||
| 560 | writel(val, config->cfg_reg); | ||
| 561 | |||
| 562 | clk->rate = rate; | ||
| 563 | |||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* | ||
| 568 | * Calculates ahb, apb clk rate for specific value of div | ||
| 569 | */ | ||
| 570 | unsigned long bus_calc_rate(struct clk *clk, int index) | ||
| 571 | { | ||
| 572 | unsigned long rate = clk->pclk->rate; | ||
| 573 | struct bus_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 574 | |||
| 575 | return rate / (tbls[index].div + 1); | ||
| 330 | } | 576 | } |
| 331 | 577 | ||
| 332 | /* calculates current programmed rate of ahb or apb bus */ | 578 | /* calculates current programmed rate of ahb or apb bus */ |
| 333 | void bus_clk_recalc(struct clk *clk) | 579 | int bus_clk_recalc(struct clk *clk) |
| 334 | { | 580 | { |
| 335 | struct bus_clk_config *config = clk->private_data; | 581 | struct bus_clk_config *config = clk->private_data; |
| 336 | unsigned int div; | 582 | unsigned int div; |
| 337 | unsigned long flags; | ||
| 338 | 583 | ||
| 339 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 340 | div = ((readl(config->reg) >> config->masks->shift) & | 584 | div = ((readl(config->reg) >> config->masks->shift) & |
| 341 | config->masks->mask) + 1; | 585 | config->masks->mask) + 1; |
| 586 | |||
| 587 | if (!div) | ||
| 588 | return -EINVAL; | ||
| 589 | |||
| 342 | clk->rate = (unsigned long)clk->pclk->rate / div; | 590 | clk->rate = (unsigned long)clk->pclk->rate / div; |
| 343 | spin_unlock_irqrestore(&clocks_lock, flags); | 591 | return 0; |
| 592 | } | ||
| 593 | |||
| 594 | /* Configures new clock rate of AHB OR APB bus */ | ||
| 595 | int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate) | ||
| 596 | { | ||
| 597 | struct bus_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 598 | struct bus_clk_config *config = clk->private_data; | ||
| 599 | unsigned long val, rate; | ||
| 600 | int i; | ||
| 601 | |||
| 602 | i = round_rate_index(clk, desired_rate, &rate); | ||
| 603 | if (i < 0) | ||
| 604 | return i; | ||
| 605 | |||
| 606 | val = readl(config->reg) & | ||
| 607 | ~(config->masks->mask << config->masks->shift); | ||
| 608 | val |= (tbls[i].div & config->masks->mask) << config->masks->shift; | ||
| 609 | writel(val, config->reg); | ||
| 610 | |||
| 611 | clk->rate = rate; | ||
| 612 | |||
| 613 | return 0; | ||
| 614 | } | ||
| 615 | |||
| 616 | /* | ||
| 617 | * gives rate for different values of eq, x and y | ||
| 618 | * | ||
| 619 | * Fout from synthesizer can be given from two equations: | ||
| 620 | * Fout1 = (Fin * X/Y)/2 EQ1 | ||
| 621 | * Fout2 = Fin * X/Y EQ2 | ||
| 622 | */ | ||
| 623 | unsigned long aux_calc_rate(struct clk *clk, int index) | ||
| 624 | { | ||
| 625 | unsigned long rate = clk->pclk->rate; | ||
| 626 | struct aux_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 627 | u8 eq = tbls[index].eq ? 1 : 2; | ||
| 628 | |||
| 629 | return (((rate/10000) * tbls[index].xscale) / | ||
| 630 | (tbls[index].yscale * eq)) * 10000; | ||
| 344 | } | 631 | } |
| 345 | 632 | ||
| 346 | /* | 633 | /* |
| @@ -353,47 +640,76 @@ void bus_clk_recalc(struct clk *clk) | |||
| 353 | * | 640 | * |
| 354 | * Selection of eqn 1 or 2 is programmed in register | 641 | * Selection of eqn 1 or 2 is programmed in register |
| 355 | */ | 642 | */ |
| 356 | void aux_clk_recalc(struct clk *clk) | 643 | int aux_clk_recalc(struct clk *clk) |
| 357 | { | 644 | { |
| 358 | struct aux_clk_config *config = clk->private_data; | 645 | struct aux_clk_config *config = clk->private_data; |
| 359 | struct pclk_info *pclk_info = NULL; | ||
| 360 | unsigned int num = 1, den = 1, val, eqn; | 646 | unsigned int num = 1, den = 1, val, eqn; |
| 361 | unsigned long flags; | ||
| 362 | 647 | ||
| 363 | /* get current programmed parent */ | 648 | val = readl(config->synth_reg); |
| 364 | pclk_info = pclk_info_get(clk); | ||
| 365 | if (!pclk_info) { | ||
| 366 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 367 | clk->pclk = NULL; | ||
| 368 | clk->rate = 0; | ||
| 369 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
| 370 | return; | ||
| 371 | } | ||
| 372 | 649 | ||
| 373 | change_parent(clk, pclk_info->pclk); | 650 | eqn = (val >> config->masks->eq_sel_shift) & |
| 651 | config->masks->eq_sel_mask; | ||
| 652 | if (eqn == config->masks->eq1_mask) | ||
| 653 | den *= 2; | ||
| 374 | 654 | ||
| 375 | spin_lock_irqsave(&clocks_lock, flags); | 655 | /* calculate numerator */ |
| 376 | if (pclk_info->scalable) { | 656 | num = (val >> config->masks->xscale_sel_shift) & |
| 377 | val = readl(config->synth_reg); | 657 | config->masks->xscale_sel_mask; |
| 378 | |||
| 379 | eqn = (val >> config->masks->eq_sel_shift) & | ||
| 380 | config->masks->eq_sel_mask; | ||
| 381 | if (eqn == config->masks->eq1_mask) | ||
| 382 | den *= 2; | ||
| 383 | |||
| 384 | /* calculate numerator */ | ||
| 385 | num = (val >> config->masks->xscale_sel_shift) & | ||
| 386 | config->masks->xscale_sel_mask; | ||
| 387 | |||
| 388 | /* calculate denominator */ | ||
| 389 | den *= (val >> config->masks->yscale_sel_shift) & | ||
| 390 | config->masks->yscale_sel_mask; | ||
| 391 | val = (((clk->pclk->rate/10000) * num) / den) * 10000; | ||
| 392 | } else | ||
| 393 | val = clk->pclk->rate; | ||
| 394 | 658 | ||
| 395 | clk->rate = val; | 659 | /* calculate denominator */ |
| 396 | spin_unlock_irqrestore(&clocks_lock, flags); | 660 | den *= (val >> config->masks->yscale_sel_shift) & |
| 661 | config->masks->yscale_sel_mask; | ||
| 662 | |||
| 663 | if (!den) | ||
| 664 | return -EINVAL; | ||
| 665 | |||
| 666 | clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; | ||
| 667 | return 0; | ||
| 668 | } | ||
| 669 | |||
| 670 | /* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/ | ||
| 671 | int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate) | ||
| 672 | { | ||
| 673 | struct aux_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 674 | struct aux_clk_config *config = clk->private_data; | ||
| 675 | unsigned long val, rate; | ||
| 676 | int i; | ||
| 677 | |||
| 678 | i = round_rate_index(clk, desired_rate, &rate); | ||
| 679 | if (i < 0) | ||
| 680 | return i; | ||
| 681 | |||
| 682 | val = readl(config->synth_reg) & | ||
| 683 | ~(config->masks->eq_sel_mask << config->masks->eq_sel_shift); | ||
| 684 | val |= (tbls[i].eq & config->masks->eq_sel_mask) << | ||
| 685 | config->masks->eq_sel_shift; | ||
| 686 | val &= ~(config->masks->xscale_sel_mask << | ||
| 687 | config->masks->xscale_sel_shift); | ||
| 688 | val |= (tbls[i].xscale & config->masks->xscale_sel_mask) << | ||
| 689 | config->masks->xscale_sel_shift; | ||
| 690 | val &= ~(config->masks->yscale_sel_mask << | ||
| 691 | config->masks->yscale_sel_shift); | ||
| 692 | val |= (tbls[i].yscale & config->masks->yscale_sel_mask) << | ||
| 693 | config->masks->yscale_sel_shift; | ||
| 694 | writel(val, config->synth_reg); | ||
| 695 | |||
| 696 | clk->rate = rate; | ||
| 697 | |||
| 698 | return 0; | ||
| 699 | } | ||
| 700 | |||
| 701 | /* | ||
| 702 | * Calculates gpt clk rate for different values of mscale and nscale | ||
| 703 | * | ||
| 704 | * Fout= Fin/((2 ^ (N+1)) * (M+1)) | ||
| 705 | */ | ||
| 706 | unsigned long gpt_calc_rate(struct clk *clk, int index) | ||
| 707 | { | ||
| 708 | unsigned long rate = clk->pclk->rate; | ||
| 709 | struct gpt_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 710 | |||
| 711 | return rate / ((1 << (tbls[index].nscale + 1)) * | ||
| 712 | (tbls[index].mscale + 1)); | ||
| 397 | } | 713 | } |
| 398 | 714 | ||
| 399 | /* | 715 | /* |
| @@ -401,49 +717,142 @@ void aux_clk_recalc(struct clk *clk) | |||
| 401 | * Fout from synthesizer can be given from below equations: | 717 | * Fout from synthesizer can be given from below equations: |
| 402 | * Fout= Fin/((2 ^ (N+1)) * (M+1)) | 718 | * Fout= Fin/((2 ^ (N+1)) * (M+1)) |
| 403 | */ | 719 | */ |
| 404 | void gpt_clk_recalc(struct clk *clk) | 720 | int gpt_clk_recalc(struct clk *clk) |
| 405 | { | 721 | { |
| 406 | struct gpt_clk_config *config = clk->private_data; | 722 | struct gpt_clk_config *config = clk->private_data; |
| 407 | struct pclk_info *pclk_info = NULL; | ||
| 408 | unsigned int div = 1, val; | 723 | unsigned int div = 1, val; |
| 409 | unsigned long flags; | ||
| 410 | 724 | ||
| 411 | pclk_info = pclk_info_get(clk); | 725 | val = readl(config->synth_reg); |
| 412 | if (!pclk_info) { | 726 | div += (val >> config->masks->mscale_sel_shift) & |
| 413 | spin_lock_irqsave(&clocks_lock, flags); | 727 | config->masks->mscale_sel_mask; |
| 414 | clk->pclk = NULL; | 728 | div *= 1 << (((val >> config->masks->nscale_sel_shift) & |
| 415 | clk->rate = 0; | 729 | config->masks->nscale_sel_mask) + 1); |
| 416 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
| 417 | return; | ||
| 418 | } | ||
| 419 | 730 | ||
| 420 | change_parent(clk, pclk_info->pclk); | 731 | if (!div) |
| 421 | 732 | return -EINVAL; | |
| 422 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 423 | if (pclk_info->scalable) { | ||
| 424 | val = readl(config->synth_reg); | ||
| 425 | div += (val >> config->masks->mscale_sel_shift) & | ||
| 426 | config->masks->mscale_sel_mask; | ||
| 427 | div *= 1 << (((val >> config->masks->nscale_sel_shift) & | ||
| 428 | config->masks->nscale_sel_mask) + 1); | ||
| 429 | } | ||
| 430 | 733 | ||
| 431 | clk->rate = (unsigned long)clk->pclk->rate / div; | 734 | clk->rate = (unsigned long)clk->pclk->rate / div; |
| 432 | spin_unlock_irqrestore(&clocks_lock, flags); | 735 | return 0; |
| 736 | } | ||
| 737 | |||
| 738 | /* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/ | ||
| 739 | int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate) | ||
| 740 | { | ||
| 741 | struct gpt_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 742 | struct gpt_clk_config *config = clk->private_data; | ||
| 743 | unsigned long val, rate; | ||
| 744 | int i; | ||
| 745 | |||
| 746 | i = round_rate_index(clk, desired_rate, &rate); | ||
| 747 | if (i < 0) | ||
| 748 | return i; | ||
| 749 | |||
| 750 | val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask << | ||
| 751 | config->masks->mscale_sel_shift); | ||
| 752 | val |= (tbls[i].mscale & config->masks->mscale_sel_mask) << | ||
| 753 | config->masks->mscale_sel_shift; | ||
| 754 | val &= ~(config->masks->nscale_sel_mask << | ||
| 755 | config->masks->nscale_sel_shift); | ||
| 756 | val |= (tbls[i].nscale & config->masks->nscale_sel_mask) << | ||
| 757 | config->masks->nscale_sel_shift; | ||
| 758 | writel(val, config->synth_reg); | ||
| 759 | |||
| 760 | clk->rate = rate; | ||
| 761 | |||
| 762 | return 0; | ||
| 763 | } | ||
| 764 | |||
| 765 | /* | ||
| 766 | * Calculates clcd clk rate for different values of div | ||
| 767 | * | ||
| 768 | * Fout from synthesizer can be given from below equation: | ||
| 769 | * Fout= Fin/2*div (division factor) | ||
| 770 | * div is 17 bits:- | ||
| 771 | * 0-13 (fractional part) | ||
| 772 | * 14-16 (integer part) | ||
| 773 | * To calculate Fout we left shift val by 14 bits and divide Fin by | ||
| 774 | * complete div (including fractional part) and then right shift the | ||
| 775 | * result by 14 places. | ||
| 776 | */ | ||
| 777 | unsigned long clcd_calc_rate(struct clk *clk, int index) | ||
| 778 | { | ||
| 779 | unsigned long rate = clk->pclk->rate; | ||
| 780 | struct clcd_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 781 | |||
| 782 | rate /= 1000; | ||
| 783 | rate <<= 12; | ||
| 784 | rate /= (2 * tbls[index].div); | ||
| 785 | rate >>= 12; | ||
| 786 | rate *= 1000; | ||
| 787 | |||
| 788 | return rate; | ||
| 789 | } | ||
| 790 | |||
| 791 | /* | ||
| 792 | * calculates current programmed rate of clcd synthesizer | ||
| 793 | * Fout from synthesizer can be given from below equation: | ||
| 794 | * Fout= Fin/2*div (division factor) | ||
| 795 | * div is 17 bits:- | ||
| 796 | * 0-13 (fractional part) | ||
| 797 | * 14-16 (integer part) | ||
| 798 | * To calculate Fout we left shift val by 14 bits and divide Fin by | ||
| 799 | * complete div (including fractional part) and then right shift the | ||
| 800 | * result by 14 places. | ||
| 801 | */ | ||
| 802 | int clcd_clk_recalc(struct clk *clk) | ||
| 803 | { | ||
| 804 | struct clcd_clk_config *config = clk->private_data; | ||
| 805 | unsigned int div = 1; | ||
| 806 | unsigned long prate; | ||
| 807 | unsigned int val; | ||
| 808 | |||
| 809 | val = readl(config->synth_reg); | ||
| 810 | div = (val >> config->masks->div_factor_shift) & | ||
| 811 | config->masks->div_factor_mask; | ||
| 812 | |||
| 813 | if (!div) | ||
| 814 | return -EINVAL; | ||
| 815 | |||
| 816 | prate = clk->pclk->rate / 1000; /* first level division, make it KHz */ | ||
| 817 | |||
| 818 | clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12; | ||
| 819 | clk->rate *= 1000; | ||
| 820 | return 0; | ||
| 821 | } | ||
| 822 | |||
| 823 | /* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/ | ||
| 824 | int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate) | ||
| 825 | { | ||
| 826 | struct clcd_rate_tbl *tbls = clk->rate_config.tbls; | ||
| 827 | struct clcd_clk_config *config = clk->private_data; | ||
| 828 | unsigned long val, rate; | ||
| 829 | int i; | ||
| 830 | |||
| 831 | i = round_rate_index(clk, desired_rate, &rate); | ||
| 832 | if (i < 0) | ||
| 833 | return i; | ||
| 834 | |||
| 835 | val = readl(config->synth_reg) & ~(config->masks->div_factor_mask << | ||
| 836 | config->masks->div_factor_shift); | ||
| 837 | val |= (tbls[i].div & config->masks->div_factor_mask) << | ||
| 838 | config->masks->div_factor_shift; | ||
| 839 | writel(val, config->synth_reg); | ||
| 840 | |||
| 841 | clk->rate = rate; | ||
| 842 | |||
| 843 | return 0; | ||
| 433 | } | 844 | } |
| 434 | 845 | ||
| 435 | /* | 846 | /* |
| 436 | * Used for clocks that always have value as the parent clock divided by a | 847 | * Used for clocks that always have value as the parent clock divided by a |
| 437 | * fixed divisor | 848 | * fixed divisor |
| 438 | */ | 849 | */ |
| 439 | void follow_parent(struct clk *clk) | 850 | int follow_parent(struct clk *clk) |
| 440 | { | 851 | { |
| 441 | unsigned long flags; | ||
| 442 | unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor; | 852 | unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor; |
| 443 | 853 | ||
| 444 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 445 | clk->rate = clk->pclk->rate/div_factor; | 854 | clk->rate = clk->pclk->rate/div_factor; |
| 446 | spin_unlock_irqrestore(&clocks_lock, flags); | 855 | return 0; |
| 447 | } | 856 | } |
| 448 | 857 | ||
| 449 | /** | 858 | /** |
| @@ -454,5 +863,25 @@ void follow_parent(struct clk *clk) | |||
| 454 | */ | 863 | */ |
| 455 | void recalc_root_clocks(void) | 864 | void recalc_root_clocks(void) |
| 456 | { | 865 | { |
| 457 | propagate_rate(&root_clks); | 866 | struct clk *pclk; |
| 867 | unsigned long flags; | ||
| 868 | int ret = 0; | ||
| 869 | |||
| 870 | spin_lock_irqsave(&clocks_lock, flags); | ||
| 871 | list_for_each_entry(pclk, &root_clks, sibling) { | ||
| 872 | if (pclk->recalc) { | ||
| 873 | ret = pclk->recalc(pclk); | ||
| 874 | /* | ||
| 875 | * recalc will return error if clk out is not programmed | ||
| 876 | * In this case configure default clock. | ||
| 877 | */ | ||
| 878 | if (ret && pclk->set_rate) | ||
| 879 | pclk->set_rate(pclk, 0); | ||
| 880 | } | ||
| 881 | propagate_rate(pclk, 1); | ||
| 882 | /* Enable clks enabled on init, in software view */ | ||
| 883 | if (pclk->flags & ENABLED_ON_INIT) | ||
| 884 | do_clk_enable(pclk); | ||
| 885 | } | ||
| 886 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
| 458 | } | 887 | } |
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h index 863d9e983927..5a601d830971 100644 --- a/arch/arm/plat-spear/include/plat/clock.h +++ b/arch/arm/plat-spear/include/plat/clock.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | /* clk structure flags */ | 21 | /* clk structure flags */ |
| 22 | #define ALWAYS_ENABLED (1 << 0) /* clock always enabled */ | 22 | #define ALWAYS_ENABLED (1 << 0) /* clock always enabled */ |
| 23 | #define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */ | 23 | #define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */ |
| 24 | #define ENABLED_ON_INIT (1 << 2) /* clocks enabled at init */ | ||
| 24 | 25 | ||
| 25 | /** | 26 | /** |
| 26 | * struct clkops - clock operations | 27 | * struct clkops - clock operations |
| @@ -35,13 +36,11 @@ struct clkops { | |||
| 35 | /** | 36 | /** |
| 36 | * struct pclk_info - parents info | 37 | * struct pclk_info - parents info |
| 37 | * @pclk: pointer to parent clk | 38 | * @pclk: pointer to parent clk |
| 38 | * @pclk_mask: value to be written for selecting this parent | 39 | * @pclk_val: value to be written for selecting this parent |
| 39 | * @scalable: Is parent scalable (1 - YES, 0 - NO) | ||
| 40 | */ | 40 | */ |
| 41 | struct pclk_info { | 41 | struct pclk_info { |
| 42 | struct clk *pclk; | 42 | struct clk *pclk; |
| 43 | u8 pclk_mask; | 43 | u8 pclk_val; |
| 44 | u8 scalable; | ||
| 45 | }; | 44 | }; |
| 46 | 45 | ||
| 47 | /** | 46 | /** |
| @@ -59,6 +58,18 @@ struct pclk_sel { | |||
| 59 | }; | 58 | }; |
| 60 | 59 | ||
| 61 | /** | 60 | /** |
| 61 | * struct rate_config - clk rate configurations | ||
| 62 | * @tbls: array of device specific clk rate tables, in ascending order of rates | ||
| 63 | * @count: size of tbls array | ||
| 64 | * @default_index: default setting when originally disabled | ||
| 65 | */ | ||
| 66 | struct rate_config { | ||
| 67 | void *tbls; | ||
| 68 | u8 count; | ||
| 69 | u8 default_index; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /** | ||
| 62 | * struct clk - clock structure | 73 | * struct clk - clock structure |
| 63 | * @usage_count: num of users who enabled this clock | 74 | * @usage_count: num of users who enabled this clock |
| 64 | * @flags: flags for clock properties | 75 | * @flags: flags for clock properties |
| @@ -67,7 +78,10 @@ struct pclk_sel { | |||
| 67 | * @en_reg_bit: clk enable/disable bit | 78 | * @en_reg_bit: clk enable/disable bit |
| 68 | * @ops: clk enable/disable ops - generic_clkops selected if NULL | 79 | * @ops: clk enable/disable ops - generic_clkops selected if NULL |
| 69 | * @recalc: pointer to clock rate recalculate function | 80 | * @recalc: pointer to clock rate recalculate function |
| 70 | * @div_factor: division factor to parent clock. Only for recalc = follow_parent | 81 | * @set_rate: pointer to clock set rate function |
| 82 | * @calc_rate: pointer to clock get rate function for index | ||
| 83 | * @rate_config: rate configuration information, used by set_rate | ||
| 84 | * @div_factor: division factor to parent clock. | ||
| 71 | * @pclk: current parent clk | 85 | * @pclk: current parent clk |
| 72 | * @pclk_sel: pointer to parent selection structure | 86 | * @pclk_sel: pointer to parent selection structure |
| 73 | * @pclk_sel_shift: register shift for selecting parent of this clock | 87 | * @pclk_sel_shift: register shift for selecting parent of this clock |
| @@ -82,7 +96,10 @@ struct clk { | |||
| 82 | void __iomem *en_reg; | 96 | void __iomem *en_reg; |
| 83 | u8 en_reg_bit; | 97 | u8 en_reg_bit; |
| 84 | const struct clkops *ops; | 98 | const struct clkops *ops; |
| 85 | void (*recalc) (struct clk *); | 99 | int (*recalc) (struct clk *); |
| 100 | int (*set_rate) (struct clk *, unsigned long rate); | ||
| 101 | unsigned long (*calc_rate)(struct clk *, int index); | ||
| 102 | struct rate_config rate_config; | ||
| 86 | unsigned int div_factor; | 103 | unsigned int div_factor; |
| 87 | 104 | ||
| 88 | struct clk *pclk; | 105 | struct clk *pclk; |
| @@ -115,6 +132,14 @@ struct pll_clk_config { | |||
| 115 | struct pll_clk_masks *masks; | 132 | struct pll_clk_masks *masks; |
| 116 | }; | 133 | }; |
| 117 | 134 | ||
| 135 | /* pll clk rate config structure */ | ||
| 136 | struct pll_rate_tbl { | ||
| 137 | u8 mode; | ||
| 138 | u16 m; | ||
| 139 | u8 n; | ||
| 140 | u8 p; | ||
| 141 | }; | ||
| 142 | |||
| 118 | /* ahb and apb bus configuration structure */ | 143 | /* ahb and apb bus configuration structure */ |
| 119 | struct bus_clk_masks { | 144 | struct bus_clk_masks { |
| 120 | u32 mask; | 145 | u32 mask; |
| @@ -126,6 +151,11 @@ struct bus_clk_config { | |||
| 126 | struct bus_clk_masks *masks; | 151 | struct bus_clk_masks *masks; |
| 127 | }; | 152 | }; |
| 128 | 153 | ||
| 154 | /* ahb and apb clk bus rate config structure */ | ||
| 155 | struct bus_rate_tbl { | ||
| 156 | u8 div; | ||
| 157 | }; | ||
| 158 | |||
| 129 | /* Aux clk configuration structure: applicable to UART and FIRDA */ | 159 | /* Aux clk configuration structure: applicable to UART and FIRDA */ |
| 130 | struct aux_clk_masks { | 160 | struct aux_clk_masks { |
| 131 | u32 eq_sel_mask; | 161 | u32 eq_sel_mask; |
| @@ -143,6 +173,13 @@ struct aux_clk_config { | |||
| 143 | struct aux_clk_masks *masks; | 173 | struct aux_clk_masks *masks; |
| 144 | }; | 174 | }; |
| 145 | 175 | ||
| 176 | /* aux clk rate config structure */ | ||
| 177 | struct aux_rate_tbl { | ||
| 178 | u16 xscale; | ||
| 179 | u16 yscale; | ||
| 180 | u8 eq; | ||
| 181 | }; | ||
| 182 | |||
| 146 | /* GPT clk configuration structure */ | 183 | /* GPT clk configuration structure */ |
| 147 | struct gpt_clk_masks { | 184 | struct gpt_clk_masks { |
| 148 | u32 mscale_sel_mask; | 185 | u32 mscale_sel_mask; |
| @@ -156,15 +193,48 @@ struct gpt_clk_config { | |||
| 156 | struct gpt_clk_masks *masks; | 193 | struct gpt_clk_masks *masks; |
| 157 | }; | 194 | }; |
| 158 | 195 | ||
| 196 | /* gpt clk rate config structure */ | ||
| 197 | struct gpt_rate_tbl { | ||
| 198 | u16 mscale; | ||
| 199 | u16 nscale; | ||
| 200 | }; | ||
| 201 | |||
| 202 | /* clcd clk configuration structure */ | ||
| 203 | struct clcd_synth_masks { | ||
| 204 | u32 div_factor_mask; | ||
| 205 | u32 div_factor_shift; | ||
| 206 | }; | ||
| 207 | |||
| 208 | struct clcd_clk_config { | ||
| 209 | void __iomem *synth_reg; | ||
| 210 | struct clcd_synth_masks *masks; | ||
| 211 | }; | ||
| 212 | |||
| 213 | /* clcd clk rate config structure */ | ||
| 214 | struct clcd_rate_tbl { | ||
| 215 | u16 div; | ||
| 216 | }; | ||
| 217 | |||
| 159 | /* platform specific clock functions */ | 218 | /* platform specific clock functions */ |
| 160 | void clk_register(struct clk_lookup *cl); | 219 | void clk_register(struct clk_lookup *cl); |
| 161 | void recalc_root_clocks(void); | 220 | void recalc_root_clocks(void); |
| 162 | 221 | ||
| 163 | /* clock recalc functions */ | 222 | /* clock recalc & set rate functions */ |
| 164 | void follow_parent(struct clk *clk); | 223 | int follow_parent(struct clk *clk); |
| 165 | void pll_clk_recalc(struct clk *clk); | 224 | unsigned long pll_calc_rate(struct clk *clk, int index); |
| 166 | void bus_clk_recalc(struct clk *clk); | 225 | int pll_clk_recalc(struct clk *clk); |
| 167 | void gpt_clk_recalc(struct clk *clk); | 226 | int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate); |
| 168 | void aux_clk_recalc(struct clk *clk); | 227 | unsigned long bus_calc_rate(struct clk *clk, int index); |
| 228 | int bus_clk_recalc(struct clk *clk); | ||
| 229 | int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate); | ||
| 230 | unsigned long gpt_calc_rate(struct clk *clk, int index); | ||
| 231 | int gpt_clk_recalc(struct clk *clk); | ||
| 232 | int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate); | ||
| 233 | unsigned long aux_calc_rate(struct clk *clk, int index); | ||
| 234 | int aux_clk_recalc(struct clk *clk); | ||
| 235 | int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate); | ||
| 236 | unsigned long clcd_calc_rate(struct clk *clk, int index); | ||
| 237 | int clcd_clk_recalc(struct clk *clk); | ||
| 238 | int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate); | ||
| 169 | 239 | ||
| 170 | #endif /* __PLAT_CLOCK_H */ | 240 | #endif /* __PLAT_CLOCK_H */ |
