Beispiel #1
0
static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
{
	struct clk_gate *gate = to_clk_gate(hw);
	u32 val;

	/*
	 * Divider field is write only, so divider stat field must
	 * be read so divider field can be set accordingly.
	 */
	val = clk_readl(gate->reg);
	if (val & LPC18XX_CCU_DIVSTAT)
		val |= LPC18XX_CCU_DIV;

	if (enable) {
		val |= LPC18XX_CCU_RUN;
	} else {
		/*
		 * To safely disable a branch clock a squence of two separate
		 * writes must be used. First write should set the AUTO bit
		 * and the next write should clear the RUN bit.
		 */
		val |= LPC18XX_CCU_AUTO;
		clk_writel(val, gate->reg);

		val &= ~LPC18XX_CCU_RUN;
	}

	clk_writel(val, gate->reg);

	return 0;
}
static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
			   unsigned long parent_rate)
{
	struct clk_fractional_divider *fd = to_clk_fd(hw);
	unsigned long flags = 0;
	unsigned long m, n;
	u32 val;

	rational_best_approximation(rate, parent_rate,
			GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
			&m, &n);

	if (fd->lock)
		spin_lock_irqsave(fd->lock, flags);
#if 0
	else
		__acquire(fd->lock);
#endif

	val = clk_readl(fd->reg);
	val &= ~(fd->mmask | fd->nmask);
	val |= (m << fd->mshift) | (n << fd->nshift);
	clk_writel(val, fd->reg);

	if (fd->lock)
		spin_unlock_irqrestore(fd->lock, flags);
#if 0
	else
		__release(fd->lock);
#endif

	return 0;
}
/*
 * It works on following logic:
 *
 * For enabling clock, enable = 1
 *	set2dis = 1	-> clear bit	-> set = 0
 *	set2dis = 0	-> set bit	-> set = 1
 *
 * For disabling clock, enable = 0
 *	set2dis = 1	-> set bit	-> set = 1
 *	set2dis = 0	-> clear bit	-> set = 0
 *
 * So, result is always: enable xor set2dis.
 */
static void clk_gate_endisable(struct clk_hw *hw, int enable)
{
	struct clk_gate *gate = to_clk_gate(hw);
	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
	unsigned long uninitialized_var(flags);
	u32 reg;

	set ^= enable;

	if (gate->lock)
		spin_lock_irqsave(gate->lock, flags);
	else
		__acquire(gate->lock);

	if (gate->flags & CLK_GATE_HIWORD_MASK) {
		reg = BIT(gate->bit_idx + 16);
		if (set)
			reg |= BIT(gate->bit_idx);
	} else {
		reg = clk_readl(gate->reg);

		if (set)
			reg |= BIT(gate->bit_idx);
		else
			reg &= ~BIT(gate->bit_idx);
	}

	clk_writel(reg, gate->reg);

	if (gate->lock)
		spin_unlock_irqrestore(gate->lock, flags);
	else
		__release(gate->lock);
}
static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
			   unsigned long parent_rate)
{
	struct clk_fractional_divider *fd = to_clk_fd(hw);
	unsigned long flags = 0;
	unsigned long div;
	unsigned n, m;
	u32 val;

	div = gcd(parent_rate, rate);
	m = rate / div;
	n = parent_rate / div;

	if (fd->lock)
		spin_lock_irqsave(fd->lock, flags);
	else
		__acquire(fd->lock);

	val = clk_readl(fd->reg);
	val &= ~(fd->mmask | fd->nmask);
	val |= (m << fd->mshift) | (n << fd->nshift);
	clk_writel(val, fd->reg);

	if (fd->lock)
		spin_unlock_irqrestore(fd->lock, flags);
	else
		__release(fd->lock);

	return 0;
}
Beispiel #5
0
/* clk_m functions */
static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
{
	u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK;

	c->rate = clk_measure_input_freq();
	switch (c->rate) {
	case 12000000:
		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
		break;
	case 13000000:
		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
		break;
	case 19200000:
		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
		break;
	case 26000000:
		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
		break;
	default:
		pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
		BUG();
	}
	clk_writel(auto_clock_control, OSC_CTRL);
	return c->rate;
}
unsigned long tegra_clk_measure_input_freq(void)
{
	u32 clock_autodetect;

	if (osc_input_freq)
		return osc_input_freq;

	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);

	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3)
		osc_input_freq = 12000000;
	else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3)
		osc_input_freq = 13000000;
	else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3)
		osc_input_freq = 19200000;
	else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3)
		osc_input_freq = 26000000;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3)
		osc_input_freq = 16800000;
	else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3)
		osc_input_freq = 38400000;
	else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3)
		osc_input_freq = 48000000;
#endif
	else {
		pr_err("%s: Unexpected clock autodetect value %d", __func__,
			clock_autodetect);
		BUG();
	}
	return osc_input_freq;
}
static int cpg_div6_clock_enable(struct clk_hw *hw)
{
	struct div6_clock *clock = to_div6_clock(hw);

	clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg);

	return 0;
}
static void cpg_div6_clock_disable(struct clk_hw *hw)
{
	struct div6_clock *clock = to_div6_clock(hw);

	/* DIV6 clocks require the divisor field to be non-zero when stopping
	 * the clock.
	 */
	clk_writel(CPG_DIV6_CKSTP | CPG_DIV6_DIV(CPG_DIV6_DIV_MASK),
		   clock->reg);
}
static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
				   unsigned long parent_rate)
{
	struct div6_clock *clock = to_div6_clock(hw);
	unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate);

	clock->div = div;

	/* Only program the new divisor if the clock isn't stopped. */
	if (!(clk_readl(clock->reg) & CPG_DIV6_CKSTP))
		clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg);

	return 0;
}
Beispiel #10
0
static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
{
    struct mstp_clock *clock = to_mstp_clock(hw);
    struct cpg_mssr_priv *priv = clock->priv;
    unsigned int reg = clock->index / 32;
    unsigned int bit = clock->index % 32;
    struct device *dev = priv->dev;
    u32 bitmask = BIT(bit);
    unsigned long flags;
    unsigned int i;
    u32 value;

    dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
            enable ? "ON" : "OFF");
    spin_lock_irqsave(&priv->mstp_lock, flags);

    value = clk_readl(priv->base + SMSTPCR(reg));
    if (enable)
        value &= ~bitmask;
    else
        value |= bitmask;
    clk_writel(value, priv->base + SMSTPCR(reg));

    spin_unlock_irqrestore(&priv->mstp_lock, flags);

    if (!enable)
        return 0;

    for (i = 1000; i > 0; --i) {
        if (!(clk_readl(priv->base + MSTPSR(reg)) &
                bitmask))
            break;
        cpu_relax();
    }

    if (!i) {
        dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
                priv->base + SMSTPCR(reg), bit);
        return -ETIMEDOUT;
    }

    return 0;
}
Beispiel #11
0
unsigned long clk_measure_input_freq(void)
{
	u32 clock_autodetect;
	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
		return 12000000;
	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
		return 13000000;
	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
		return 19200000;
	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
		return 26000000;
	} else {
		pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect);
		BUG();
		return 0;
	}
}
Beispiel #12
0
static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
{
	struct mstp_clock *clock = to_mstp_clock(hw);
	struct mstp_clock_group *group = clock->group;
	u32 bitmask = BIT(clock->bit_index);
	unsigned long flags;
	unsigned int i;
	u32 value;

	spin_lock_irqsave(&group->lock, flags);

	value = clk_readl(group->smstpcr);
	if (enable)
		value &= ~bitmask;
	else
		value |= bitmask;
	clk_writel(value, group->smstpcr);

	spin_unlock_irqrestore(&group->lock, flags);

	if (!enable || !group->mstpsr)
		return 0;

	for (i = 1000; i > 0; --i) {
		if (!(clk_readl(group->mstpsr) & bitmask))
			break;
		cpu_relax();
	}

	if (!i) {
		pr_err("%s: failed to enable %p[%d]\n", __func__,
		       group->smstpcr, clock->bit_index);
		return -ETIMEDOUT;
	}

	return 0;
}