void __clk_put(struct clk *clk) { int ret; ret = atomic_dec_return( &clk->use_cnt ); if( ret > 0 ) return; BUG_ON( ret < 0 ); if( clk->parent ) __clk_put( clk->parent ); }
static int zclk_set_rate(struct clk *clk, unsigned long rate) { void __iomem *frqcrc; int ret; unsigned long step, p_rate; u32 val; if (!clk->parent || !__clk_get(clk->parent)) return -ENODEV; if (!atomic_inc_and_test(&frqcr_lock) || !frqcr_kick_check(clk)) { ret = -EBUSY; goto done; } /* * Users are supposed to first call clk_set_rate() only with * clk_round_rate() results. So, we don't fix wrong rates here, but * guard against them anyway */ p_rate = clk_get_rate(clk->parent); if (rate == p_rate) { val = 0; } else { step = DIV_ROUND_CLOSEST(p_rate, 32); if (rate > p_rate || rate < step) { ret = -EINVAL; goto done; } val = 32 - rate / step; } frqcrc = clk->mapped_reg + (FRQCRC - (u32)clk->enable_reg); iowrite32((ioread32(frqcrc) & ~(clk->div_mask << clk->enable_bit)) | (val << clk->enable_bit), frqcrc); ret = frqcr_kick_do(clk); done: atomic_dec(&frqcr_lock); __clk_put(clk->parent); return ret; }