On Wed, Jan 5, 2011 at 10:13 AM, Stephen Warren <swarren@xxxxxxxxxxxxx> wrote: > From: Stephen Warren <swarren@xxxxxxxxxx> > > These clocks are needed for the audio to work. > > Signed-off-by: Stephen Warren <swarren@xxxxxxxxxx> > --- > arch/arm/mach-tegra/tegra2_clocks.c | 133 +++++++++++++++++++++++++++++++++++ > 1 files changed, 133 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c > index 10e25fa..00a397d 100644 > --- a/arch/arm/mach-tegra/tegra2_clocks.c > +++ b/arch/arm/mach-tegra/tegra2_clocks.c > @@ -28,6 +28,7 @@ > #include <asm/clkdev.h> > > #include <mach/iomap.h> > +#include <mach/pinmux.h> > > #include "clock.h" > #include "fuse.h" > @@ -1007,6 +1008,98 @@ static struct clk_ops tegra_audio_sync_clk_ops = { > .set_parent = tegra2_audio_sync_clk_set_parent, > }; > > +/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ > + > +static void tegra2_cdev_clk_init(struct clk *c) > +{ > + int ret; > + enum tegra_tristate tristate; > + enum tegra_mux_func func; > + const struct clk_mux_sel *sel; > + > + c->state = ON; > + > + if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & > + PERIPH_CLK_TO_ENB_BIT(c))) > + c->state = OFF; > + > + ret = tegra_pinmux_get_tristate(c->reg, &tristate); > + if (ret || tristate) > + c->state = OFF; I would suggest not messing with the tristate from the clock driver. In general, you don't want to tristate clock pins when the clock is disabled, it will leave the line floating an susceptible to noise causing spurious clock edges. Let the board pinmux tables handle untristating the pin, and only use the clock enable register and the pinmux function register from the clock driver. > + > + ret = tegra_pinmux_get_func(c->reg, &func); > + if (ret) > + func = -1; > + > + for (sel = c->inputs; sel->input != NULL; sel++) { > + if (sel->value == func) { > + c->parent = sel->input; > + break; > + } > + } > + > + if (!c->parent) > + c->state = OFF; > +} > + > + > +static int tegra2_cdev_clk_enable(struct clk *c) > +{ > + int ret; > + > + ret = tegra_pinmux_set_tristate(c->reg, TEGRA_TRI_NORMAL); > + if (ret) { > + pr_err("Failed to drive %s\n", c->name); > + return ret; > + } Same on the tristate > + clk_writel(PERIPH_CLK_TO_ENB_BIT(c), > + CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); > + > + return 0; > +} > + > +static void tegra2_cdev_clk_disable(struct clk *c) > +{ > + int ret; > + > + ret = tegra_pinmux_set_tristate(c->reg, TEGRA_TRI_TRISTATE); > + if (ret) > + pr_err("Failed to tristate %s\n", c->name); Same on the tristate > + > + clk_writel(PERIPH_CLK_TO_ENB_BIT(c), > + CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); > +} > + > +static int tegra2_cdev_clk_set_parent(struct clk *c, struct clk *p) > +{ > + const struct clk_mux_sel *sel; > + > + for (sel = c->inputs; sel->input != NULL; sel++) { > + if (sel->input == p) { > + if (c->refcnt) > + clk_enable_locked(p); Please target linux-tegra-2.6.36 (or linux-tegra-2.6.37, which I should be pushing soon), not for-next. I will squash and move patches to for-next as appropriate. clk_enable_locked is no longer necessary in the latest version of the clock code. > + > + tegra_pinmux_set_func(c->reg, sel->value); > + > + if (c->refcnt && c->parent) > + clk_disable_locked(c->parent); > + > + clk_reparent(c, p); > + return 0; > + } > + } > + > + return -EINVAL; > +} <snip> -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html