ARM: tegra12: clock: Add gpu shared bus
Alex Frid [Sat, 24 Aug 2013 04:44:23 +0000 (21:44 -0700)]
Added Tegra12 gpu shared bus (gbus) on top of clock operations exported
by gk20a driver. Populated bus with gk20a shared user, cap and override
user clocks. Updated gbus dvfs tables.

Bug 1320966

Change-Id: Iafadc4e00fa6348f1f139d69f467c4071c48b145
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/265875
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

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

index 6c8de74..911dc0f 100644 (file)
@@ -6974,7 +6974,80 @@ static struct clk tegra_clk_gpu = {
        .u.periph  = {
                .clk_num = 184,
        },
-       .max_rate  = 806000000,
+       .max_rate  = 48000000,
+       .min_rate  = 12000000,
+};
+
+static void tegra12_clk_gbus_init(struct clk *c)
+{
+       unsigned long rate;
+       bool enabled;
+
+       pr_debug("%s on clock %s (export ops %s)\n", __func__,
+                c->name, c->u.export_clk.ops ? "ready" : "not ready");
+
+       if (!c->u.export_clk.ops || !c->u.export_clk.ops->init)
+               return;
+
+       c->u.export_clk.ops->init(c->u.export_clk.ops->data, &rate, &enabled);
+       c->div = clk_get_rate(c->parent) / 1000000;
+       c->mul = rate / 1000000;
+       c->state = enabled ? ON : OFF;
+}
+
+static int tegra12_clk_gbus_enable(struct clk *c)
+{
+       pr_debug("%s on clock %s (export ops %s)\n", __func__,
+                c->name, c->u.export_clk.ops ? "ready" : "not ready");
+
+       if (!c->u.export_clk.ops || !c->u.export_clk.ops->enable)
+               return -ENOENT;
+
+       return c->u.export_clk.ops->enable(c->u.export_clk.ops->data);
+}
+
+static void tegra12_clk_gbus_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s (export ops %s)\n", __func__,
+                c->name, c->u.export_clk.ops ? "ready" : "not ready");
+
+       if (!c->u.export_clk.ops || !c->u.export_clk.ops->disable)
+               return;
+
+       c->u.export_clk.ops->disable(c->u.export_clk.ops->data);
+}
+
+static int tegra12_clk_gbus_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret;
+
+       pr_debug("%s %lu on clock %s (export ops %s)\n", __func__,
+                rate, c->name, c->u.export_clk.ops ? "ready" : "not ready");
+
+       if (!c->u.export_clk.ops || !c->u.export_clk.ops->set_rate)
+               return -ENOENT;
+
+       ret = c->u.export_clk.ops->set_rate(c->u.export_clk.ops->data, &rate);
+       if (!ret)
+               c->mul = rate / 1000000;
+       return ret;
+}
+
+static struct clk_ops tegra_clk_gbus_ops = {
+       .init           = tegra12_clk_gbus_init,
+       .enable         = tegra12_clk_gbus_enable,
+       .disable        = tegra12_clk_gbus_disable,
+       .set_rate       = tegra12_clk_gbus_set_rate,
+       .round_rate     = tegra12_clk_cbus_round_rate,            /* re-use */
+       .round_rate_updown = tegra12_clk_cbus_round_updown,       /* re-use */
+       .shared_bus_update = tegra12_clk_shared_connector_update, /* re-use */
+};
+
+static struct clk tegra_clk_gbus = {
+       .name      = "gbus",
+       .ops       = &tegra_clk_gbus_ops,
+       .parent    = &tegra_clk_gpu,
+       .max_rate  = 1000000000,
 };
 
 static void tegra12_camera_mclk_init(struct clk *c)
@@ -7340,6 +7413,10 @@ struct clk tegra_list_clks[] = {
        SHARED_CLK("override.cbus", "override.cbus",    NULL,   &tegra_clk_cbus, NULL,  0, SHARED_OVERRIDE),
        SHARED_CLK("edp.cbus",  "edp.cbus",             NULL,   &tegra_clk_cbus, NULL,  0, SHARED_CEILING),
 #endif
+       SHARED_CLK("gk20a.gbus",        "tegra_gk20a",  "gpu",  &tegra_clk_gbus, NULL,  0, 0),
+       SHARED_CLK("cap.gbus",          "cap.gbus",     NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
+       SHARED_CLK("cap.throttle.gbus", "cap_throttle", NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
+       SHARED_CLK("override.gbus",     "override.gbus", NULL,  &tegra_clk_gbus, NULL,  0, SHARED_OVERRIDE),
 };
 
 /* VI, ISP buses */
@@ -7494,6 +7571,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("host1x", "tegra_host1x", "host1x"),
        CLK_DUPLICATE("actmon", "tegra_host1x", "actmon"),
        CLK_DUPLICATE("gpu", "tegra_gk20a", "PLLG_ref"),
+       CLK_DUPLICATE("gbus", "tegra_gk20a", "PLLG_out"),
        CLK_DUPLICATE("pll_p_out5", "tegra_gk20a", "pwr"),
        CLK_DUPLICATE("ispa.isp.c4bus", "tegra_isp", "isp"),
        CLK_DUPLICATE("ispb.isp.c4bus", "tegra_isp.1", "isp"),
@@ -7576,6 +7654,7 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_cbus,
 #endif
        &tegra_clk_gpu,
+       &tegra_clk_gbus,
        &tegra_clk_isp,
        &tegra_clk_c4bus,
 };
index 3691203..c6ba5b6 100644 (file)
@@ -290,11 +290,11 @@ static struct gpu_cvb_dvfs gpu_cvb_dvfs_table[] = {
                .voltage_scale = 1000,
                .cvb_table = {
                        /*f        dfll  pll:   c0,     c1,   c2 */
-                       {  408000, {  }, {  810000,      0,   0}, },
-                       {  528000, {  }, {  860000,      0,   0}, },
-                       {  702000, {  }, {  900000,      0,   0}, },
-                       {  984000, {  }, {  990000,      0,   0}, },
-                       { 1248000, {  }, { 1080000,      0,   0}, },
+                       {  204000, {  }, {  810000,      0,   0}, },
+                       {  264000, {  }, {  860000,      0,   0}, },
+                       {  351000, {  }, {  900000,      0,   0}, },
+                       {  492000, {  }, {  990000,      0,   0}, },
+                       {  624000, {  }, { 1080000,      0,   0}, },
                        {       0, {  }, {       0,      0,   0}, },
                },
        },
@@ -302,9 +302,9 @@ static struct gpu_cvb_dvfs gpu_cvb_dvfs_table[] = {
 
 static int gpu_millivolts[MAX_DVFS_FREQS];
 static struct dvfs gpu_dvfs = {
-       .clk_name       = "gpu",
+       .clk_name       = "gbus",
        .millivolts     = gpu_millivolts,
-       .auto_dvfs      = false,
+       .auto_dvfs      = true,
        .dvfs_rail      = &tegra12_dvfs_rail_vdd_gpu,
 };