+
+static void exynos4210_cmu_set_pll(void *opaque, Exynos4210ClockState
*pll)
+{
+ Exynos4210CmuState *s = opaque;
+ Exynos4210ClockState *source;
+ target_phys_addr_t offset = pll->div_reg;
+ ClockChangeEntry *cce;
+ uint32_t pdiv, mdiv, sdiv, enable;
+
+ source = exynos4210_clock_find(pll->src_id);
+
+ if (source == NULL) {
+ hw_error("We haven't find source clock %d (requested for %s)\n",
+ pll->src_id, pll->name);
+ }
+
+ /*
+ * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
+ */
+
+ enable = (s->reg[I_(offset)]& PLL_ENABLE_MASK)>> PLL_ENABLE_SHIFT;
+ mdiv = (s->reg[I_(offset)]& PLL_MDIV_MASK)>> PLL_MDIV_SHIFT;
+ pdiv = (s->reg[I_(offset)]& PLL_PDIV_MASK)>> PLL_PDIV_SHIFT;
+ sdiv = (s->reg[I_(offset)]& PLL_SDIV_MASK)>> PLL_SDIV_SHIFT;
+
+ if (source) {
+ if (enable) {
+ pll->rate = mdiv * source->rate / (pdiv * (1<< (sdiv-1)));
+ } else {
+ pll->rate = 0;
+ }
+ } else {
+ hw_error("%s: Source undefined for %s\n", __func__, pll->name);
+ }
+
+ QTAILQ_FOREACH(cce,&pll->clock_change_handler, entry) {
+ cce->func(cce->opaque);
+ }
+
+ PRINT_DEBUG("%s rate: %llu\n", pll->name, pll->rate);