1 /*
2  * Copyright (c) 2016, NVIDIA CORPORATION.
3  *
4  * SPDX-License-Identifier: GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <power-domain.h>
10 #include <power-domain-uclass.h>
11 
12 DECLARE_GLOBAL_DATA_PTR;
13 
14 static inline struct power_domain_ops *power_domain_dev_ops(struct udevice *dev)
15 {
16 	return (struct power_domain_ops *)dev->driver->ops;
17 }
18 
19 static int power_domain_of_xlate_default(struct power_domain *power_domain,
20 					 struct ofnode_phandle_args *args)
21 {
22 	debug("%s(power_domain=%p)\n", __func__, power_domain);
23 
24 	if (args->args_count != 1) {
25 		debug("Invalid args_count: %d\n", args->args_count);
26 		return -EINVAL;
27 	}
28 
29 	power_domain->id = args->args[0];
30 
31 	return 0;
32 }
33 
34 int power_domain_get(struct udevice *dev, struct power_domain *power_domain)
35 {
36 	struct ofnode_phandle_args args;
37 	int ret;
38 	struct udevice *dev_power_domain;
39 	struct power_domain_ops *ops;
40 
41 	debug("%s(dev=%p, power_domain=%p)\n", __func__, dev, power_domain);
42 
43 	ret = dev_read_phandle_with_args(dev, "power-domains",
44 					 "#power-domain-cells", 0, 0, &args);
45 	if (ret) {
46 		debug("%s: dev_read_phandle_with_args failed: %d\n",
47 		      __func__, ret);
48 		return ret;
49 	}
50 
51 	ret = uclass_get_device_by_ofnode(UCLASS_POWER_DOMAIN, args.node,
52 					  &dev_power_domain);
53 	if (ret) {
54 		debug("%s: uclass_get_device_by_ofnode failed: %d\n",
55 		      __func__, ret);
56 		return ret;
57 	}
58 	ops = power_domain_dev_ops(dev_power_domain);
59 
60 	power_domain->dev = dev_power_domain;
61 	if (ops->of_xlate)
62 		ret = ops->of_xlate(power_domain, &args);
63 	else
64 		ret = power_domain_of_xlate_default(power_domain, &args);
65 	if (ret) {
66 		debug("of_xlate() failed: %d\n", ret);
67 		return ret;
68 	}
69 
70 	ret = ops->request(power_domain);
71 	if (ret) {
72 		debug("ops->request() failed: %d\n", ret);
73 		return ret;
74 	}
75 
76 	return 0;
77 }
78 
79 int power_domain_free(struct power_domain *power_domain)
80 {
81 	struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
82 
83 	debug("%s(power_domain=%p)\n", __func__, power_domain);
84 
85 	return ops->free(power_domain);
86 }
87 
88 int power_domain_on(struct power_domain *power_domain)
89 {
90 	struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
91 
92 	debug("%s(power_domain=%p)\n", __func__, power_domain);
93 
94 	return ops->on(power_domain);
95 }
96 
97 int power_domain_off(struct power_domain *power_domain)
98 {
99 	struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
100 
101 	debug("%s(power_domain=%p)\n", __func__, power_domain);
102 
103 	return ops->off(power_domain);
104 }
105 
106 UCLASS_DRIVER(power_domain) = {
107 	.id		= UCLASS_POWER_DOMAIN,
108 	.name		= "power_domain",
109 };
110