static int pix_rdi_set_parent(struct clk_hw *hw, u8 index) { int i; int ret = 0; u32 val; struct clk_pix_rdi *rdi = to_clk_pix_rdi(hw); struct clk *clk = hw->clk; int num_parents = __clk_get_num_parents(hw->clk); /* * These clocks select three inputs via two muxes. One mux selects * between csi0 and csi1 and the second mux selects between that mux's * output and csi2. The source and destination selections for each * mux must be clocking for the switch to succeed so just turn on * all three sources because it's easier than figuring out what source * needs to be on at what time. */ for (i = 0; i < num_parents; i++) { ret = clk_prepare_enable(clk_get_parent_by_index(clk, i)); if (ret) goto err; } if (index == 2) val = rdi->s2_mask; else val = 0; regmap_update_bits(rdi->clkr.regmap, rdi->s2_reg, rdi->s2_mask, val); /* * Wait at least 6 cycles of slowest clock * for the glitch-free MUX to fully switch sources. */ udelay(1); if (index == 1) val = rdi->s_mask; else val = 0; regmap_update_bits(rdi->clkr.regmap, rdi->s_reg, rdi->s_mask, val); /* * Wait at least 6 cycles of slowest clock * for the glitch-free MUX to fully switch sources. */ udelay(1); err: for (i--; i >= 0; i--) clk_disable_unprepare(clk_get_parent_by_index(clk, i)); return ret; }
static void dw_mci_hs_set_parent(struct dw_mci *host, int timing) { struct dw_mci_hs_priv_data *priv = host->priv; int id = priv->id; struct clk *clk_parent = NULL; int reg_value; if (id != DW_MCI_EMMC_ID) return; /* first disable GPIO div clock */ reg_value = mci_readl(host, GPIO); mci_writel(host, GPIO, reg_value & ~GPIO_CLK_ENABLE); udelay(1); #ifndef CONFIG_ARCH_HI3630 /* select 19.2M clk */ if (timing == MMC_TIMING_LEGACY) { clk_parent = clk_get_parent_by_index(host->parent_clk, 0); if (IS_ERR_OR_NULL(clk_parent)) { dev_err(host->dev, " fail to get parent clk. \n"); } clk_set_parent(host->parent_clk, clk_parent); } else { clk_parent = clk_get_parent_by_index(host->parent_clk, 4); if (IS_ERR_OR_NULL(clk_parent)) { dev_err(host->dev, " fail to get parent clk. \n"); } clk_set_parent(host->parent_clk, clk_parent); } #else clk_parent = clk_get_parent_by_index(host->parent_clk, 4); if (IS_ERR_OR_NULL(clk_parent)) { dev_err(host->dev, " fail to get parent clk. \n"); } clk_set_parent(host->parent_clk, clk_parent); #endif /* enable internal GPIO div clock */ mci_writel(host, GPIO, reg_value | GPIO_CLK_ENABLE); }
static long clk_mux_with_evendiv_determine_rate(struct clk_hw *div_hw, unsigned long rate, unsigned long *best_parent_rate, struct clk **best_parent_p) { struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL; int i, num_parents; unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0; parent = __clk_get_parent(clk); if(!parent){ best = __clk_get_rate(clk); goto out; } /* if NO_REPARENT flag set, pass through to current parent */ if (clk->flags & CLK_SET_RATE_NO_REPARENT) { best_prate = __clk_get_rate(parent); best = clk_div_round_rate_even(div_hw, rate, &best_prate); goto out; } /* find the parent that can provide the fastest rate <= rate */ num_parents = clk->num_parents; for (i = 0; i < num_parents; i++) { parent = clk_get_parent_by_index(clk, i); if (!parent) continue; parent_rate = __clk_get_rate(parent); now = clk_div_round_rate_even(div_hw, rate, &parent_rate); if (now <= rate && now > best) { best_parent = parent; best_prate = parent_rate; best = now; } } out: if(best_prate) *best_parent_rate = best_prate; if (best_parent) *best_parent_p = best_parent; clk_debug("clk name = %s, determine rate = %lu, best = %lu\n" "\tbest_parent name = %s, best_prate = %lu\n", clk->name, rate, best, __clk_get_name(*best_parent_p), *best_parent_rate); return best; }
static struct clk *mux_get_safe_parent(struct clk_hw *hw) { int i; struct mux_clk *mux = to_mux_clk(hw); int num_parents = __clk_get_num_parents(hw->clk); if (!mux->has_safe_parent) return NULL; i = mux->safe_sel; if (mux->parent_map) for (i = 0; i < num_parents; i++) if (mux->safe_sel == mux->parent_map[i]) break; return clk_get_parent_by_index(hw->clk, i); }
static long __mux_div_round_rate(struct clk_hw *hw, unsigned long rate, struct clk **best_parent, int *best_div, unsigned long *best_prate) { struct mux_div_clk *md = to_mux_div_clk(hw); unsigned int i; unsigned long rrate, best = 0, _best_div = 0, _best_prate = 0; struct clk *_best_parent = 0; int num_parents = __clk_get_num_parents(hw->clk); bool set_parent = __clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT; for (i = 0; i < num_parents; i++) { int div; unsigned long prate; struct clk *p = clk_get_parent_by_index(hw->clk, i); rrate = __div_round_rate(&md->data, rate, p, &div, &prate, set_parent); if (is_better_rate(rate, best, rrate)) { best = rrate; _best_div = div; _best_prate = prate; _best_parent = p; } if (rate <= rrate) break; } if (best_div) *best_div = _best_div; if (best_prate) *best_prate = _best_prate; if (best_parent) *best_parent = _best_parent; if (best) return best; return -EINVAL; }
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long min_rate, unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_p) { struct clk_composite *composite = to_clk_composite(hw); const struct clk_ops *rate_ops = composite->rate_ops; const struct clk_ops *mux_ops = composite->mux_ops; struct clk_hw *rate_hw = composite->rate_hw; struct clk_hw *mux_hw = composite->mux_hw; struct clk *parent; unsigned long parent_rate; long tmp_rate, best_rate = 0; unsigned long rate_diff; unsigned long best_rate_diff = ULONG_MAX; int i; if (rate_hw && rate_ops && rate_ops->determine_rate) { __clk_hw_set_clk(rate_hw, hw); return rate_ops->determine_rate(rate_hw, rate, min_rate, max_rate, best_parent_rate, best_parent_p); } else if (rate_hw && rate_ops && rate_ops->round_rate && mux_hw && mux_ops && mux_ops->set_parent) { *best_parent_p = NULL; if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) { parent = clk_get_parent(mux_hw->clk); *best_parent_p = __clk_get_hw(parent); *best_parent_rate = __clk_get_rate(parent); return rate_ops->round_rate(rate_hw, rate, best_parent_rate); } for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) { parent = clk_get_parent_by_index(mux_hw->clk, i); if (!parent) continue; parent_rate = __clk_get_rate(parent); tmp_rate = rate_ops->round_rate(rate_hw, rate, &parent_rate); if (tmp_rate < 0) continue; rate_diff = abs(rate - tmp_rate); if (!rate_diff || !*best_parent_p || best_rate_diff > rate_diff) { *best_parent_p = __clk_get_hw(parent); *best_parent_rate = parent_rate; best_rate_diff = rate_diff; best_rate = tmp_rate; } if (!rate_diff) return rate; } return best_rate; } else if (mux_hw && mux_ops && mux_ops->determine_rate) { __clk_hw_set_clk(mux_hw, hw); return mux_ops->determine_rate(mux_hw, rate, min_rate, max_rate, best_parent_rate, best_parent_p); } else { pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n"); return 0; } }