linux/arch/arm/mach-omap2/dpll44xx.c

152 lines
3.6 KiB
C
Raw Normal View History

/*
* OMAP4-specific DPLL control functions
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Rajendra Nayak
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/bitops.h>
ARM: OMAP: Split plat/hardware.h, use local soc.h for omap2+ As the plat and mach includes need to disappear for single zImage work, we need to remove plat/hardware.h. Do this by splitting plat/hardware.h into omap1 and omap2+ specific files. The old plat/hardware.h already has omap1 only defines, so it gets moved to mach/hardware.h for omap1. For omap2+, we use the local soc.h that for now just includes the related SoC headers to keep this patch more readable. Note that the local soc.h still includes plat/cpu.h that can be dealt with in later patches. Let's also include plat/serial.h from common.h for all the board-*.c files. This allows making the include files local later on without patching these files again. Note that only minimal changes are done in this patch for the drivers/watchdog/omap_wdt.c driver to keep things compiling. Further patches are needed to eventually remove cpu_is_omap usage in the drivers. Also only minimal changes are done to sound/soc/omap/* to remove the unneeded includes and to define OMAP44XX_MCPDM_L3_BASE locally so there's no need to include omap44xx.h. While at it, also sort some of the includes in the standard way. Cc: linux-watchdog@vger.kernel.org Cc: alsa-devel@alsa-project.org Cc: Peter Ujfalusi <peter.ujfalusi@ti.com> Cc: Jarkko Nikula <jarkko.nikula@bitmer.com> Cc: Liam Girdwood <lrg@ti.com> Acked-by: Wim Van Sebroeck <wim@iguana.be> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
2012-09-01 01:59:07 +08:00
#include "soc.h"
#include "clock.h"
#include "clock44xx.h"
#include "cm-regbits-44xx.h"
/* Supported only on OMAP4 */
int omap4_dpllmx_gatectrl_read(struct clk *clk)
{
u32 v;
u32 mask;
if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
return -EINVAL;
mask = clk->flags & CLOCK_CLKOUTX2 ?
OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
v = __raw_readl(clk->clksel_reg);
v &= mask;
v >>= __ffs(mask);
return v;
}
void omap4_dpllmx_allow_gatectrl(struct clk *clk)
{
u32 v;
u32 mask;
if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
return;
mask = clk->flags & CLOCK_CLKOUTX2 ?
OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
v = __raw_readl(clk->clksel_reg);
/* Clear the bit to allow gatectrl */
v &= ~mask;
__raw_writel(v, clk->clksel_reg);
}
void omap4_dpllmx_deny_gatectrl(struct clk *clk)
{
u32 v;
u32 mask;
if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
return;
mask = clk->flags & CLOCK_CLKOUTX2 ?
OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
v = __raw_readl(clk->clksel_reg);
/* Set the bit to deny gatectrl */
v |= mask;
__raw_writel(v, clk->clksel_reg);
}
const struct clkops clkops_omap4_dpllmx_ops = {
.allow_idle = omap4_dpllmx_allow_gatectrl,
.deny_idle = omap4_dpllmx_deny_gatectrl,
};
/**
* omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
* @clk: struct clk * of the DPLL to compute the rate for
*
* Compute the output rate for the OMAP4 DPLL represented by @clk.
* Takes the REGM4XEN bit into consideration, which is needed for the
* OMAP4 ABE DPLL. Returns the DPLL's output rate (before M-dividers)
* upon success, or 0 upon error.
*/
unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
{
u32 v;
unsigned long rate;
struct dpll_data *dd;
if (!clk || !clk->dpll_data)
return 0;
dd = clk->dpll_data;
rate = omap2_get_dpll_rate(clk);
/* regm4xen adds a multiplier of 4 to DPLL calculations */
v = __raw_readl(dd->control_reg);
if (v & OMAP4430_DPLL_REGM4XEN_MASK)
rate *= OMAP4430_REGM4XEN_MULT;
return rate;
}
/**
* omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
* @clk: struct clk * of the DPLL to round a rate for
* @target_rate: the desired rate of the DPLL
*
* Compute the rate that would be programmed into the DPLL hardware
* for @clk if set_rate() were to be provided with the rate
* @target_rate. Takes the REGM4XEN bit into consideration, which is
* needed for the OMAP4 ABE DPLL. Returns the rounded rate (before
* M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
* ~0 if an error occurred in omap2_dpll_round_rate().
*/
long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
{
u32 v;
struct dpll_data *dd;
long r;
if (!clk || !clk->dpll_data)
return -EINVAL;
dd = clk->dpll_data;
/* regm4xen adds a multiplier of 4 to DPLL calculations */
v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
if (v)
target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
r = omap2_dpll_round_rate(clk, target_rate);
if (r == ~0)
return r;
if (v)
clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
return clk->dpll_data->last_rounded_rate;
}