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