ARM: tegra: clock: Refcount periph clock enables
Some peripheral clocks share enable bits. Refcount the enables so that calling clk_disable on one clock will not turn off another clock. Signed-off-by: Colin Cross <ccross@android.com> Acked-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
parent
9c7dc562cd
commit
78f379b574
|
@ -159,6 +159,12 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
|
|||
*/
|
||||
static DEFINE_SPINLOCK(clock_register_lock);
|
||||
|
||||
/*
|
||||
* Some peripheral clocks share an enable bit, so refcount the enable bits
|
||||
* in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
|
||||
*/
|
||||
static int tegra_periph_clk_enable_refcount[3 * 32];
|
||||
|
||||
#define clk_writel(value, reg) \
|
||||
__raw_writel(value, (u32)reg_clk_base + (reg))
|
||||
#define clk_readl(reg) \
|
||||
|
@ -952,8 +958,17 @@ static void tegra2_periph_clk_init(struct clk *c)
|
|||
static int tegra2_periph_clk_enable(struct clk *c)
|
||||
{
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int refcount;
|
||||
pr_debug("%s on clock %s\n", __func__, c->name);
|
||||
|
||||
spin_lock_irqsave(&clock_register_lock, flags);
|
||||
|
||||
refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
|
||||
|
||||
if (refcount > 1)
|
||||
goto out;
|
||||
|
||||
clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
|
||||
CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
|
||||
if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
|
||||
|
@ -966,15 +981,29 @@ static int tegra2_periph_clk_enable(struct clk *c)
|
|||
val |= 0x3 << 24;
|
||||
clk_writel(val, c->reg);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&clock_register_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra2_periph_clk_disable(struct clk *c)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s on clock %s\n", __func__, c->name);
|
||||
|
||||
clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
|
||||
CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
|
||||
spin_lock_irqsave(&clock_register_lock, flags);
|
||||
|
||||
if (c->refcnt)
|
||||
tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
|
||||
|
||||
if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
|
||||
clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
|
||||
CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
|
||||
|
||||
spin_unlock_irqrestore(&clock_register_lock, flags);
|
||||
}
|
||||
|
||||
static void tegra2_periph_clk_reset(struct clk *c, bool assert)
|
||||
|
@ -2076,7 +2105,6 @@ struct clk tegra_list_clks[] = {
|
|||
PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0),
|
||||
PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
|
||||
/* FIXME: spdif has 2 clocks but 1 enable */
|
||||
PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71),
|
||||
PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
|
||||
|
@ -2089,7 +2117,6 @@ struct clk tegra_list_clks[] = {
|
|||
PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */
|
||||
PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
|
||||
/* FIXME: vfir shares an enable with uartb */
|
||||
PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
|
||||
PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
|
||||
|
@ -2120,13 +2147,11 @@ struct clk tegra_list_clks[] = {
|
|||
PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX),
|
||||
PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
|
||||
PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */
|
||||
/* FIXME: vi and vi_sensor share an enable */
|
||||
PERIPH_CLK("vi", "tegra_camera", "vi", 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */
|
||||
PERIPH_CLK("vi_sensor", "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
|
||||
PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */
|
||||
PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */
|
||||
PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */
|
||||
/* FIXME: cve and tvo share an enable */
|
||||
PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
|
||||
PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
|
||||
PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
|
||||
|
|
Loading…
Reference in a new issue