diff options
Diffstat (limited to 'drivers/clk/clk-mux.c')
| -rw-r--r-- | drivers/clk/clk-mux.c | 50 | 
1 files changed, 39 insertions, 11 deletions
| diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 508c032edce..25b1734560d 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -32,6 +32,7 @@  static u8 clk_mux_get_parent(struct clk_hw *hw)  {  	struct clk_mux *mux = to_clk_mux(hw); +	int num_parents = __clk_get_num_parents(hw->clk);  	u32 val;  	/* @@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)  	 * val = 0x4 really means "bit 2, index starts at bit 0"  	 */  	val = readl(mux->reg) >> mux->shift; -	val &= (1 << mux->width) - 1; +	val &= mux->mask; + +	if (mux->table) { +		int i; + +		for (i = 0; i < num_parents; i++) +			if (mux->table[i] == val) +				return i; +		return -EINVAL; +	}  	if (val && (mux->flags & CLK_MUX_INDEX_BIT))  		val = ffs(val) - 1; @@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)  	if (val && (mux->flags & CLK_MUX_INDEX_ONE))  		val--; -	if (val >= __clk_get_num_parents(hw->clk)) +	if (val >= num_parents)  		return -EINVAL;  	return val; @@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)  	u32 val;  	unsigned long flags = 0; -	if (mux->flags & CLK_MUX_INDEX_BIT) -		index = (1 << ffs(index)); +	if (mux->table) +		index = mux->table[index]; -	if (mux->flags & CLK_MUX_INDEX_ONE) -		index++; +	else { +		if (mux->flags & CLK_MUX_INDEX_BIT) +			index = (1 << ffs(index)); + +		if (mux->flags & CLK_MUX_INDEX_ONE) +			index++; +	}  	if (mux->lock)  		spin_lock_irqsave(mux->lock, flags);  	val = readl(mux->reg); -	val &= ~(((1 << mux->width) - 1) << mux->shift); +	val &= ~(mux->mask << mux->shift);  	val |= index << mux->shift;  	writel(val, mux->reg); @@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = {  };  EXPORT_SYMBOL_GPL(clk_mux_ops); -struct clk *clk_register_mux(struct device *dev, const char *name, +struct clk *clk_register_mux_table(struct device *dev, const char *name,  		const char **parent_names, u8 num_parents, unsigned long flags, -		void __iomem *reg, u8 shift, u8 width, -		u8 clk_mux_flags, spinlock_t *lock) +		void __iomem *reg, u8 shift, u32 mask, +		u8 clk_mux_flags, u32 *table, spinlock_t *lock)  {  	struct clk_mux *mux;  	struct clk *clk; @@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name,  	/* struct clk_mux assignments */  	mux->reg = reg;  	mux->shift = shift; -	mux->width = width; +	mux->mask = mask;  	mux->flags = clk_mux_flags;  	mux->lock = lock; +	mux->table = table;  	mux->hw.init = &init;  	clk = clk_register(dev, &mux->hw); @@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name,  	return clk;  } + +struct clk *clk_register_mux(struct device *dev, const char *name, +		const char **parent_names, u8 num_parents, unsigned long flags, +		void __iomem *reg, u8 shift, u8 width, +		u8 clk_mux_flags, spinlock_t *lock) +{ +	u32 mask = BIT(width) - 1; + +	return clk_register_mux_table(dev, name, parent_names, num_parents, +				      flags, reg, shift, mask, clk_mux_flags, +				      NULL, lock); +} |