summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2014-04-11 14:42:29 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2014-04-13 20:09:36 -0700
commit974da74574f3d36f8957db6353ee8a419c4e1670 (patch)
tree1008fa38c906843d49e1347598c91cbfb52e39e4 /drivers/platform
parentdc7cbe176efe641ff27c4ef63568816d8b45d732 (diff)
platform: tegra: move pm_domain to drivers
Change-Id: I30baee4084399b8078232f31296c4d891a903d47 Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed-on: http://git-master/r/395123 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/Kconfig4
-rw-r--r--drivers/platform/tegra/Kconfig23
-rw-r--r--drivers/platform/tegra/Makefile6
-rw-r--r--drivers/platform/tegra/pm_domains.c272
4 files changed, 300 insertions, 5 deletions
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 69616aeaa966..6d36c5e4f3ef 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -4,4 +4,6 @@ endif
if GOLDFISH
source "drivers/platform/goldfish/Kconfig"
endif
-
+if ARCH_TEGRA
+source "drivers/platform/tegra/Kconfig"
+endif
diff --git a/drivers/platform/tegra/Kconfig b/drivers/platform/tegra/Kconfig
new file mode 100644
index 000000000000..25916fd9c38e
--- /dev/null
+++ b/drivers/platform/tegra/Kconfig
@@ -0,0 +1,23 @@
+
+# Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+comment "NVIDIA Tegra options"
+
+config TEGRA_MC_DOMAINS
+ bool "Enable Tegra MC PM domain"
+ depends on PM_GENERIC_DOMAINS
+ default n
+ help
+ When enabled, clock gates MC when it's not needed.
diff --git a/drivers/platform/tegra/Makefile b/drivers/platform/tegra/Makefile
index c82cc3403b4b..918e2af246b6 100644
--- a/drivers/platform/tegra/Makefile
+++ b/drivers/platform/tegra/Makefile
@@ -16,6 +16,8 @@ obj-y += mc/
obj-$(CONFIG_PM_SLEEP) += pm-irq.o
obj-y += pmc.o
+obj-$(CONFIG_TEGRA_MC_DOMAINS) += pm_domains.o
+
ifneq ($(CONFIG_ARM64),)
ccflags-y += -I$(srctree)/arch/arm/mach-tegra/include \
@@ -48,8 +50,6 @@ obj-y += powergate-ops-txx.o
obj-y += powergate-ops-t1xx.o
obj-$(CONFIG_ARCH_TEGRA_12x_SOC) += powergate-t12x.o
-obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
-
obj-y += dvfs.o
obj-$(CONFIG_ARCH_TEGRA_13x_SOC) += tegra13_dvfs.o
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
@@ -77,6 +77,8 @@ obj-y += tegra_emc.o
obj-$(CONFIG_ARCH_TEGRA_12x_SOC) += tegra12_emc.o
obj-$(CONFIG_ARCH_TEGRA_12x_SOC) += tegra_emc_dt_parse.o
+obj-$(CONFIG_TEGRA_MC_DOMAINS) += pm_domains.o
+
obj-y += flowctrl.o
obj-y += reset.o
obj-$(CONFIG_DEBUG_ICEDCC) += sysfs-dcc.o
diff --git a/drivers/platform/tegra/pm_domains.c b/drivers/platform/tegra/pm_domains.c
index 19d305704a7d..d98999562b95 100644
--- a/drivers/platform/tegra/pm_domains.c
+++ b/drivers/platform/tegra/pm_domains.c
@@ -1,2 +1,270 @@
-/* Automatically generated file; DO NOT EDIT. */
-#include "../../../arch/arm/mach-tegra/pm_domains.c"
+/*
+ * drivers/platform/tegra/pm_domains.c
+ *
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/tegra_pm_domains.h>
+
+#ifdef CONFIG_TEGRA_MC_DOMAINS
+#define TEGRA_PD_DEV_CALLBACK(callback, dev) \
+({ \
+ int (*__routine)(struct device *__d); \
+ int __ret = 0; \
+ \
+ if (dev->type && dev->type->pm) \
+ __routine = dev->type->pm->callback; \
+ else if (dev->class && dev->class->pm) \
+ __routine = dev->class->pm->callback; \
+ else if (dev->bus && dev->bus->pm) \
+ __routine = dev->bus->pm->callback; \
+ else \
+ __routine = NULL; \
+ \
+ if (!__routine && dev->driver && dev->driver->pm) \
+ __routine = dev->driver->pm->callback; \
+ \
+ if (__routine) \
+ __ret = __routine(dev); \
+ __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)
+{
+ return TEGRA_PD_DEV_CALLBACK(suspend, dev);
+}
+
+static int tegra_pd_suspend_late(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(suspend_late, dev);
+}
+
+static int tegra_pd_resume_early(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(resume_early, dev);
+}
+
+static int tegra_pd_resume_dev(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(resume, dev);
+}
+
+static int tegra_pd_freeze_dev(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(freeze, dev);
+}
+
+static int tegra_pd_freeze_late(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(freeze_late, dev);
+}
+
+static int tegra_pd_thaw_early(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(thaw_early, dev);
+}
+
+static int tegra_pd_thaw_dev(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(thaw, dev);
+}
+#else /* !CONFIG_PM_SLEEP */
+
+#define tegra_pd_suspend_dev NULL
+#define tegra_pd_suspend_late NULL
+#define tegra_pd_resume_early NULL
+#define tegra_pd_resume_dev NULL
+#define tegra_pd_freeze_dev NULL
+#define tegra_pd_freeze_late NULL
+#define tegra_pd_thaw_early NULL
+#define tegra_pd_thaw_dev NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
+static bool tegra_pd_active_wakeup(struct device *dev)
+{
+ return device_may_wakeup(dev);
+}
+
+static int tegra_pd_save_dev(struct device *dev)
+{
+ return 0;
+}
+
+static int tegra_pd_restore_dev(struct device *dev)
+{
+ return 0;
+}
+
+static int tegra_pd_stop_dev(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(runtime_suspend, dev);
+}
+
+static int tegra_pd_start_dev(struct device *dev)
+{
+ return TEGRA_PD_DEV_CALLBACK(runtime_resume, dev);
+}
+
+struct gpd_dev_ops tegra_pd_ops = {
+ .active_wakeup = tegra_pd_active_wakeup,
+ .save_state = tegra_pd_save_dev,
+ .restore_state = tegra_pd_restore_dev,
+ .stop = tegra_pd_stop_dev,
+ .start = tegra_pd_start_dev,
+ .suspend = tegra_pd_suspend_dev,
+ .suspend_late = tegra_pd_suspend_late,
+ .resume_early = tegra_pd_resume_early,
+ .resume = tegra_pd_resume_dev,
+ .freeze = tegra_pd_freeze_dev,
+ .freeze_late = tegra_pd_freeze_late,
+ .thaw_early = tegra_pd_thaw_early,
+ .thaw = tegra_pd_thaw_dev,
+};
+
+static int tegra_mc_clk_power_off(struct generic_pm_domain *genpd)
+{
+ struct tegra_pm_domain *pd = to_tegra_pd(genpd);
+
+ if (!pd)
+ return -EINVAL;
+
+ if (IS_ERR_OR_NULL(pd->clk))
+ return 0;
+
+ clk_disable_unprepare(pd->clk);
+
+ return 0;
+}
+
+static int tegra_mc_clk_power_on(struct generic_pm_domain *genpd)
+{
+ struct tegra_pm_domain *pd = to_tegra_pd(genpd);
+
+ if (!pd)
+ return -EINVAL;
+
+ if (IS_ERR_OR_NULL(pd->clk))
+ return 0;
+
+ clk_prepare_enable(pd->clk);
+
+ return 0;
+}
+
+static struct tegra_pm_domain tegra_nvavp = {
+ .gpd.name = "tegra_nvavp",
+};
+
+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,
+};
+
+static struct domain_client client_list[] = {
+ { .name = "tegradc", .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 = "tegra-host1x", .domain = &tegra_mc_clk.gpd },
+ { .name = "tegra_nvavp", .domain = &tegra_mc_clk.gpd },
+ { .name = "nvavp", .domain = &tegra_nvavp.gpd },
+ { .name = "sdhci-tegra", .domain = &tegra_mc_clk.gpd },
+ { .name = "tegra11-se", .domain = &tegra_mc_clk.gpd },
+ { .name = "tegra12-se", .domain = &tegra_mc_clk.gpd },
+ { .name = "tegra-pcie", .domain = &tegra_mc_clk.gpd },
+ { .name = "gpu", .domain = &tegra_mc_clk.gpd },
+ {},
+};
+
+static int __init tegra_init_pm_domain(void)
+{
+ pm_genpd_init(&tegra_mc_clk.gpd, &simple_qos_governor, false);
+
+ pm_genpd_init(&tegra_nvavp.gpd, &simple_qos_governor, false);
+ tegra_pd_add_sd(&tegra_nvavp.gpd);
+
+ return 0;
+}
+core_initcall(tegra_init_pm_domain);
+
+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(master, dev);
+ pm_genpd_dev_need_save(dev, false);
+ pm_genpd_add_callbacks(dev, &tegra_pd_ops, NULL);
+}
+EXPORT_SYMBOL(tegra_pd_add_device);
+
+void tegra_pd_remove_device(struct device *dev)
+{
+ 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
+struct tegra_pm_domain tegra_mc_clk;
+EXPORT_SYMBOL(tegra_mc_clk);
+struct tegra_pm_domain tegra_mc_chain_a;
+EXPORT_SYMBOL(tegra_mc_chain_a);
+struct tegra_pm_domain tegra_mc_chain_b;
+EXPORT_SYMBOL(tegra_mc_chain_b);
+#endif