arm: tegra: add api to remove device from domain
[linux-3.10.git] / arch / arm / mach-tegra / pm_domains.c
index 93c5d0a..e5fcada 100644 (file)
        __ret;                                                  \
 })
 
+struct domain_client {
+       const char *name;
+       struct generic_pm_domain *domain;
+};
+
 #ifdef CONFIG_PM_SLEEP
 
 static int tegra_pd_suspend_dev(struct device *dev)
@@ -170,54 +175,128 @@ static int tegra_mc_clk_power_on(struct generic_pm_domain *genpd)
        return 0;
 }
 
-struct tegra_pm_domain tegra_mc_clk = {
+static struct tegra_pm_domain tegra_mc_clk = {
        .gpd.name = "tegra_mc_clk",
        .gpd.power_off = tegra_mc_clk_power_off,
        .gpd.power_on = tegra_mc_clk_power_on,
 };
-EXPORT_SYMBOL(tegra_mc_clk);
 
-struct tegra_pm_domain tegra_mc_chain_a = {
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+static struct tegra_pm_domain tegra_mc_chain_a = {
        .gpd.name = "tegra_mc_chain_a",
        .gpd.power_off = tegra_mc_clk_power_off,
        .gpd.power_on = tegra_mc_clk_power_on,
 };
-EXPORT_SYMBOL(tegra_mc_chain_a);
 
-struct tegra_pm_domain tegra_mc_chain_b = {
-       .gpd.name = "tegra_chain_b",
+static struct tegra_pm_domain tegra_mc_chain_b = {
+       .gpd.name = "tegra_mc_chain_b",
        .gpd.power_off = tegra_mc_clk_power_off,
        .gpd.power_on = tegra_mc_clk_power_on,
 };
-EXPORT_SYMBOL(tegra_mc_chain_b);
+#endif
+
+static struct domain_client client_list[] = {
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       { .name = "tegra_mc_chain_a", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra_mc_chain_b", .domain = &tegra_mc_clk.gpd },
+       { .name = "gr2d", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "gr3d", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "msenc", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "isp", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "tegradc", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "vi", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "tegra30-hda", .domain = &tegra_mc_chain_a.gpd },
+       { .name = "tegra-apbdma", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "tegra-otg", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "tegra-ehci", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "tegra-xhci", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "host1x", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "tsec", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "nvavp", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "sdhci-tegra", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "tegra11-se", .domain = &tegra_mc_chain_b.gpd },
+       { .name = "tegra_bb", .domain = &tegra_mc_clk.gpd },
+#endif
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       { .name = "gr2d", .domain = &tegra_mc_clk.gpd },
+       { .name = "gr3d", .domain = &tegra_mc_clk.gpd },
+       { .name = "msenc", .domain = &tegra_mc_clk.gpd },
+       { .name = "isp", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegradc", .domain = &tegra_mc_clk.gpd },
+       { .name = "vi", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra30-hda", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra-apbdma", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra-otg", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra-ehci", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra-xhci", .domain = &tegra_mc_clk.gpd },
+       { .name = "host1x", .domain = &tegra_mc_clk.gpd },
+       { .name = "tsec", .domain = &tegra_mc_clk.gpd },
+       { .name = "nvavp", .domain = &tegra_mc_clk.gpd },
+       { .name = "sdhci-tegra", .domain = &tegra_mc_clk.gpd },
+       { .name = "tegra11-se", .domain = &tegra_mc_clk.gpd },
+#endif
+       {},
+};
 
 static int __init tegra_init_pm_domain(void)
 {
        pm_genpd_init(&tegra_mc_clk.gpd, &simple_qos_governor, false);
 
-       tegra_mc_chain_a.clk = clk_get_sys("mc_capa", "mc_capa");
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
        pm_genpd_init(&tegra_mc_chain_a.gpd, &simple_qos_governor, false);
-       tegra_pd_add_sd(&tegra_mc_clk, &tegra_mc_chain_a.gpd);
+       tegra_pd_add_sd(&tegra_mc_chain_a.gpd);
 
-       tegra_mc_chain_b.clk = clk_get_sys("mc_cbpa", "mc_cbpa");
        pm_genpd_init(&tegra_mc_chain_b.gpd, &simple_qos_governor, false);
-       tegra_pd_add_sd(&tegra_mc_chain_a, &tegra_mc_chain_b.gpd);
-
+       tegra_pd_add_sd(&tegra_mc_chain_b.gpd);
+#endif
        return 0;
 }
 core_initcall(tegra_init_pm_domain);
 
-void tegra_pd_add_device(struct tegra_pm_domain *pd, struct device *dev)
+static struct generic_pm_domain *tegra_pd_get_domain(const char *client)
 {
+       const char *s;
+       struct domain_client *clients = client_list;
+
+       while ((s = clients->name) != NULL) {
+               if (!strncmp(s, client, strlen(s)))
+                       return clients->domain;
+
+               clients++;
+       }
+       return NULL;
+}
+
+void tegra_pd_add_device(struct device *dev)
+{
+       struct generic_pm_domain *master = tegra_pd_get_domain(dev_name(dev));
+
+       if (!master)
+               return;
+
        device_set_wakeup_capable(dev, 1);
-       pm_genpd_add_device(&pd->gpd, dev);
+       pm_genpd_add_device(master, dev);
        pm_genpd_add_callbacks(dev, &tegra_pd_ops, NULL);
 }
 EXPORT_SYMBOL(tegra_pd_add_device);
 
-void tegra_pd_add_sd(struct tegra_pm_domain *pd, struct generic_pm_domain *sd)
+void tegra_pd_remove_device(struct device *dev)
 {
-       pm_genpd_add_subdomain(&pd->gpd, sd);
+       struct generic_pm_domain *genpd = dev_to_genpd(dev);
+
+       if (!IS_ERR_OR_NULL(genpd))
+               pm_genpd_remove_device(genpd, dev);
+}
+EXPORT_SYMBOL(tegra_pd_remove_device);
+
+void tegra_pd_add_sd(struct generic_pm_domain *sd)
+{
+       struct generic_pm_domain *master = tegra_pd_get_domain(sd->name);
+
+       if (!master)
+               return;
+
+       pm_genpd_add_subdomain(master, sd);
 }
 EXPORT_SYMBOL(tegra_pd_add_sd);
 #else