static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_device *cdev = to_clk_device(hw); u32 divisor; unsigned long flags = 0; if (rate == 0) return 0; divisor = parent_rate / rate; /* If prate / rate would be decimal, incr the divisor */ if (rate * divisor < parent_rate) divisor++; if (divisor == cdev->div_mask + 1) divisor = 0; /* SDMMC mask may need to be corrected before testing if its valid */ if ((cdev->div_mask == 0x3F) && (divisor > 31)) { /* * Bit 5 is a fixed /64 predivisor. If the requested divisor * is >31 then correct for the fixed divisor being required. */ divisor = 0x20 + (divisor / 64); } if (divisor > cdev->div_mask) { pr_err("%s: invalid divisor for clock\n", __func__); return -EINVAL; } spin_lock_irqsave(cdev->lock, flags); vt8500_pmc_wait_busy(); writel(divisor, cdev->div_reg); vt8500_pmc_wait_busy(); spin_lock_irqsave(cdev->lock, flags); return 0; }
static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); u32 filter, mul, div1, div2; u32 pll_val; unsigned long flags = 0; /* sanity check */ switch (pll->type) { case PLL_TYPE_VT8500: vt8500_find_pll_bits(rate, parent_rate, &mul, &div1); pll_val = VT8500_BITS_TO_VAL(mul, div1); break; case PLL_TYPE_WM8650: wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); pll_val = WM8650_BITS_TO_VAL(mul, div1, div2); break; case PLL_TYPE_WM8750: wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); break; case PLL_TYPE_WM8850: wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); pll_val = WM8850_BITS_TO_VAL(mul, div1, div2); break; default: pr_err("%s: invalid pll type\n", __func__); return 0; } spin_lock_irqsave(pll->lock, flags); vt8500_pmc_wait_busy(); writel(pll_val, pll->reg); vt8500_pmc_wait_busy(); spin_unlock_irqrestore(pll->lock, flags); return 0; }