162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2014 Linaro Ltd. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Ulf Hansson <ulf.hansson@linaro.org> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Implements PM domains using the generic PM domain for ux500. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/printk.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/err.h> 1562306a36Sopenharmony_ci#include <linux/of.h> 1662306a36Sopenharmony_ci#include <linux/pm_domain.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <dt-bindings/arm/ux500_pm_domains.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic int pd_power_off(struct generic_pm_domain *domain) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci /* 2362306a36Sopenharmony_ci * Handle the gating of the PM domain regulator here. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Drivers/subsystems handling devices in the PM domain needs to perform 2662306a36Sopenharmony_ci * register context save/restore from their respective runtime PM 2762306a36Sopenharmony_ci * callbacks, to be able to enable PM domain gating/ungating. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci return 0; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int pd_power_on(struct generic_pm_domain *domain) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci /* 3562306a36Sopenharmony_ci * Handle the ungating of the PM domain regulator here. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * Drivers/subsystems handling devices in the PM domain needs to perform 3862306a36Sopenharmony_ci * register context save/restore from their respective runtime PM 3962306a36Sopenharmony_ci * callbacks, to be able to enable PM domain gating/ungating. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic struct generic_pm_domain ux500_pm_domain_vape = { 4562306a36Sopenharmony_ci .name = "VAPE", 4662306a36Sopenharmony_ci .power_off = pd_power_off, 4762306a36Sopenharmony_ci .power_on = pd_power_on, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = { 5162306a36Sopenharmony_ci [DOMAIN_VAPE] = &ux500_pm_domain_vape, 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic const struct of_device_id ux500_pm_domain_matches[] = { 5562306a36Sopenharmony_ci { .compatible = "stericsson,ux500-pm-domains", }, 5662306a36Sopenharmony_ci { }, 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic int ux500_pm_domains_probe(struct platform_device *pdev) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 6262306a36Sopenharmony_ci struct genpd_onecell_data *genpd_data; 6362306a36Sopenharmony_ci int i; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (!np) 6662306a36Sopenharmony_ci return -ENODEV; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci genpd_data = kzalloc(sizeof(*genpd_data), GFP_KERNEL); 6962306a36Sopenharmony_ci if (!genpd_data) 7062306a36Sopenharmony_ci return -ENOMEM; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci genpd_data->domains = ux500_pm_domains; 7362306a36Sopenharmony_ci genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i) 7662306a36Sopenharmony_ci pm_genpd_init(ux500_pm_domains[i], NULL, false); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci of_genpd_add_provider_onecell(np, genpd_data); 7962306a36Sopenharmony_ci return 0; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic struct platform_driver ux500_pm_domains_driver = { 8362306a36Sopenharmony_ci .probe = ux500_pm_domains_probe, 8462306a36Sopenharmony_ci .driver = { 8562306a36Sopenharmony_ci .name = "ux500_pm_domains", 8662306a36Sopenharmony_ci .of_match_table = ux500_pm_domain_matches, 8762306a36Sopenharmony_ci }, 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic int __init ux500_pm_domains_init(void) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci return platform_driver_register(&ux500_pm_domains_driver); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ciarch_initcall(ux500_pm_domains_init); 95