Example #1
0
static int sunxi_clk_disable_plllock(struct sunxi_clk_factors *factor)
{
	volatile u32 reg;

	switch (factor->lock_mode) {
		case PLL_LOCK_NEW_MODE:
		case PLL_LOCK_OLD_MODE: {
			/* make sure pll new mode is disable */
			reg = factor_readl(factor,factor->pll_lock_ctrl_reg);
			reg = SET_BITS(factor->lock_en_bit, 1, reg, 0);
			factor_writel(factor,reg, factor->pll_lock_ctrl_reg);

			reg = factor_readl(factor, factor->pll_lock_ctrl_reg);
			reg = SET_BITS(28, 1, reg, 0);
			factor_writel(factor, reg, factor->pll_lock_ctrl_reg);

			return 0;
		}
		case PLL_LOCK_NONE_MODE: {
			return 0;
		}
		default: {
			WARN(1, "invaid pll lock mode:%u\n", factor->lock_mode);
			return -1;
		}
	}

}
Example #2
0
static int sunxi_clk_fators_enable(struct clk_hw *hw)
{
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
    struct sunxi_clk_factors_config *config = factor->config;
    unsigned long reg = factor_readl(factor,factor->reg);

    if(config->sdmwidth)
    {
        factor_writel(factor,config->sdmval, (void __iomem *)config->sdmpat);
        reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 1);
    }
    reg = SET_BITS(config->enshift, 1, reg, 1);
    factor_writel(factor,reg, factor->reg);
    return 0;
}
Example #3
0
static void sunxi_clk_fators_disable(struct clk_hw *hw)
{
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
	struct sunxi_clk_factors_config *config = factor->config;
	unsigned long reg;
	unsigned long flags = 0;

	if(factor->flags & CLK_IGNORE_DISABLE)
		return;

	/* check if the pll disabled already */
	reg = factor_readl(factor, factor->reg);
	if(!GET_BITS(config->enshift, 1, reg))
		return;

	if(factor->lock)
		spin_lock_irqsave(factor->lock, flags);

	reg = factor_readl(factor, factor->reg);
	if(config->sdmwidth)
		reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 0);
	/* update for pll_ddr register */
	if(config->updshift)
		reg = SET_BITS(config->updshift, 1, reg, 1);
	/* disable pll */
	reg = SET_BITS(config->enshift, 1, reg, 0);
	factor_writel(factor,reg, factor->reg);

	/* disable pll lock if needed */
	sunxi_clk_disable_plllock(factor);

	if(factor->lock)
		spin_unlock_irqrestore(factor->lock, flags);
}
Example #4
0
static int sunxi_clk_fators_enable(struct clk_hw *hw)
{
    struct sunxi_clk_factors *factor = to_clk_factor(hw);
    struct sunxi_clk_factors_config *config = factor->config;
    unsigned long reg = factor_readl(factor,factor->reg);
    unsigned int loop = 300;
    unsigned long flags = 0;

    if(factor->lock)
        spin_lock_irqsave(factor->lock, flags);

    if(config->sdmwidth)
    {
        factor_writel(factor,config->sdmval, (void __iomem *)config->sdmpat);
        reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 1);
    }

    //enable the register
    reg = SET_BITS(config->enshift, 1, reg, 1);

    if(config->updshift) //update for pll_ddr register
        reg = SET_BITS(config->updshift, 1, reg, 1);

    factor_writel(factor,reg, factor->reg);

    while(loop--)
    {
        reg = factor_readl(factor,factor->lock_reg);
        if(GET_BITS(factor->lock_bit, 1, reg))
             break;
        else
            udelay(10);
    }

    if(factor->lock)
        spin_unlock_irqrestore(factor->lock, flags);

    if(!loop)
#if (defined CONFIG_FPGA_V4_PLATFORM) || (defined CONFIG_FPGA_V7_PLATFORM)
    printk("clk %s wait lock timeout\n",hw->clk->name);
#else
    WARN(1, "clk %s wait lock timeout\n",hw->clk->name);
#endif
    return 0;
}
Example #5
0
static int sunxi_clk_fators_enable(struct clk_hw *hw)
{
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
	struct sunxi_clk_factors_config *config = factor->config;
	unsigned long reg;
	unsigned long flags = 0;

	/* check if the pll enabled already */
	reg = factor_readl(factor, factor->reg);
	if(GET_BITS(config->enshift, 1, reg))
		return 0;

	if(factor->lock)
		spin_lock_irqsave(factor->lock, flags);

	sunxi_clk_disable_plllock(factor);

	/* get factor register value */
	reg = factor_readl(factor, factor->reg);
	if(config->sdmwidth)
	{
		factor_writel(factor, config->sdmval, (void __iomem *)config->sdmpat);
		reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 1);
	}
	/* enable the register */
	reg = SET_BITS(config->enshift, 1, reg, 1);
	/* update for pll_ddr register */
	if(config->updshift)
		reg = SET_BITS(config->updshift, 1, reg, 1);

	factor_writel(factor,reg, factor->reg);

	if (sunxi_clk_is_lock(factor)) {
		if(factor->lock)
			spin_unlock_irqrestore(factor->lock, flags);
		WARN(1, "clk %s wait lock timeout\n", factor->hw.clk->name);
		return -1;
	}

	if(factor->lock)
		spin_unlock_irqrestore(factor->lock, flags);

		return 0;
}
Example #6
0
static void sunxi_clk_fators_disable(struct clk_hw *hw)
{
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
    struct sunxi_clk_factors_config *config = factor->config;
    unsigned long reg = factor_readl(factor,factor->reg);

    if(config->sdmwidth)
        reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 0);

    reg = SET_BITS(config->enshift, 1, reg, 0);
    factor_writel(factor,reg, factor->reg);
}
Example #7
0
static int sunxi_clk_is_lock(struct sunxi_clk_factors *factor)
{
	volatile u32 reg;
	u32 loop = 5000;

	switch (factor->lock_mode) {
		case PLL_LOCK_NEW_MODE: {
			/* enable pll new mode */
			reg = factor_readl(factor, factor->pll_lock_ctrl_reg);
			reg = SET_BITS(28, 1, reg, 1);
			factor_writel(factor, reg, factor->pll_lock_ctrl_reg);

			reg = factor_readl(factor, factor->pll_lock_ctrl_reg);
			reg = SET_BITS(factor->lock_en_bit, 1, reg, 1);
			factor_writel(factor, reg, factor->pll_lock_ctrl_reg);

			while(loop--) {
				reg = factor_readl(factor,factor->lock_reg);
				if(GET_BITS(factor->lock_bit, 1, reg)) {
					udelay(20);
					break;
				} else {
					udelay(1);
				}
			}

			reg = factor_readl(factor,factor->pll_lock_ctrl_reg);
			reg = SET_BITS(factor->lock_en_bit, 1, reg, 0);
			factor_writel(factor,reg, factor->pll_lock_ctrl_reg);

			reg = factor_readl(factor, factor->pll_lock_ctrl_reg);
			reg = SET_BITS(28, 1, reg, 0);
			factor_writel(factor, reg, factor->pll_lock_ctrl_reg);

			if(!loop) {
#if (defined CONFIG_FPGA_V4_PLATFORM) || (defined CONFIG_FPGA_V7_PLATFORM)
				printk("clk %s wait lock timeout\n", factor->hw.clk->name);
				return 0;
#else
				WARN(1, "clk %s wait lock timeout\n", factor->hw.clk->name);
				return -1;
#endif
			}
			return 0;
		}
		case PLL_LOCK_OLD_MODE:
		case PLL_LOCK_NONE_MODE: {
			while(loop--) {
				reg = factor_readl(factor,factor->lock_reg);
				if(GET_BITS(factor->lock_bit, 1, reg)) {
					udelay(20);
					break;
				} else {
					udelay(1);
				}
			}

			if(!loop) {
#if (defined CONFIG_FPGA_V4_PLATFORM) || (defined CONFIG_FPGA_V7_PLATFORM)
				printk("clk %s wait lock timeout\n", factor->hw.clk->name);
#else
				WARN(1, "clk %s wait lock timeout\n", factor->hw.clk->name);
				return -1;
#endif
			}
			return 0;
		}
		default: {
			WARN(1, "invaid pll lock mode:%u\n", factor->lock_mode);
			return -1;
		}
	}
}
Example #8
0
static int sunxi_clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
{
	unsigned long reg;
	struct clk_factors_value factor_val;
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
	struct sunxi_clk_factors_config *config = factor->config;
	unsigned long flags = 0;

	if(!factor->get_factors)
		return 0;

	/* factor_val is initialized with its original value,
	 * it's factors(such as:M,N,K,P,d1,d2...) are Random Value.
	 * if donot judge the return value of "factor->get_factors",
	 * it may change the original register value.
	 */
	if(factor->get_factors(rate, parent_rate, &factor_val) < 0)
	{
		/* cannot get right factors for clk,just break */
		WARN(1, "clk %s set rate failed! Because cannot get right factors for clk\n", hw->clk->name);
		return 0;
	}

	if(factor->flags & CLK_RATE_FLAT_FACTORS)
		return sunxi_clk_factors_set_flat_facotrs(factor, &factor_val);

	if(factor->lock)
		spin_lock_irqsave(factor->lock, flags);

	sunxi_clk_disable_plllock(factor);

	reg = factor_readl(factor, factor->reg);
	if(config->sdmwidth)
	{
		factor_writel(factor, config->sdmval, (void __iomem *)config->sdmpat);
		reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 1);
	}
	if(config->nwidth)
		reg = SET_BITS(config->nshift, config->nwidth, reg, factor_val.factorn);
	if(config->kwidth)
		reg = SET_BITS(config->kshift, config->kwidth, reg, factor_val.factork);
	if(config->mwidth)
		reg = SET_BITS(config->mshift, config->mwidth, reg, factor_val.factorm);
	if(config->pwidth)
		reg = SET_BITS(config->pshift, config->pwidth, reg, factor_val.factorp);
	if(config->d1width)
		reg = SET_BITS(config->d1shift, config->d1width, reg, factor_val.factord1);
	if(config->d2width)
		reg = SET_BITS(config->d2shift, config->d2width, reg, factor_val.factord2);
	if(config->frac) {
		reg = SET_BITS(config->modeshift, 1, reg, factor_val.frac_mode);
		reg = SET_BITS(config->outshift, 1, reg, factor_val.frac_freq);
	}
	if(config->updshift) //update for pll_ddr register
		reg = SET_BITS(config->updshift, 1, reg, 1);
	factor_writel(factor,reg, factor->reg);

#ifndef CONFIG_SUNXI_CLK_DUMMY_DEBUG
	if(GET_BITS(config->enshift, 1, reg)) {
		if (sunxi_clk_is_lock(factor)) {
			if(factor->lock)
				spin_unlock_irqrestore(factor->lock, flags);
			WARN(1, "clk %s wait lock timeout\n", factor->hw.clk->name);
			return -1;
		}
	}
#endif

	if(factor->lock)
		spin_unlock_irqrestore(factor->lock, flags);

	return 0;
}
Example #9
0
static int sunxi_clk_factors_set_flat_facotrs(struct sunxi_clk_factors *factor,
				struct clk_factors_value *values)
{
	struct sunxi_clk_factors_config *config = factor->config;
	u32 reg, tmp_factor_p, tmp_factor_m;
	unsigned long flags = 0;


	if(factor->lock)
		spin_lock_irqsave(factor->lock, flags);

	sunxi_clk_disable_plllock(factor);

	/*get all factors from the regitsters*/
	reg = factor_readl(factor,factor->reg);
	tmp_factor_p = config->pwidth ? GET_BITS(config->pshift, config->pwidth, reg) : 0 ;
	tmp_factor_m = config->mwidth ? GET_BITS(config->mshift, config->mwidth, reg) : 0 ;

	/* 1).try to increase factor p first */
	if(config->pwidth && (tmp_factor_p < values->factorp))
	{
		reg = factor_readl(factor, factor->reg);
		reg = SET_BITS(config->pshift, config->pwidth, reg, values->factorp);
		factor_writel(factor,reg, factor->reg);
		if(factor->flags & CLK_RATE_FLAT_DELAY)
			udelay(config->delay);
	}

	/* 2).try to increase factor m first */
	if(config->mwidth && (tmp_factor_m < values->factorm))
	{
		reg = factor_readl(factor, factor->reg);
		reg = SET_BITS( config->mshift, config->mwidth, reg, values->factorm );
		factor_writel(factor, reg, factor->reg);
		if(factor->flags & CLK_RATE_FLAT_DELAY)
			udelay(config->delay);
	}

	/* 3. write factor n & k */
	reg = factor_readl(factor, factor->reg);
	if(config->nwidth)
		reg = SET_BITS(config->nshift, config->nwidth, reg, values->factorn);
	if(config->kwidth)
		reg = SET_BITS(config->kshift, config->kwidth, reg, values->factork);
	factor_writel(factor,reg, factor->reg);

	/* 4. do pair things for 2). decease factor m */
	if(config->mwidth && (tmp_factor_m > values->factorm))
	{
		reg = factor_readl(factor, factor->reg);
		reg = SET_BITS(config->mshift, config->mwidth, reg, values->factorm);
		factor_writel(factor, reg, factor->reg);
		if( factor->flags & CLK_RATE_FLAT_DELAY)
			udelay(config->delay);
	}

	/* 5. wait for PLL state stable */
	if (sunxi_clk_is_lock(factor)) {
		if(factor->lock)
			spin_unlock_irqrestore(factor->lock, flags);
		WARN(1, "clk %s wait lock timeout\n", factor->hw.clk->name);
		return -1;
	}

	/*6.do pair things for 1).  decease factor p */
	if(config->pwidth && (tmp_factor_p > values->factorp))
	{
		reg = factor_readl(factor, factor->reg);
		reg = SET_BITS(config->pshift, config->pwidth, reg, values->factorp);
		factor_writel(factor,reg, factor->reg);
		if(factor->flags & CLK_RATE_FLAT_DELAY)
			udelay(config->delay);
	}

	if(factor->lock)
		spin_unlock_irqrestore(factor->lock, flags);

	return 0;
}
Example #10
0
static int sunxi_clk_factors_set_flat_facotrs(struct sunxi_clk_factors *factor , struct clk_factors_value *values)
{
    struct sunxi_clk_factors_config *config = factor->config;
    u32 reg, tmp_factor_p, tmp_factor_m;
    unsigned long flags = 0;

#ifdef CONFIG_EVB_PLATFORM
    unsigned int loop = 300; /*lock loops*/
#endif

    if(factor->lock)
        spin_lock_irqsave(factor->lock, flags);

    /*get all factors from the regitsters*/
    reg = factor_readl(factor,factor->reg);
    tmp_factor_p = config->pwidth ? GET_BITS( config->pshift , config->pwidth , reg) : 0 ;
    tmp_factor_m = config->mwidth ? GET_BITS( config->mshift , config->mwidth , reg) : 0 ;

    /* 1).try to increase factor p first */
    if( config->pwidth && tmp_factor_p < values->factorp )
    {
        reg = SET_BITS( config->pshift , config->pwidth , reg , values->factorp );
        factor_writel(factor,reg, factor->reg);
        if( factor->flags & CLK_RATE_FLAT_DELAY)
            udelay(config->delay);
    }
    /* 2).try to increase factor m first */
    if( config->mwidth && tmp_factor_m < values->factorm )
    {
        reg = SET_BITS( config->mshift , config->mwidth , reg, values->factorm );
        factor_writel(factor,reg, factor->reg);
        if( factor->flags & CLK_RATE_FLAT_DELAY)
            udelay(config->delay);
    }

    /* 3. write factor n & k */
    if( config->nwidth )
        reg = SET_BITS( config->nshift , config->nwidth , reg, values->factorn );

    if( config->kwidth )
        reg = SET_BITS( config->kshift , config->kwidth , reg, values->factork );

    factor_writel(factor,reg, factor->reg);
    /* 4. do pair things for 2). decease factor m */
    if( config->mwidth && tmp_factor_m > values->factorm)
    {
        reg = SET_BITS( config->mshift , config->mwidth , reg, values->factorm );
        factor_writel(factor,reg, factor->reg);
        if( factor->flags & CLK_RATE_FLAT_DELAY)
            udelay(config->delay);
    }

    /* 5. wait for PLL state stable */
#ifdef CONFIG_EVB_PLATFORM
    while(loop--)
    {
        u32 reg_val = factor_readl(factor,factor->lock_reg);
        if(GET_BITS(factor->lock_bit, 1, reg_val))
             break;
        else
            udelay(10);
    }

    if(!loop)
#if (defined CONFIG_FPGA_V4_PLATFORM) || (defined CONFIG_FPGA_V7_PLATFORM)
        printk("clk %s wait lock timeout\n",factor->hw.clk->name);
#else
        WARN(1, "clk %s wait lock timeout\n",factor->hw.clk->name);
#endif

#endif

    /*6.do pair things for 1).  decease factor p */
    if( config->pwidth && tmp_factor_p > values->factorp )
    {
        reg = SET_BITS( config->pshift , config->pwidth , reg, values->factorp );
        factor_writel(factor,reg, factor->reg);
        if( factor->flags & CLK_RATE_FLAT_DELAY)
            udelay(config->delay);
    }

    if(factor->lock)
        spin_unlock_irqrestore(factor->lock, flags);

    return 0;
}
Example #11
0
static int sunxi_clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
{
    unsigned long reg;
    struct clk_factors_value factor_val;
    unsigned long orig_jiffies;
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
    struct sunxi_clk_factors_config *config = factor->config;

    if(!factor->get_factors)
        return 0;

    factor->get_factors(rate, parent_rate, &factor_val);

    reg = factor_readl(factor,factor->reg);

    if(config->sdmwidth)
    {
        factor_writel(factor,config->sdmval, (void __iomem *)config->sdmpat);
        reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 1);
    }

    if(config->nwidth)
        reg = SET_BITS(config->nshift, config->nwidth, reg, factor_val.factorn);

    if(config->kwidth)
        reg = SET_BITS(config->kshift, config->kwidth, reg, factor_val.factork);

    if(config->mwidth)
        reg = SET_BITS(config->mshift, config->mwidth, reg, factor_val.factorm);

    if(config->pwidth)
        reg = SET_BITS(config->pshift, config->pwidth, reg, factor_val.factorp);

    if(config->d1width)
        reg = SET_BITS(config->d1shift, config->d1width, reg, factor_val.factord1);

    if(config->d2width)
        reg = SET_BITS(config->d2shift, config->d2width, reg, factor_val.factord2);

    if(config->frac) {
        reg = SET_BITS(config->modeshift, 1, reg, factor_val.frac_mode);
        reg = SET_BITS(config->outshift, 1, reg, factor_val.frac_freq);
    }
    factor_writel(factor,reg, factor->reg);
#ifndef CONFIG_SUNXI_CLK_DUMMY_DEBUG
    orig_jiffies = jiffies;
    if(GET_BITS(config->enshift, 1, reg))
    {
    		while(1)
    		{
                    reg = factor_readl(factor,factor->lock_reg);
    				if(GET_BITS(factor->lock_bit, 1, reg))
                        break;
                    if(time_after(jiffies, orig_jiffies + msecs_to_jiffies(500)))
                    {
#if (defined CONFIG_FPGA_V4_PLATFORM) || (defined CONFIG_FPGA_V7_PLATFORM)
                        printk("clk %s wait lock timeout\n",hw->clk->name);
#else
                        WARN(1, "clk %s wait lock timeout\n",hw->clk->name);
#endif
                        break;
                    }
            }
    }
#endif
    return 0;
}