diff options
Diffstat (limited to 'drivers/clk/meson/clk-mpll.c')
| -rw-r--r-- | drivers/clk/meson/clk-mpll.c | 125 | 
1 files changed, 30 insertions, 95 deletions
| diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 5144360e2c80..0df1227b65b3 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -68,11 +68,15 @@  #define N2_MIN	4  #define N2_MAX	511 -#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) +static inline struct meson_clk_mpll_data * +meson_clk_mpll_data(struct clk_regmap *clk) +{ +	return (struct meson_clk_mpll_data *)clk->data; +}  static long rate_from_params(unsigned long parent_rate, -				      unsigned long sdm, -				      unsigned long n2) +			     unsigned int sdm, +			     unsigned int n2)  {  	unsigned long divisor = (SDM_DEN * n2) + sdm; @@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate,  static void params_from_rate(unsigned long requested_rate,  			     unsigned long parent_rate, -			     unsigned long *sdm, -			     unsigned long *n2) +			     unsigned int *sdm, +			     unsigned int *n2)  {  	uint64_t div = parent_rate;  	unsigned long rem = do_div(div, requested_rate); @@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate,  static unsigned long mpll_recalc_rate(struct clk_hw *hw,  		unsigned long parent_rate)  { -	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); -	struct parm *p; -	unsigned long reg, sdm, n2; +	struct clk_regmap *clk = to_clk_regmap(hw); +	struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); +	unsigned int sdm, n2;  	long rate; -	p = &mpll->sdm; -	reg = readl(mpll->base + p->reg_off); -	sdm = PARM_GET(p->width, p->shift, reg); - -	p = &mpll->n2; -	reg = readl(mpll->base + p->reg_off); -	n2 = PARM_GET(p->width, p->shift, reg); +	sdm = meson_parm_read(clk->map, &mpll->sdm); +	n2 = meson_parm_read(clk->map, &mpll->n2);  	rate = rate_from_params(parent_rate, sdm, n2); -	if (rate < 0) -		return 0; - -	return rate; +	return rate < 0 ? 0 : rate;  }  static long mpll_round_rate(struct clk_hw *hw,  			    unsigned long rate,  			    unsigned long *parent_rate)  { -	unsigned long sdm, n2; +	unsigned int sdm, n2;  	params_from_rate(rate, *parent_rate, &sdm, &n2);  	return rate_from_params(*parent_rate, sdm, n2); @@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw,  			 unsigned long rate,  			 unsigned long parent_rate)  { -	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); -	struct parm *p; -	unsigned long reg, sdm, n2; +	struct clk_regmap *clk = to_clk_regmap(hw); +	struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); +	unsigned int sdm, n2;  	unsigned long flags = 0;  	params_from_rate(rate, parent_rate, &sdm, &n2); @@ -151,97 +147,36 @@ static int mpll_set_rate(struct clk_hw *hw,  	else  		__acquire(mpll->lock); -	p = &mpll->sdm; -	reg = readl(mpll->base + p->reg_off); -	reg = PARM_SET(p->width, p->shift, reg, sdm); -	writel(reg, mpll->base + p->reg_off); - -	p = &mpll->sdm_en; -	reg = readl(mpll->base + p->reg_off); -	reg = PARM_SET(p->width, p->shift, reg, 1); -	writel(reg, mpll->base + p->reg_off); - -	p = &mpll->ssen; -	if (p->width != 0) { -		reg = readl(mpll->base + p->reg_off); -		reg = PARM_SET(p->width, p->shift, reg, 1); -		writel(reg, mpll->base + p->reg_off); -	} - -	p = &mpll->n2; -	reg = readl(mpll->base + p->reg_off); -	reg = PARM_SET(p->width, p->shift, reg, n2); -	writel(reg, mpll->base + p->reg_off); - -	if (mpll->lock) -		spin_unlock_irqrestore(mpll->lock, flags); -	else -		__release(mpll->lock); - -	return 0; -} +	/* Enable and set the fractional part */ +	meson_parm_write(clk->map, &mpll->sdm, sdm); +	meson_parm_write(clk->map, &mpll->sdm_en, 1); -static void mpll_enable_core(struct clk_hw *hw, int enable) -{ -	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); -	struct parm *p; -	unsigned long reg; -	unsigned long flags = 0; +	/* Set additional fractional part enable if required */ +	if (MESON_PARM_APPLICABLE(&mpll->ssen)) +		meson_parm_write(clk->map, &mpll->ssen, 1); -	if (mpll->lock) -		spin_lock_irqsave(mpll->lock, flags); -	else -		__acquire(mpll->lock); +	/* Set the integer divider part */ +	meson_parm_write(clk->map, &mpll->n2, n2); -	p = &mpll->en; -	reg = readl(mpll->base + p->reg_off); -	reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0); -	writel(reg, mpll->base + p->reg_off); +	/* Set the magic misc bit if required */ +	if (MESON_PARM_APPLICABLE(&mpll->misc)) +		meson_parm_write(clk->map, &mpll->misc, 1);  	if (mpll->lock)  		spin_unlock_irqrestore(mpll->lock, flags);  	else  		__release(mpll->lock); -} - - -static int mpll_enable(struct clk_hw *hw) -{ -	mpll_enable_core(hw, 1);  	return 0;  } -static void mpll_disable(struct clk_hw *hw) -{ -	mpll_enable_core(hw, 0); -} - -static int mpll_is_enabled(struct clk_hw *hw) -{ -	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); -	struct parm *p; -	unsigned long reg; -	int en; - -	p = &mpll->en; -	reg = readl(mpll->base + p->reg_off); -	en = PARM_GET(p->width, p->shift, reg); - -	return en; -} -  const struct clk_ops meson_clk_mpll_ro_ops = {  	.recalc_rate	= mpll_recalc_rate,  	.round_rate	= mpll_round_rate, -	.is_enabled	= mpll_is_enabled,  };  const struct clk_ops meson_clk_mpll_ops = {  	.recalc_rate	= mpll_recalc_rate,  	.round_rate	= mpll_round_rate,  	.set_rate	= mpll_set_rate, -	.enable		= mpll_enable, -	.disable	= mpll_disable, -	.is_enabled	= mpll_is_enabled,  }; | 
