ARM: tegra: Add virtual mclk for camera
David Schalig [Thu, 25 Jul 2013 03:21:24 +0000 (12:21 +0900)]
Add virtual clocks 'mclk' and 'mclk2' to control sensor mclk and
and its clock gate at the same time. This enables drivers to control
MCLK with only one clk handle instead of two.

mclk: controls vi_sensor + csus gate (on T20, T30, T114, T148, T124)
mclk2: controls vi_sensor2 + vim2_clk gate (on T148, T124 only)

Also remove obsolete source files.

Bug 1298672

Change-Id: I0ff210f22d2e6f023de852a169045bb2f66942e0
Signed-off-by: David Schalig <dschalig@nvidia.com>
Reviewed-on: http://git-master/r/253173
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Frank Chen <frankc@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

arch/arm/mach-tegra/tegra11_clocks.c
arch/arm/mach-tegra/tegra12_clocks.c

index 667916d..4dadba0 100644 (file)
@@ -6730,6 +6730,35 @@ static struct clk tegra_clk_cbus = {
 };
 #endif
 
+static void tegra11_camera_mclk_init(struct clk *c)
+{
+       c->state = OFF;
+       c->set = true;
+       c->parent = tegra_get_clock_by_name("vi_sensor");
+       c->max_rate = c->parent->max_rate;
+}
+
+static int tegra11_camera_mclk_set_rate(struct clk *c, unsigned long rate)
+{
+       return clk_set_rate(c->parent, rate);
+}
+
+static struct clk_ops tegra_camera_mclk_ops = {
+       .init     = tegra11_camera_mclk_init,
+       .enable   = tegra11_periph_clk_enable,
+       .disable  = tegra11_periph_clk_disable,
+       .set_rate = tegra11_camera_mclk_set_rate,
+};
+
+static struct clk tegra_camera_mclk = {
+       .name = "mclk",
+       .ops = &tegra_camera_mclk_ops,
+       .u.periph = {
+               .clk_num = 92, /* csus */
+       },
+       .flags = PERIPH_NO_RESET,
+};
+
 #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
        {                                               \
                .name      = _name,                     \
@@ -7161,7 +7190,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("i2c5", "tegra_cl_dvfs", "i2c"),
        CLK_DUPLICATE("cpu_g", "tegra_cl_dvfs", "safe_dvfs"),
        CLK_DUPLICATE("epp.cbus", "tegra_isp", "epp"),
-       CLK_DUPLICATE("vi_sensor", NULL, "default_mclk"),
+       CLK_DUPLICATE("mclk", NULL, "default_mclk"),
 };
 
 struct clk *tegra_ptr_clks[] = {
@@ -7977,6 +8006,8 @@ void __init tegra11x_init_clocks(void)
        for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
                tegra11_init_one_clock(&tegra_list_clks[i]);
 
+       tegra11_init_one_clock(&tegra_camera_mclk);
+
        for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++)
                tegra11_init_one_clock(&tegra_sync_source_list[i]);
        for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++)
index 68ef070..30687a4 100644 (file)
@@ -6807,6 +6807,50 @@ static struct clk tegra_clk_gpu = {
        .max_rate  = 806000000,
 };
 
+static void tegra12_camera_mclk_init(struct clk *c)
+{
+       c->state = OFF;
+       c->set = true;
+
+       if (!strcmp(c->name, "mclk")) {
+               c->parent = tegra_get_clock_by_name("vi_sensor");
+               c->max_rate = c->parent->max_rate;
+       } else if (!strcmp(c->name, "mclk2")) {
+               c->parent = tegra_get_clock_by_name("vi_sensor2");
+               c->max_rate = c->parent->max_rate;
+       }
+}
+
+static int tegra12_camera_mclk_set_rate(struct clk *c, unsigned long rate)
+{
+       return clk_set_rate(c->parent, rate);
+}
+
+static struct clk_ops tegra_camera_mclk_ops = {
+       .init     = tegra12_camera_mclk_init,
+       .enable   = tegra12_periph_clk_enable,
+       .disable  = tegra12_periph_clk_disable,
+       .set_rate = tegra12_camera_mclk_set_rate,
+};
+
+static struct clk tegra_camera_mclk = {
+       .name = "mclk",
+       .ops = &tegra_camera_mclk_ops,
+       .u.periph = {
+               .clk_num = 92, /* csus */
+       },
+       .flags = PERIPH_NO_RESET,
+};
+
+static struct clk tegra_camera_mclk2 = {
+       .name = "mclk2",
+       .ops = &tegra_camera_mclk_ops,
+       .u.periph = {
+               .clk_num = 171, /* vim2_clk */
+       },
+       .flags = PERIPH_NO_RESET,
+};
+
 #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
        {                                               \
                .name      = _name,                     \
@@ -7253,7 +7297,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("dam1", NULL, "dam1"),
        CLK_DUPLICATE("dam2", NULL, "dam2"),
        CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
-       CLK_DUPLICATE("vi_sensor", NULL, "default_mclk"),
+       CLK_DUPLICATE("mclk", NULL, "default_mclk"),
 };
 
 struct clk *tegra_ptr_clks[] = {
@@ -7316,6 +7360,11 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_gpu,
 };
 
+struct clk *tegra_ptr_camera_mclks[] = {
+       &tegra_camera_mclk,
+       &tegra_camera_mclk2,
+};
+
 /* Return true from this function if the target rate can be locked without
    switching pll clients to back-up source */
 static bool tegra12_is_dyn_ramp(
@@ -7986,6 +8035,9 @@ void __init tegra12x_init_clocks(void)
        for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
                tegra12_init_one_clock(&tegra_list_clks[i]);
 
+       for (i = 0; i < ARRAY_SIZE(tegra_ptr_camera_mclks); i++)
+               tegra12_init_one_clock(tegra_ptr_camera_mclks[i]);
+
        for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
                c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
                if (!c) {