1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2014 Linaro Ltd. |
4 | * |
5 | * Author: Ulf Hansson <ulf.hansson@linaro.org> |
6 | * |
7 | * Implements PM domains using the generic PM domain for ux500. |
8 | */ |
9 | #include <linux/device.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/platform_device.h> |
12 | #include <linux/printk.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/err.h> |
15 | #include <linux/of.h> |
16 | #include <linux/pm_domain.h> |
17 | |
18 | #include <dt-bindings/arm/ux500_pm_domains.h> |
19 | |
20 | static int pd_power_off(struct generic_pm_domain *domain) |
21 | { |
22 | /* |
23 | * Handle the gating of the PM domain regulator here. |
24 | * |
25 | * Drivers/subsystems handling devices in the PM domain needs to perform |
26 | * register context save/restore from their respective runtime PM |
27 | * callbacks, to be able to enable PM domain gating/ungating. |
28 | */ |
29 | return 0; |
30 | } |
31 | |
32 | static int pd_power_on(struct generic_pm_domain *domain) |
33 | { |
34 | /* |
35 | * Handle the ungating of the PM domain regulator here. |
36 | * |
37 | * Drivers/subsystems handling devices in the PM domain needs to perform |
38 | * register context save/restore from their respective runtime PM |
39 | * callbacks, to be able to enable PM domain gating/ungating. |
40 | */ |
41 | return 0; |
42 | } |
43 | |
44 | static struct generic_pm_domain ux500_pm_domain_vape = { |
45 | .name = "VAPE" , |
46 | .power_off = pd_power_off, |
47 | .power_on = pd_power_on, |
48 | }; |
49 | |
50 | static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = { |
51 | [DOMAIN_VAPE] = &ux500_pm_domain_vape, |
52 | }; |
53 | |
54 | static const struct of_device_id ux500_pm_domain_matches[] = { |
55 | { .compatible = "stericsson,ux500-pm-domains" , }, |
56 | { }, |
57 | }; |
58 | |
59 | static int ux500_pm_domains_probe(struct platform_device *pdev) |
60 | { |
61 | struct device_node *np = pdev->dev.of_node; |
62 | struct genpd_onecell_data *genpd_data; |
63 | int i; |
64 | |
65 | if (!np) |
66 | return -ENODEV; |
67 | |
68 | genpd_data = kzalloc(size: sizeof(*genpd_data), GFP_KERNEL); |
69 | if (!genpd_data) |
70 | return -ENOMEM; |
71 | |
72 | genpd_data->domains = ux500_pm_domains; |
73 | genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains); |
74 | |
75 | for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i) |
76 | pm_genpd_init(genpd: ux500_pm_domains[i], NULL, is_off: false); |
77 | |
78 | of_genpd_add_provider_onecell(np, data: genpd_data); |
79 | return 0; |
80 | } |
81 | |
82 | static struct platform_driver ux500_pm_domains_driver = { |
83 | .probe = ux500_pm_domains_probe, |
84 | .driver = { |
85 | .name = "ux500_pm_domains" , |
86 | .of_match_table = ux500_pm_domain_matches, |
87 | }, |
88 | }; |
89 | |
90 | static int __init ux500_pm_domains_init(void) |
91 | { |
92 | return platform_driver_register(&ux500_pm_domains_driver); |
93 | } |
94 | arch_initcall(ux500_pm_domains_init); |
95 | |