1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_power.h"
10 #include "gpio_if.h"
11 #include "hdf_base.h"
12 #include "hdf_chip.h"
13 #include "hdf_chip_config.h"
14
15 #define MAX_POWER_COUNT 4
16
17 struct NoManagablePower {
18 struct HdfPower base;
19 uint8_t powerSeqDelay;
20 };
21
22 struct GpioBasedPower {
23 struct HdfPower base;
24 uint8_t powerSeqDelay;
25 uint8_t gpioId;
26 uint8_t activeLevel;
27 };
28
29 struct MutiPowers {
30 struct HdfPower base;
31 uint8_t innerPowerCount;
32 struct HdfPower *powers[0];
33 };
34
NotManagablePowerOn(struct HdfPower * power)35 static int32_t NotManagablePowerOn(struct HdfPower *power) {
36 (void)power;
37 return HDF_SUCCESS;
38 }
39
NotManagablePowerOff(struct HdfPower * power)40 static int32_t NotManagablePowerOff(struct HdfPower *power) {
41 (void)power;
42 return HDF_FAILURE;
43 }
44
ReleasePower(struct HdfPower * power)45 static void ReleasePower(struct HdfPower *power) {
46 if (power == NULL) {
47 return;
48 }
49 OsalMemFree(power);
50 }
51
CreateNoManagablePower(const struct HdfPowerConfig * power)52 static struct NoManagablePower *CreateNoManagablePower(const struct HdfPowerConfig *power) {
53 struct NoManagablePower *result = NULL;
54 static const struct HdfPowerOps notManagablePowerOps = {.On = NotManagablePowerOn,
55 .Off = NotManagablePowerOff,
56 .Release = ReleasePower};
57 result = (struct NoManagablePower *)OsalMemCalloc(sizeof(struct NoManagablePower));
58 if (result == NULL) {
59 return NULL;
60 }
61 result->base.ops = ¬ManagablePowerOps;
62 result->powerSeqDelay = power->powerSeqDelay;
63 return result;
64 }
65
GpioPowerOn(struct HdfPower * power)66 static int32_t GpioPowerOn(struct HdfPower *power) {
67 int32_t ret;
68 struct GpioBasedPower *gpioPower = (struct GpioBasedPower *)power;
69 if (power == NULL) {
70 HDF_LOGE("%s:nullptr", __func__);
71 return HDF_FAILURE;
72 }
73 ret = GpioSetDir(gpioPower->gpioId, 1);
74 if (ret != HDF_SUCCESS) {
75 HDF_LOGE("%s:set dir fail! ret=%d\n", __func__, ret);
76 return HDF_FAILURE;
77 }
78 ret = GpioWrite(gpioPower->gpioId, gpioPower->activeLevel);
79 if (ret != HDF_SUCCESS) {
80 HDF_LOGE("%s:set power on fail! ret=%d\n", __func__, ret);
81 return HDF_FAILURE;
82 }
83 return HDF_SUCCESS;
84 }
85
GpioPowerOff(struct HdfPower * power)86 static int32_t GpioPowerOff(struct HdfPower *power) {
87 int32_t ret;
88 struct GpioBasedPower *gpioPower = (struct GpioBasedPower *)power;
89 if (power == NULL) {
90 HDF_LOGE("%s:nullptr", __func__);
91 return HDF_FAILURE;
92 }
93 ret = GpioSetDir(gpioPower->gpioId, 1);
94 if (ret != HDF_SUCCESS) {
95 HDF_LOGE("%s:set dir fail! ret=%d\n", __func__, ret);
96 return HDF_FAILURE;
97 }
98 ret = GpioWrite(gpioPower->gpioId, !gpioPower->activeLevel);
99 if (ret != HDF_SUCCESS) {
100 HDF_LOGE("%s:set power on fail! ret=%d\n", __func__, ret);
101 return HDF_FAILURE;
102 }
103 return HDF_SUCCESS;
104 }
105
CreateGpioBasedPower(const struct HdfPowerConfig * power)106 static struct GpioBasedPower *CreateGpioBasedPower(const struct HdfPowerConfig *power) {
107 struct GpioBasedPower *result = NULL;
108 result = (struct GpioBasedPower *)OsalMemCalloc(sizeof(struct GpioBasedPower));
109 if (result == NULL) {
110 return NULL;
111 }
112 static const struct HdfPowerOps notManagablePowerOps = {.On = GpioPowerOn,
113 .Off = GpioPowerOff,
114 .Release = ReleasePower};
115 result->base.ops = ¬ManagablePowerOps;
116 result->powerSeqDelay = power->powerSeqDelay;
117 result->gpioId = power->gpio.gpioId;
118 result->activeLevel = power->gpio.activeLevel;
119 return result;
120 }
121
CreatePower(const struct HdfPowerConfig * power)122 static struct HdfPower *CreatePower(const struct HdfPowerConfig *power) {
123 if (power == NULL) {
124 return NULL;
125 }
126 if (power->type == POWER_TYPE_ALWAYS_ON) {
127 return (struct HdfPower *)CreateNoManagablePower(power);
128 } else if (power->type == POWER_TYPE_GPIO) {
129 return (struct HdfPower *)CreateGpioBasedPower(power);
130 } else {
131 HDF_LOGE("%s:not supported power type %d", __func__, power->type);
132 return NULL;
133 }
134 }
135
ActiveMutiPower(struct HdfPower * power)136 static int32_t ActiveMutiPower(struct HdfPower *power) {
137 struct MutiPowers *mutiPower = (struct MutiPowers *)power;
138 int ret;
139 if (power == NULL) {
140 HDF_LOGE("%s:nullptr", __func__);
141 return HDF_FAILURE;
142 }
143 for (uint8_t i = 0; i < mutiPower->innerPowerCount; i++) {
144 if (mutiPower->powers[i] == NULL || mutiPower->powers[i]->ops == NULL ||
145 mutiPower->powers[i]->ops->On == NULL) {
146 HDF_LOGW("%s:bad power!index=%d", __func__, i);
147 ret = HDF_FAILURE;
148 break;
149 }
150 if (i > 0) {
151 struct NoManagablePower *innerPower = (struct NoManagablePower *)mutiPower->powers[i];
152 OsalMSleep(innerPower->powerSeqDelay);
153 }
154 ret = mutiPower->powers[i]->ops->On(mutiPower->powers[i]);
155 if (ret != HDF_SUCCESS) {
156 break;
157 }
158 }
159 return ret;
160 }
161
DeactiveMutiPower(struct HdfPower * power)162 static int32_t DeactiveMutiPower(struct HdfPower *power) {
163 struct MutiPowers *mutiPower = (struct MutiPowers *)power;
164 int ret;
165 if (power == NULL) {
166 HDF_LOGE("%s:nullptr", __func__);
167 return HDF_FAILURE;
168 }
169 for (uint8_t i = 0; i < mutiPower->innerPowerCount; i++) {
170 if (mutiPower->powers[i] == NULL || mutiPower->powers[i]->ops == NULL ||
171 mutiPower->powers[i]->ops->Off == NULL) {
172 HDF_LOGW("%s:bad power!index=%d", __func__, i);
173 ret = HDF_FAILURE;
174 break;
175 }
176 ret = mutiPower->powers[i]->ops->Off(mutiPower->powers[i]);
177 if (ret != HDF_SUCCESS) {
178 break;
179 }
180 }
181 return ret;
182 }
183
ReleaseMutiPower(struct HdfPower * power)184 static void ReleaseMutiPower(struct HdfPower *power) {
185 struct MutiPowers *mutiPower = (struct MutiPowers *)power;
186 if (power == NULL) {
187 HDF_LOGE("%s:nullptr", __func__);
188 return;
189 }
190 for (uint8_t i = 0; i < mutiPower->innerPowerCount; i++) {
191 if (mutiPower->powers[i] == NULL || mutiPower->powers[i]->ops == NULL ||
192 mutiPower->powers[i]->ops->Release == NULL) {
193 HDF_LOGW("%s:bad power!index=%d", __func__, i);
194 } else {
195 mutiPower->powers[i]->ops->Release(mutiPower->powers[i]);
196 }
197 mutiPower->powers[i] = NULL;
198 }
199 OsalMemFree(power);
200 }
201
CreateMutiPower(const struct HdfPowersConfig * powersConfig)202 static struct MutiPowers *CreateMutiPower(const struct HdfPowersConfig *powersConfig) {
203 int ret = HDF_SUCCESS;
204 struct MutiPowers *mutiPower =
205 OsalMemCalloc(sizeof(struct MutiPowers) + sizeof(struct HdfPower *) * powersConfig->powerCount);
206 static const struct HdfPowerOps mutiPowerOps = {.On = ActiveMutiPower,
207 .Off = DeactiveMutiPower,
208 .Release = ReleaseMutiPower};
209 for (uint8_t i = 0; i < powersConfig->powerCount; i++) {
210 mutiPower->powers[i] = CreatePower(powersConfig->power + i);
211 if (mutiPower->powers[i] == NULL) {
212 OsalMemFree(mutiPower);
213 ret = HDF_FAILURE;
214 break;
215 }
216 }
217 mutiPower->innerPowerCount = powersConfig->powerCount;
218 if (ret != HDF_SUCCESS) {
219 ReleaseMutiPower((struct HdfPower *)mutiPower);
220 return NULL;
221 }
222 mutiPower->base.ops = &mutiPowerOps;
223 return mutiPower;
224 }
225
CreateVirtualPower(const struct HdfPowersConfig * powers)226 struct HdfPower *CreateVirtualPower(const struct HdfPowersConfig *powers) {
227 if (powers == NULL) {
228 HDF_LOGE("%s:nullptr", __func__);
229 return NULL;
230 }
231 if (powers->powerCount > MAX_POWER_COUNT) {
232 HDF_LOGE("%s:too many power in config!count=%d", __func__, powers->powerCount);
233 return NULL;
234 }
235 if (powers->powerCount == 1) {
236 return CreatePower(&powers->power[0]);
237 } else if (powers->powerCount > 1) {
238 return (struct HdfPower *)CreateMutiPower(powers);
239 } else {
240 return NULL;
241 }
242 }
243