clk: meson: migrate the audio divider clock to clk_regmap
Rework meson audio divider driver to use clk_regmap and move gxbb clock using meson_clk_audio_divider to clk_regmap. Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
This commit is contained in:
		
							parent
							
								
									c763e61ae8
								
							
						
					
					
						commit
						88a4e12836
					
				| @ -28,8 +28,11 @@ | ||||
| #include <linux/clk-provider.h> | ||||
| #include "clkc.h" | ||||
| 
 | ||||
| #define to_meson_clk_audio_divider(_hw) container_of(_hw, \ | ||||
| 				struct meson_clk_audio_divider, hw) | ||||
| static inline struct meson_clk_audio_div_data * | ||||
| meson_clk_audio_div_data(struct clk_regmap *clk) | ||||
| { | ||||
| 	return (struct meson_clk_audio_div_data *)clk->data; | ||||
| } | ||||
| 
 | ||||
| static int _div_round(unsigned long parent_rate, unsigned long rate, | ||||
| 		      unsigned long flags) | ||||
| @ -45,15 +48,9 @@ static int _get_val(unsigned long parent_rate, unsigned long rate) | ||||
| 	return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; | ||||
| } | ||||
| 
 | ||||
| static int _valid_divider(struct clk_hw *hw, int divider) | ||||
| static int _valid_divider(unsigned int width, int divider) | ||||
| { | ||||
| 	struct meson_clk_audio_divider *adiv = | ||||
| 		to_meson_clk_audio_divider(hw); | ||||
| 	int max_divider; | ||||
| 	u8 width; | ||||
| 
 | ||||
| 	width = adiv->div.width; | ||||
| 	max_divider = 1 << width; | ||||
| 	int max_divider = 1 << width; | ||||
| 
 | ||||
| 	return clamp(divider, 1, max_divider); | ||||
| } | ||||
| @ -61,14 +58,11 @@ static int _valid_divider(struct clk_hw *hw, int divider) | ||||
| static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, | ||||
| 					       unsigned long parent_rate) | ||||
| { | ||||
| 	struct meson_clk_audio_divider *adiv = | ||||
| 		to_meson_clk_audio_divider(hw); | ||||
| 	struct parm *p; | ||||
| 	unsigned long reg, divider; | ||||
| 	struct clk_regmap *clk = to_clk_regmap(hw); | ||||
| 	struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); | ||||
| 	unsigned long divider; | ||||
| 
 | ||||
| 	p = &adiv->div; | ||||
| 	reg = readl(adiv->base + p->reg_off); | ||||
| 	divider = PARM_GET(p->width, p->shift, reg) + 1; | ||||
| 	divider = meson_parm_read(clk->map, &adiv->div); | ||||
| 
 | ||||
| 	return DIV_ROUND_UP_ULL((u64)parent_rate, divider); | ||||
| } | ||||
| @ -77,14 +71,14 @@ static long audio_divider_round_rate(struct clk_hw *hw, | ||||
| 				     unsigned long rate, | ||||
| 				     unsigned long *parent_rate) | ||||
| { | ||||
| 	struct meson_clk_audio_divider *adiv = | ||||
| 		to_meson_clk_audio_divider(hw); | ||||
| 	struct clk_regmap *clk = to_clk_regmap(hw); | ||||
| 	struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); | ||||
| 	unsigned long max_prate; | ||||
| 	int divider; | ||||
| 
 | ||||
| 	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { | ||||
| 		divider = _div_round(*parent_rate, rate, adiv->flags); | ||||
| 		divider = _valid_divider(hw, divider); | ||||
| 		divider = _valid_divider(adiv->div.width, divider); | ||||
| 		return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); | ||||
| 	} | ||||
| 
 | ||||
| @ -93,7 +87,7 @@ static long audio_divider_round_rate(struct clk_hw *hw, | ||||
| 
 | ||||
| 	/* Get the corresponding rounded down divider */ | ||||
| 	divider = max_prate / rate; | ||||
| 	divider = _valid_divider(hw, divider); | ||||
| 	divider = _valid_divider(adiv->div.width, divider); | ||||
| 
 | ||||
| 	/* Get actual rate of the parent */ | ||||
| 	*parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), | ||||
| @ -106,28 +100,11 @@ static int audio_divider_set_rate(struct clk_hw *hw, | ||||
| 				  unsigned long rate, | ||||
| 				  unsigned long parent_rate) | ||||
| { | ||||
| 	struct meson_clk_audio_divider *adiv = | ||||
| 		to_meson_clk_audio_divider(hw); | ||||
| 	struct parm *p; | ||||
| 	unsigned long reg, flags = 0; | ||||
| 	int val; | ||||
| 	struct clk_regmap *clk = to_clk_regmap(hw); | ||||
| 	struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); | ||||
| 	int val = _get_val(parent_rate, rate); | ||||
| 
 | ||||
| 	val = _get_val(parent_rate, rate); | ||||
| 
 | ||||
| 	if (adiv->lock) | ||||
| 		spin_lock_irqsave(adiv->lock, flags); | ||||
| 	else | ||||
| 		__acquire(adiv->lock); | ||||
| 
 | ||||
| 	p = &adiv->div; | ||||
| 	reg = readl(adiv->base + p->reg_off); | ||||
| 	reg = PARM_SET(p->width, p->shift, reg, val); | ||||
| 	writel(reg, adiv->base + p->reg_off); | ||||
| 
 | ||||
| 	if (adiv->lock) | ||||
| 		spin_unlock_irqrestore(adiv->lock, flags); | ||||
| 	else | ||||
| 		__release(adiv->lock); | ||||
| 	meson_parm_write(clk->map, &adiv->div, val); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -142,12 +142,9 @@ struct meson_clk_mpll_data { | ||||
| 	spinlock_t *lock; | ||||
| }; | ||||
| 
 | ||||
| struct meson_clk_audio_divider { | ||||
| 	struct clk_hw hw; | ||||
| 	void __iomem *base; | ||||
| struct meson_clk_audio_div_data { | ||||
| 	struct parm div; | ||||
| 	u8 flags; | ||||
| 	spinlock_t *lock; | ||||
| }; | ||||
| 
 | ||||
| #define MESON_GATE(_name, _reg, _bit)					\ | ||||
|  | ||||
| @ -826,14 +826,15 @@ static struct clk_regmap gxbb_cts_amclk_sel = { | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static struct meson_clk_audio_divider gxbb_cts_amclk_div = { | ||||
| 	.div = { | ||||
| 		.reg_off = HHI_AUD_CLK_CNTL, | ||||
| 		.shift   = 0, | ||||
| 		.width   = 8, | ||||
| static struct clk_regmap gxbb_cts_amclk_div = { | ||||
| 	.data = &(struct meson_clk_audio_div_data){ | ||||
| 		.div = { | ||||
| 			.reg_off = HHI_AUD_CLK_CNTL, | ||||
| 			.shift   = 0, | ||||
| 			.width   = 8, | ||||
| 		}, | ||||
| 		.flags = CLK_DIVIDER_ROUND_CLOSEST, | ||||
| 	}, | ||||
| 	.flags = CLK_DIVIDER_ROUND_CLOSEST, | ||||
| 	.lock = &meson_clk_lock, | ||||
| 	.hw.init = &(struct clk_init_data){ | ||||
| 		.name = "cts_amclk_div", | ||||
| 		.ops = &meson_clk_audio_divider_ops, | ||||
| @ -1777,10 +1778,6 @@ static struct meson_clk_pll *const gxl_clk_plls[] = { | ||||
| 	&gxl_gp0_pll, | ||||
| }; | ||||
| 
 | ||||
| static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { | ||||
| 	&gxbb_cts_amclk_div, | ||||
| }; | ||||
| 
 | ||||
| static struct clk_regmap *const gx_clk_regmaps[] = { | ||||
| 	&gxbb_clk81, | ||||
| 	&gxbb_ddr, | ||||
| @ -1912,29 +1909,24 @@ static struct clk_regmap *const gx_clk_regmaps[] = { | ||||
| 	&gxbb_mpll0, | ||||
| 	&gxbb_mpll1, | ||||
| 	&gxbb_mpll2, | ||||
| 	&gxbb_cts_amclk_div, | ||||
| }; | ||||
| 
 | ||||
| struct clkc_data { | ||||
| 	struct meson_clk_pll *const *clk_plls; | ||||
| 	unsigned int clk_plls_count; | ||||
| 	struct meson_clk_audio_divider *const *clk_audio_dividers; | ||||
| 	unsigned int clk_audio_dividers_count; | ||||
| 	struct clk_hw_onecell_data *hw_onecell_data; | ||||
| }; | ||||
| 
 | ||||
| static const struct clkc_data gxbb_clkc_data = { | ||||
| 	.clk_plls = gxbb_clk_plls, | ||||
| 	.clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), | ||||
| 	.clk_audio_dividers = gxbb_audio_dividers, | ||||
| 	.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), | ||||
| 	.hw_onecell_data = &gxbb_hw_onecell_data, | ||||
| }; | ||||
| 
 | ||||
| static const struct clkc_data gxl_clkc_data = { | ||||
| 	.clk_plls = gxl_clk_plls, | ||||
| 	.clk_plls_count = ARRAY_SIZE(gxl_clk_plls), | ||||
| 	.clk_audio_dividers = gxbb_audio_dividers, | ||||
| 	.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), | ||||
| 	.hw_onecell_data = &gxl_hw_onecell_data, | ||||
| }; | ||||
| 
 | ||||
| @ -1981,10 +1973,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) | ||||
| 	for (i = 0; i < clkc_data->clk_plls_count; i++) | ||||
| 		clkc_data->clk_plls[i]->base = clk_base; | ||||
| 
 | ||||
| 	/* Populate base address for the audio dividers */ | ||||
| 	for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) | ||||
| 		clkc_data->clk_audio_dividers[i]->base = clk_base; | ||||
| 
 | ||||
| 	/* Populate regmap for the common regmap backed clocks */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) | ||||
| 		gx_clk_regmaps[i]->map = map; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user