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 uint16_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 {
37 (void)power;
38 return HDF_SUCCESS;
39 }
40
NotManagablePowerOff(struct HdfPower * power)41 static int32_t NotManagablePowerOff(struct HdfPower *power)
42 {
43 (void)power;
44 return HDF_FAILURE;
45 }
46
ReleasePower(struct HdfPower * power)47 static void ReleasePower(struct HdfPower *power)
48 {
49 if (power == NULL) {
50 return;
51 }
52 OsalMemFree(power);
53 }
54
CreateNoManagablePower(const struct HdfPowerConfig * power)55 static struct NoManagablePower *CreateNoManagablePower(const struct HdfPowerConfig *power)
56 {
57 struct NoManagablePower *result = NULL;
58 static const struct HdfPowerOps notManagablePowerOps = {.On = NotManagablePowerOn,
59 .Off = NotManagablePowerOff,
60 .Release = ReleasePower};
61 result = (struct NoManagablePower *)OsalMemCalloc(sizeof(struct NoManagablePower));
62 if (result == NULL) {
63 return NULL;
64 }
65 result->base.ops = ¬ManagablePowerOps;
66 result->powerSeqDelay = power->powerSeqDelay;
67 return result;
68 }
69
GpioPowerOn(struct HdfPower * power)70 static int32_t GpioPowerOn(struct HdfPower *power)
71 {
72 int32_t ret;
73 struct GpioBasedPower *gpioPower = (struct GpioBasedPower *)power;
74 if (power == NULL) {
75 HDF_LOGE("%s:nullptr", __func__);
76 return HDF_FAILURE;
77 }
78 ret = GpioSetDir(gpioPower->gpioId, 1);
79 if (ret != HDF_SUCCESS) {
80 HDF_LOGE("%s:set dir fail! ret=%d\n", __func__, ret);
81 return HDF_FAILURE;
82 }
83 ret = GpioWrite(gpioPower->gpioId, gpioPower->activeLevel);
84 if (ret != HDF_SUCCESS) {
85 HDF_LOGE("%s:set power on fail! ret=%d\n", __func__, ret);
86 return HDF_FAILURE;
87 }
88 return HDF_SUCCESS;
89 }
90
GpioPowerOff(struct HdfPower * power)91 static int32_t GpioPowerOff(struct HdfPower *power)
92 {
93 int32_t ret;
94 struct GpioBasedPower *gpioPower = (struct GpioBasedPower *)power;
95 if (power == NULL) {
96 HDF_LOGE("%s:nullptr", __func__);
97 return HDF_FAILURE;
98 }
99 ret = GpioSetDir(gpioPower->gpioId, 1);
100 if (ret != HDF_SUCCESS) {
101 HDF_LOGE("%s:set dir fail! ret=%d\n", __func__, ret);
102 return HDF_FAILURE;
103 }
104 ret = GpioWrite(gpioPower->gpioId, !gpioPower->activeLevel);
105 if (ret != HDF_SUCCESS) {
106 HDF_LOGE("%s:set power on fail! ret=%d\n", __func__, ret);
107 return HDF_FAILURE;
108 }
109 return HDF_SUCCESS;
110 }
111
CreateGpioBasedPower(const struct HdfPowerConfig * power)112 static struct GpioBasedPower *CreateGpioBasedPower(const struct HdfPowerConfig *power)
113 {
114 struct GpioBasedPower *result = NULL;
115 result = (struct GpioBasedPower *)OsalMemCalloc(sizeof(struct GpioBasedPower));
116 if (result == NULL) {
117 return NULL;
118 }
119 static const struct HdfPowerOps notManagablePowerOps = {.On = GpioPowerOn,
120 .Off = GpioPowerOff,
121 .Release = ReleasePower};
122 result->base.ops = ¬ManagablePowerOps;
123 result->powerSeqDelay = power->powerSeqDelay;
124 result->gpioId = power->gpio.gpioId;
125 result->activeLevel = power->gpio.activeLevel;
126 return result;
127 }
128
CreatePower(const struct HdfPowerConfig * power)129 static struct HdfPower *CreatePower(const struct HdfPowerConfig *power)
130 {
131 if (power == NULL) {
132 return NULL;
133 }
134 if (power->type == POWER_TYPE_ALWAYS_ON) {
135 return (struct HdfPower *)CreateNoManagablePower(power);
136 } else if (power->type == POWER_TYPE_GPIO) {
137 return (struct HdfPower *)CreateGpioBasedPower(power);
138 } else {
139 HDF_LOGE("%s:not supported power type %d", __func__, power->type);
140 return NULL;
141 }
142 }
143
ActiveMutiPower(struct HdfPower * power)144 static int32_t ActiveMutiPower(struct HdfPower *power)
145 {
146 struct MutiPowers *mutiPower = (struct MutiPowers *)power;
147 int ret;
148 if (power == NULL) {
149 HDF_LOGE("%s:nullptr", __func__);
150 return HDF_FAILURE;
151 }
152 for (uint8_t i = 0; i < mutiPower->innerPowerCount; i++) {
153 if (mutiPower->powers[i] == NULL || mutiPower->powers[i]->ops == NULL ||
154 mutiPower->powers[i]->ops->On == NULL) {
155 HDF_LOGW("%s:bad power!index=%d", __func__, i);
156 ret = HDF_FAILURE;
157 break;
158 }
159 if (i > 0) {
160 struct NoManagablePower *innerPower = (struct NoManagablePower *)mutiPower->powers[i];
161 OsalMSleep(innerPower->powerSeqDelay);
162 }
163 ret = mutiPower->powers[i]->ops->On(mutiPower->powers[i]);
164 if (ret != HDF_SUCCESS) {
165 break;
166 }
167 }
168 return ret;
169 }
170
DeactiveMutiPower(struct HdfPower * power)171 static int32_t DeactiveMutiPower(struct HdfPower *power)
172 {
173 struct MutiPowers *mutiPower = (struct MutiPowers *)power;
174 int ret;
175 if (power == NULL) {
176 HDF_LOGE("%s:nullptr", __func__);
177 return HDF_FAILURE;
178 }
179 for (uint8_t i = 0; i < mutiPower->innerPowerCount; i++) {
180 if (mutiPower->powers[i] == NULL || mutiPower->powers[i]->ops == NULL ||
181 mutiPower->powers[i]->ops->Off == NULL) {
182 HDF_LOGW("%s:bad power!index=%d", __func__, i);
183 ret = HDF_FAILURE;
184 break;
185 }
186 ret = mutiPower->powers[i]->ops->Off(mutiPower->powers[i]);
187 if (ret != HDF_SUCCESS) {
188 break;
189 }
190 }
191 return ret;
192 }
193
ReleaseMutiPower(struct HdfPower * power)194 static void ReleaseMutiPower(struct HdfPower *power)
195 {
196 struct MutiPowers *mutiPower = (struct MutiPowers *)power;
197 if (power == NULL) {
198 HDF_LOGE("%s:nullptr", __func__);
199 return;
200 }
201 for (uint8_t i = 0; i < mutiPower->innerPowerCount; i++) {
202 if (mutiPower->powers[i] == NULL || mutiPower->powers[i]->ops == NULL ||
203 mutiPower->powers[i]->ops->Release == NULL) {
204 HDF_LOGW("%s:bad power!index=%d", __func__, i);
205 } else {
206 mutiPower->powers[i]->ops->Release(mutiPower->powers[i]);
207 }
208 mutiPower->powers[i] = NULL;
209 }
210 OsalMemFree(power);
211 }
212
CreateMutiPower(const struct HdfPowersConfig * powersConfig)213 static struct MutiPowers *CreateMutiPower(const struct HdfPowersConfig *powersConfig) {
214 int ret = HDF_SUCCESS;
215 struct MutiPowers *mutiPower =
216 OsalMemCalloc(sizeof(struct MutiPowers) + sizeof(struct HdfPower *) * powersConfig->powerCount);
217 static const struct HdfPowerOps mutiPowerOps = {.On = ActiveMutiPower,
218 .Off = DeactiveMutiPower,
219 .Release = ReleaseMutiPower};
220 for (uint8_t i = 0; i < powersConfig->powerCount; i++) {
221 mutiPower->powers[i] = CreatePower(powersConfig->power + i);
222 if (mutiPower->powers[i] == NULL) {
223 OsalMemFree(mutiPower);
224 ret = HDF_FAILURE;
225 break;
226 }
227 }
228 mutiPower->innerPowerCount = powersConfig->powerCount;
229 if (ret != HDF_SUCCESS) {
230 ReleaseMutiPower((struct HdfPower *)mutiPower);
231 return NULL;
232 }
233 mutiPower->base.ops = &mutiPowerOps;
234 return mutiPower;
235 }
236
CreateVirtualPower(const struct HdfPowersConfig * powers)237 struct HdfPower *CreateVirtualPower(const struct HdfPowersConfig *powers)
238 {
239 if (powers == NULL) {
240 HDF_LOGE("%s:nullptr", __func__);
241 return NULL;
242 }
243 if (powers->powerCount > MAX_POWER_COUNT) {
244 HDF_LOGE("%s:too many power in config!count=%d", __func__, powers->powerCount);
245 return NULL;
246 }
247 if (powers->powerCount == 1) {
248 return CreatePower(&powers->power[0]);
249 } else if (powers->powerCount > 1) {
250 return (struct HdfPower *)CreateMutiPower(powers);
251 } else {
252 return NULL;
253 }
254 }
255