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); }
static int exynos_pd_power_on(struct device *dev, const char * device_name) { struct exynos_pm_domain *pd_index = NULL; int ret = 0; struct gpd_timing_data gpd_td = { .stop_latency_ns = 50000, .start_latency_ns = 50000, .save_state_latency_ns = 500000, .restore_state_latency_ns = 500000, }; #ifdef CONFIG_SOC_EXYNOS5260 if(soc_is_exynos5260()) pd_index = exynos5260_pm_domain(); #endif #ifdef CONFIG_SOC_EXYNOS4415 if (soc_is_exynos4415()) pd_index = exynos4415_pm_domain(); #endif if (!pd_index) { pr_err(PM_DOMAIN_PREFIX "domain data is not found\n"); return -EINVAL; } /* lookup master pd */ for_each_power_domain(pd_index) { /* skip unmanaged power domains */ if (!pd_index->enable) continue; if (strcmp(pd_index->name, device_name)) { continue; } if (pd_index->check_status(pd_index)) { pr_err("PM DOMAIN: %s is already on.\n", pd_index->name); break; } while (1) { ret = __pm_genpd_add_device(&pd_index->genpd, dev, &gpd_td); if (ret != -EAGAIN) break; cond_resched(); } if (!ret) { pm_genpd_dev_need_restore(dev, true); pr_info("PM DOMAIN: %s, Device : %s Registered\n", pd_index->name, dev_name(dev)); } else pr_err("PM DOMAIN: %s cannot add device %s\n", pd_index->name, dev_name(dev)); pm_runtime_enable(dev); pm_runtime_get_sync(dev); pr_info("%s: power on.\n", pd_index->name); } return ret; } static int exynos_pd_power_off(struct device *dev, const char * device_name) { struct exynos_pm_domain *pd_index = NULL; int ret = 0; #ifdef CONFIG_SOC_EXYNOS5260 if(soc_is_exynos5260()) pd_index = exynos5260_pm_domain(); #endif #ifdef CONFIG_SOC_EXYNOS4415 if (soc_is_exynos4415()) pd_index = exynos4415_pm_domain(); #endif if (!pd_index) { pr_err(PM_DOMAIN_PREFIX "domain data is not found\n"); return -EINVAL; } /* lookup master pd */ for_each_power_domain(pd_index) { /* skip unmanaged power domains */ if (!pd_index->enable) continue; if (strcmp(pd_index->name, device_name)) { continue; } if (!pd_index->check_status(pd_index)) { pr_err("PM DOMAIN: %s is already off.\n", pd_index->name); break; } pm_runtime_put_sync(dev); pm_runtime_disable(dev); while (1) { ret = pm_genpd_remove_device(&pd_index->genpd, dev); if (ret != -EAGAIN) break; cond_resched(); } if (ret) pr_err("PM DOMAIN: %s cannot remove device %s\n", pd_index->name, dev_name(dev)); pr_info("%s: power off.\n", pd_index->name); } return ret; } static int exynos_pd_longrun_test(struct device *dev, const char * device_name) { struct exynos_pm_domain *pd_index = NULL; int i, ret = 0; struct gpd_timing_data gpd_td = { .stop_latency_ns = 50000, .start_latency_ns = 50000, .save_state_latency_ns = 500000, .restore_state_latency_ns = 500000, }; #ifdef CONFIG_SOC_EXYNOS5260 if(soc_is_exynos5260()) pd_index = exynos5260_pm_domain(); #endif #ifdef CONFIG_SOC_EXYNOS4415 if (soc_is_exynos4415()) pd_index = exynos4415_pm_domain(); #endif if (!pd_index) { pr_err(PM_DOMAIN_PREFIX "domain data is not found\n"); return -EINVAL; } /* lookup master pd */ for_each_power_domain(pd_index) { /* skip unmanaged power domains */ if (!pd_index->enable) continue; if (strcmp(pd_index->name, device_name)) { continue; } if (pd_index->check_status(pd_index)) { pr_err("PM DOMAIN: %s is working. Stop testing\n", pd_index->genpd.name); break; } while (1) { ret = __pm_genpd_add_device(&pd_index->genpd, dev, &gpd_td); if (ret != -EAGAIN) break; cond_resched(); } if (!ret) { pm_genpd_dev_need_restore(dev, true); pr_info("PM DOMAIN: %s, Device : %s Registered\n", pd_index->genpd.name, dev_name(dev)); } else pr_err("PM DOMAIN: %s cannot add device %s\n", pd_index->genpd.name, dev_name(dev)); pr_info("%s: test start.\n", pd_index->genpd.name); pm_runtime_enable(dev); for (i=0; i<100; i++) { pm_runtime_get_sync(dev); mdelay(50); pm_runtime_put_sync(dev); mdelay(50); } pr_info("%s: test done.\n", pd_index->genpd.name); pm_runtime_disable(dev); while (1) { ret = pm_genpd_remove_device(&pd_index->genpd, dev); if (ret != -EAGAIN) break; cond_resched(); } if (ret) pr_err("PM DOMAIN: %s cannot remove device %s\n", pd_index->name, dev_name(dev)); } return ret; } static ssize_t store_power_domain_test(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { char device_name[32], test_name[32]; sscanf(buf, "%s %s", device_name, test_name); switch (test_name[0]) { case '1': exynos_pd_power_on(dev, device_name); break; case '0': exynos_pd_power_off(dev, device_name); break; case 't': exynos_pd_longrun_test(dev, device_name); break; default: printk("echo \"device\" \"test\" > control\n"); } return count; } static DEVICE_ATTR(control, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, show_power_domain, store_power_domain_test); static struct attribute *control_device_attrs[] = { &dev_attr_control.attr, NULL, }; static const struct attribute_group control_device_attr_group = { .attrs = control_device_attrs, }; static int runtime_pm_test_probe(struct platform_device *pdev) { struct class *runtime_pm_class; struct device *runtime_pm_dev; int ret; runtime_pm_class = class_create(THIS_MODULE, "runtime_pm"); runtime_pm_dev = device_create(runtime_pm_class, NULL, 0, NULL, "test"); ret = sysfs_create_group(&runtime_pm_dev->kobj, &control_device_attr_group); if (ret) { pr_err("Runtime PM Test : error to create sysfs\n"); return -EINVAL; } pm_runtime_enable(&pdev->dev); return 0; } static int runtime_pm_test_runtime_suspend(struct device *dev) { pr_info("Runtime PM Test : Runtime_Suspend\n"); return 0; }