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; + + 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; + } + + 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); + + 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); + + 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; +} + +static struct clk_ops tegra_cdev_clk_ops = { + .init = &tegra2_cdev_clk_init, + .enable = &tegra2_cdev_clk_enable, + .disable = &tegra2_cdev_clk_disable, + .set_parent = &tegra2_cdev_clk_set_parent, +}; + /* Clock definitions */ static struct clk tegra_clk_32k = { .name = "clk_32k", @@ -1408,6 +1501,44 @@ static struct clk tegra_clk_audio_2x = { .parent = &tegra_clk_audio, }; +static struct clk_mux_sel mux_cdev1[] = { + { .input = &tegra_clk_m, .value = TEGRA_MUX_OSC}, + { .input = &tegra_pll_a_out0, .value = TEGRA_MUX_PLLA_OUT}, + { .input = &tegra_pll_m_out1, .value = TEGRA_MUX_PLLM_OUT1}, + { .input = &tegra_clk_audio, .value = TEGRA_MUX_AUDIO_SYNC}, + { 0, 0}, +}; + +/* dap_mclk1, belongs to the cdev1 pingroup. */ +static struct clk tegra_clk_cdev1 = { + .name = "cdev1", + .inputs = mux_cdev1, + .ops = &tegra_cdev_clk_ops, + .clk_num = 94, + .reg = TEGRA_PINGROUP_CDEV1, + .max_rate = 73728000, +}; + +static struct clk_mux_sel mux_cdev2[] = { + { .input = &tegra_clk_m, .value = TEGRA_MUX_OSC}, +#if 0 /* FIXME: not implemented */ + { .input = &tegra_clk_, .value = TEGRA_MUX_AHB_CLK}, + { .input = &tegra_clk_, .value = TEGRA_MUX_APB_CLK}, +#endif + { .input = &tegra_pll_p_out4, .value = TEGRA_MUX_PLLP_OUT4}, + { 0, 0}, +}; + +/* dap_mclk2, belongs to the cdev2 pingroup. */ +static struct clk tegra_clk_cdev2 = { + .name = "cdev2", + .inputs = mux_cdev2, + .ops = &tegra_cdev_clk_ops, + .clk_num = 93, + .reg = TEGRA_PINGROUP_CDEV2, + .max_rate = 73728000, +}; + struct clk_lookup tegra_audio_clk_lookups[] = { { .con_id = "audio", .clk = &tegra_clk_audio }, { .con_id = "audio_2x", .clk = &tegra_clk_audio_2x } @@ -1737,6 +1868,8 @@ struct clk_lookup tegra_clk_lookups[] = { CLK(NULL, "pclk", &tegra_clk_pclk), CLK(NULL, "clk_d", &tegra_clk_d), CLK(NULL, "cpu", &tegra_clk_virtual_cpu), + CLK(NULL, "cdev1", &tegra_clk_cdev1), + CLK(NULL, "cdev2", &tegra_clk_cdev2), }; void __init tegra2_init_clocks(void) -- 1.7.0.4 -- 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