Beispiel #1
0
static unsigned long sunxi_clk_periph_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
    unsigned long reg, flags = 0;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_div *divider = &periph->divider;
    unsigned long div, div_m = 0, div_n = 0;
    u64 rate = parent_rate;

    if(!divider->reg)
        return parent_rate;

	if(periph->lock)
    {
        spin_lock_irqsave(periph->lock, flags);
        reg = periph_readl(periph,divider->reg);
        if(divider->mwidth)
            div_m = GET_BITS(divider->mshift, divider->mwidth, reg);
        if(divider->nwidth)
            div_n = GET_BITS(divider->nshift, divider->nwidth, reg);
        div = (div_m+1)*(1<<div_n);
        do_div(rate, div);
        spin_unlock_irqrestore(periph->lock, flags);
    }
    else
    {
        reg = periph_readl(periph,divider->reg);
        if(divider->mwidth)
            div_m = GET_BITS(divider->mshift, divider->mwidth, reg);
        if(divider->nwidth)
            div_n = GET_BITS(divider->nshift, divider->nwidth, reg);
        div = (div_m+1)*(1<<div_n);
        do_div(rate, div);
    }
    return rate;
}
Beispiel #2
0
static int sunxi_clk_periph_set_parent(struct clk_hw *hw, u8 index)
{
    unsigned long reg, flags = 0;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);

    if(periph->flags & CLK_READONLY)
        return 0;
		
    if(!periph->mux.reg)
        return 0;
    if(periph->lock)
    {
        spin_lock_irqsave(periph->lock, flags);
        reg = periph_readl(periph,periph->mux.reg);
        reg = SET_BITS(periph->mux.shift, periph->mux.width, reg, index);
        periph_writel(periph,reg, periph->mux.reg);
        spin_unlock_irqrestore(periph->lock, flags);
    }
    else
    {
        reg = periph_readl(periph,periph->mux.reg);
        reg = SET_BITS(periph->mux.shift, periph->mux.width, reg, index);
        periph_writel(periph,reg, periph->mux.reg);
    }
    return 0;
}
Beispiel #3
0
static int __sunxi_clk_periph_is_enabled(struct clk_hw *hw)
{
    int state = 1;
    unsigned long reg;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_gate *gate = &periph->gate;

    /* enable bus gating */
    if(gate->bus) {
        reg = periph_readl(periph,gate->bus);
        state &= GET_BITS(gate->bus_shift, 1, reg);
    }

    /* enable module gating */
    if(gate->enable) {
        reg = periph_readl(periph,gate->enable);
        state &= GET_BITS(gate->enb_shift, 1, reg);
    }
    /* de-assert module */
    if(gate->reset) {
        reg = periph_readl(periph,gate->reset);
        state &= GET_BITS(gate->rst_shift, 1, reg);
    }

    /* enable dram gating */
    if(gate->dram) {
        reg = periph_readl(periph,gate->dram);
        state &= GET_BITS(gate->ddr_shift, 1, reg);
    }

    return state;
}
Beispiel #4
0
static int __sunxi_clk_periph_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
{
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_div *divider = &periph->divider;
    int i,j,m_max;
    int m=0,n=0;
    unsigned long cur_rate=0,new_rate=0;
    unsigned long cur_delta,new_delta;
    u32 reg;
    if(parent_rate == 4000000)
        m_max =1;
    else
        m_max = 8;
    for(i=0;i<m_max;i++)
        for(j=0;j<8;j++)
        {
            new_rate = parent_rate/(ac100_m_factor[i]*ac100_n_factor[j]);
            new_delta = (new_rate >rate)?(new_rate-rate):(rate-new_rate);
            cur_delta = (cur_rate >rate)?(cur_rate-rate):(rate-cur_rate);
            if(new_delta < cur_delta)
            {
                cur_rate = new_rate;
                m =i;
                n = j;
            }
        }
    reg = periph_readl(periph,divider->reg);
    if(divider->mwidth)
        reg = SET_BITS(divider->mshift, divider->mwidth, reg, m);
    if(divider->nwidth)
        reg = SET_BITS(divider->nshift, divider->nwidth, reg, n);
    periph_writel(periph,reg, divider->reg);
    return 0;
}
Beispiel #5
0
static int __sunxi_clk_periph_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
{
#ifdef NEW_RATE_CALULATE
    unsigned long i=0,factor_m=0,factor_n=0,found=0;
#endif
    unsigned long reg;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_div *divider = &periph->divider;
    unsigned long div, div_m = 0, div_n = 0;
    u64 tmp_rate = parent_rate;

	if(periph->flags & CLK_READONLY)
        return 0;
		
	if(!divider->reg)
		return 0;

    do_div(tmp_rate, rate);
    div = tmp_rate;
    if(!div)
        div_m = div_n =0;
    else {
        div_m = 1<<divider->mwidth;
        div_n = (1<<divider->nwidth)-1;
#ifndef NEW_RATE_CALULATE
        if(div < div_m) {
            div_m = div;
            div_n = 0;
        } else if((div < div_m*2) && (div_n > 0)){
            div_n = 1;
            div_m = div>>1;
        } else if((div < div_m*4) && (div_n > 1)){
static void clk_periph_disable(struct clk_hw *hw)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *gate_ops = periph->gate_ops;
	struct clk_hw *gate_hw = &periph->gate.hw;

	gate_ops->disable(gate_hw);
}
Beispiel #7
0
static int clk_periph_is_enabled(struct clk_hw *hw)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *gate_ops = periph->gate_ops;
	struct clk_hw *gate_hw = &periph->gate.hw;

	__clk_hw_set_clk(gate_hw, hw);

	return gate_ops->is_enabled(gate_hw);
}
static int clk_periph_set_parent(struct clk_hw *hw, u8 index)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *mux_ops = periph->mux_ops;
	struct clk_hw *mux_hw = &periph->mux.hw;

	mux_hw->clk = hw->clk;

	return mux_ops->set_parent(mux_hw, index);
}
static int clk_periph_enable(struct clk_hw *hw)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *gate_ops = periph->gate_ops;
	struct clk_hw *gate_hw = &periph->gate.hw;

	gate_hw->clk = hw->clk;

	return gate_ops->enable(gate_hw);
}
static u8 clk_periph_get_parent(struct clk_hw *hw)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *mux_ops = periph->mux_ops;
	struct clk_hw *mux_hw = &periph->mux.hw;

	mux_hw->clk = hw->clk;

	return mux_ops->get_parent(mux_hw);
}
static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long parent_rate)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *div_ops = periph->div_ops;
	struct clk_hw *div_hw = &periph->divider.hw;

	div_hw->clk = hw->clk;

	return div_ops->set_rate(div_hw, rate, parent_rate);
}
static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
				  unsigned long *prate)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *div_ops = periph->div_ops;
	struct clk_hw *div_hw = &periph->divider.hw;

	div_hw->clk = hw->clk;

	return div_ops->round_rate(div_hw, rate, prate);
}
Beispiel #13
0
static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *div_ops = periph->div_ops;
	struct clk_hw *div_hw = &periph->divider.hw;

	__clk_hw_set_clk(div_hw, hw);

	return div_ops->recalc_rate(div_hw, parent_rate);
}
Beispiel #14
0
static int sunxi_clk_periph_is_enabled(struct clk_hw *hw)
{
    int state = 0;
    unsigned long flags = 0;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);

    if(periph->lock)
    {
        spin_lock_irqsave(periph->lock, flags);
        state = __sunxi_clk_periph_is_enabled(hw);
        spin_unlock_irqrestore(periph->lock, flags);
    }
    else
        state = __sunxi_clk_periph_is_enabled(hw);    
    return state;
}
Beispiel #15
0
void tegra_periph_reset_assert(struct clk *c)
{
	struct clk_hw *hw = __clk_get_hw(c);
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	struct tegra_clk_periph_gate *gate;

	if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
		gate = to_clk_periph_gate(hw);
		if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
			WARN_ON(1);
			return;
		}
	} else {
		gate = &periph->gate;
	}

	tegra_periph_reset(gate, 1);
}
Beispiel #16
0
static void sunxi_clk_periph_disable(struct clk_hw *hw)
{
    unsigned long flags = 0;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);

    if(periph->flags & CLK_READONLY)
        return ;

    if(periph->lock)
    {
        spin_lock_irqsave(periph->lock, flags);
        __sunxi_clk_periph_disable(hw);
        spin_unlock_irqrestore(periph->lock, flags);
    }
    else
        __sunxi_clk_periph_disable(hw);    
    if(periph->com_gate)
        sunxi_clk_periph_disable_shared(periph);        
}
Beispiel #17
0
static u8 sunxi_clk_periph_get_parent(struct clk_hw *hw)
{
    u8 parent;
    unsigned long reg, flags = 0;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);

    if(!periph->mux.reg)
        return 0;
    if(periph->lock)
    {
        spin_lock_irqsave(periph->lock, flags);
        reg = periph_readl(periph,periph->mux.reg);
        parent = GET_BITS(periph->mux.shift, periph->mux.width, reg);
        spin_unlock_irqrestore(periph->lock, flags);
    }
    else
    {
        reg = periph_readl(periph,periph->mux.reg);
        parent = GET_BITS(periph->mux.shift, periph->mux.width, reg); 
    }
    return parent;
}
Beispiel #18
0
static unsigned long sunxi_ac100_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
    unsigned long reg;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_div *divider = &periph->divider;
    unsigned long div, div_m = 0, div_n = 0;
    u64 rate = parent_rate;
    if(!divider->reg)
        return parent_rate;

    reg = periph_readl(periph,divider->reg);
    if(divider->mwidth)
        div_m = GET_BITS(divider->mshift, divider->mwidth, reg);
    if(divider->nwidth)
        div_n = GET_BITS(divider->nshift, divider->nwidth, reg);
    if(reg & 0x100)
        div = ac100_m_factor[div_m]*ac100_n_factor[div_n];
    else
        div = ac100_n_factor[div_n];
    do_div(rate, div);
    return rate;
}
Beispiel #19
0
static int __sunxi_clk_periph_enable(struct clk_hw *hw)
{
    unsigned long reg;
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_gate *gate = &periph->gate;

    /* de-assert module */
    if(gate->reset && !(periph->flags & CLK_IGNORE_AUTORESET) && !IS_SHARE_RST_GATE(periph)) {
        reg = periph_readl(periph,gate->reset);
        reg = SET_BITS(gate->rst_shift, 1, reg, 1);
        periph_writel(periph,reg, gate->reset);
    }

    /* enable bus gating */
    if(gate->bus && !IS_SHARE_BUS_GATE(periph)) {
        reg = periph_readl(periph,gate->bus);
        reg = SET_BITS(gate->bus_shift, 1, reg, 1);
        periph_writel(periph,reg, gate->bus);
    }

    /* enable module gating */
    if(gate->enable&& !IS_SHARE_MOD_GATE(periph)) {
        reg = periph_readl(periph,gate->enable);
        if(periph->flags & CLK_REVERT_ENABLE)
            reg = SET_BITS(gate->enb_shift, 1, reg, 0);
        else
            reg = SET_BITS(gate->enb_shift, 1, reg, 1);
        periph_writel(periph,reg, gate->enable);
    }

    /* enable dram gating */
    if(gate->dram&& !IS_SHARE_MBUS_GATE(periph)) {
        reg = periph_readl(periph,gate->dram);
        reg = SET_BITS(gate->ddr_shift, 1, reg, 1);
        periph_writel(periph,reg, gate->dram);
    }

    return 0;
}
Beispiel #20
0
static long sunxi_clk_periph_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
{
    struct sunxi_clk_periph *periph = to_clk_periph(hw);
    struct sunxi_clk_periph_div *divider = &periph->divider;
#ifdef NEW_RATE_CALULATE
    unsigned long i=0,factor_m=0,factor_n=0,found=0;
#endif
    unsigned long div, div_m = 0, div_n = 0;
    u64 parent_rate = (*prate+rate/2-1);

    do_div(parent_rate, rate);
    div = parent_rate;
    if(!div)
        return *prate;

    parent_rate = *prate;
    div_m = 1<<divider->mwidth;
    if(divider->nwidth) {
        div_n = 1<<divider->nwidth;
        div_n = 1<<(div_n-1);
    } else
        div_n = 1;
#ifndef NEW_RATE_CALULATE
    if(div <= div_m) {
        do_div(parent_rate, div);
    } else if((div <= div_m*2) && (div_n >= 2)) {
        div &= ~(1<<0);
        do_div(parent_rate, div);
    } else if((div <= div_m*4) && (div_n >= 4)) {
        div &= ~(3<<0);
        do_div(parent_rate, div);
    } else if((div <= div_m*8) && (div_n >= 8)) {
        div &= ~(7<<0);
        do_div(parent_rate, div);
    } else if((div <= div_m*16) && (div_n >= 16)) {
        div &= ~(15<<0);
        do_div(parent_rate, div);
    } else if((div <= div_m*32) && (div_n >= 32)) {
        div &= ~(31<<0);
        do_div(parent_rate, div);
    } else if((div <= div_m*64) && (div_n >= 64)) {
        div &= ~(63<<0);
        do_div(parent_rate, div);
    } else if((div <= div_m*128) && (div_n >= 128)) {
        div &= ~(127<<0);
        do_div(parent_rate, div);
    } else {
        do_div(parent_rate, div_m*div_n);
    }
#else //NEW_RATE_CALULATE
    while(i < (1<<divider->nwidth))
    {
        if(div <= div_m)
        {
            factor_m = div-1;
            factor_n = i;
            do_div(parent_rate, (factor_m+1)*(1 << factor_n));
            found = 1;
            break;
        }
        div = div >>1;
        i++;

         if(!div)
        {
            factor_m = 0;
            factor_n = i;
            do_div(parent_rate, (factor_m+1)*(1 << factor_n));
            found = 1;
            break;
        }
    }
    if(!found)
    {
        factor_m = (div >div_m?div_m:div)-1;
        factor_n = (1<<divider->nwidth) -1;
        do_div(parent_rate, (factor_m+1)*(1 << factor_n));
    }
#endif
    return parent_rate;
}