예제 #1
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);
}
예제 #2
0
static unsigned long sunxi_clk_factors_recalc_rate(struct clk_hw *hw, 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->calc_rate)
		return 0;

	if(factor->lock)
		spin_lock_irqsave(factor->lock, flags);
	reg = factor_readl(factor,factor->reg);
	if(factor->lock)
		spin_unlock_irqrestore(factor->lock, flags);

	if(config->nwidth)
		factor_val.factorn = GET_BITS(config->nshift, config->nwidth, reg);
	else
		factor_val.factorn = 0xffff;

	if(config->kwidth)
		factor_val.factork = GET_BITS(config->kshift, config->kwidth, reg);
	else
		factor_val.factork = 0xffff;

	if(config->mwidth)
		factor_val.factorm = GET_BITS(config->mshift, config->mwidth, reg);
	else
		factor_val.factorm = 0xffff;

	if(config->pwidth)
		factor_val.factorp = GET_BITS(config->pshift, config->pwidth, reg);
	else
		factor_val.factorp = 0xffff;

	if(config->d1width)
		factor_val.factord1 = GET_BITS(config->d1shift, config->d1width, reg);
	else
		factor_val.factord1 = 0xffff;

	if(config->d2width)
		factor_val.factord2 = GET_BITS(config->d2shift, config->d2width, reg);
	else
		factor_val.factord2 = 0xffff;

	if(config->frac) {
		factor_val.frac_mode = GET_BITS(config->modeshift, 1, reg);
		factor_val.frac_freq = GET_BITS(config->outshift, 1, reg);
	} else {
		factor_val.frac_mode = 0xffff;
		factor_val.frac_freq = 0xffff;
	}

	return factor->calc_rate(parent_rate, &factor_val);
}
예제 #3
0
static int sunxi_clk_fators_is_enabled(struct clk_hw *hw)
{
    unsigned long val;
	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);

    val = GET_BITS(config->enshift, 1, reg);
    return val ? 1 : 0;
}
예제 #4
0
static long sunxi_clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
{
	struct clk_factors_value factor_val;
	struct sunxi_clk_factors *factor = to_clk_factor(hw);

	if(!factor->get_factors || !factor->calc_rate)
		return rate;

	factor->get_factors(rate, *prate, &factor_val);
	return factor->calc_rate(*prate, &factor_val);
}
예제 #5
0
static void clk_disable_pll_mipi(struct clk_hw *hw)
{
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
    struct sunxi_clk_factors_config *config = factor->config;
    unsigned long reg = readl(factor->reg);

    if(config->sdmwidth)
        reg = SET_BITS(config->sdmshift, config->sdmwidth, reg, 0);
    reg = SET_BITS(config->enshift, 1, reg, 0);
    reg &= ~(0x3 << 22);
    writel(reg, factor->reg);
}
예제 #6
0
int set_parent_pll_mipi(struct clk_hw *hw, u8 index)
{
    unsigned long reg;
	struct sunxi_clk_factors *factor = to_clk_factor(hw);

    if(!factor->reg)
        return 0;
    reg = readl(factor->reg);
    reg = SET_BITS(21, 1, reg, index);
    writel(reg, factor->reg);
    return 0;
}
예제 #7
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);
}
예제 #8
0
u8 get_parent_pll_mipi(struct clk_hw *hw)
{
    u8 parent;
    unsigned long reg;
	struct sunxi_clk_factors *factor = to_clk_factor(hw);

    if(!factor->reg)
        return 0;
    reg = readl(factor->reg);
    parent = GET_BITS(21, 1, reg);

    return parent;
}
예제 #9
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;
}
예제 #10
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;
}
예제 #11
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;
}
예제 #12
0
static int sunxi_clk_fators_is_enabled(struct clk_hw *hw)
{
	unsigned long val;
	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->lock)
		spin_lock_irqsave(factor->lock, flags);

	reg = factor_readl(factor,factor->reg);
	val = GET_BITS(config->enshift, 1, reg);

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

	return val ? 1 : 0;
}
예제 #13
0
static int __init sunxi_clk_default_sdm(void)
{
#ifdef SYS_CONFIG_PAT_EN
	struct clk *clk = NULL;
    script_item_u   script_item;
	struct sunxi_clk_factors *factor=NULL;
    int i;
    unsigned long reg;
    for(i=0;i<sizeof(clkpat_table)/sizeof(struct sunxi_clk_pat_item);i++)
    {
        if((script_get_item("clock", clkpat_table[i].patname, &script_item) == SCIRPT_ITEM_VALUE_TYPE_INT))
           {
             clk = clk_get(NULL,clkpat_table[i].name);
             if(!IS_ERR_OR_NULL(clk))
             {
                factor = to_clk_factor(clk->hw);
                if(script_item.val)
                {
                    factor->config->sdmwidth = 1;
#ifdef SYS_CONFIG_PAT_VAL
                        if(script_item.val != 1)    //avoid old format usage to only enable
                            factor->config->sdmval=script_item.val;
#endif
                    //sync with already enable PLLs
                    if (clk->enable_count && __clk_is_enabled(clk))
                    {
                        reg = readl(factor->reg);
                        writel(factor->config->sdmval, (void __iomem *)factor->config->sdmpat);
                        reg = SET_BITS(factor->config->sdmshift, factor->config->sdmwidth, reg, 1);
                        writel(reg, factor->reg);
                    }
                }
                else
                    factor->config->sdmwidth = 0;
                clk_put(clk);
                clk=NULL;
             }
          }
     }
#endif
    return 0;
}
예제 #14
0
static int clk_enable_pll_mipi(struct clk_hw *hw)
{
	struct sunxi_clk_factors *factor = to_clk_factor(hw);
    struct sunxi_clk_factors_config *config = factor->config;
    unsigned long reg = readl(factor->reg);

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

    reg |= 0x3 << 22;
    writel(reg, factor->reg);
    udelay(100);

    reg = SET_BITS(config->enshift, 1, reg, 1);
    writel(reg, factor->reg);
    udelay(100);

    return 0;
}
예제 #15
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;
}
예제 #16
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;
}