1 /*
2 * Copyright (c) 2021-2022 GOODIX.
3 *
4 * This file 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 "app_io.h"
10 #include "app_gpiote.h"
11 #include "gpio/gpio_core.h"
12 #include "device_resource_if.h"
13 #include "hdf_device_desc.h"
14 #include "hdf_log.h"
15 #include "stdio.h"
16
17 #define HDF_LOG_TAG gpio_gr5xx
18 #define IO_NUM_GPIO 32
19 #define IO_NUM_AON 8
20 #define IO_NUM_MSIO 5
21 #define IO_NUM_MAX (IO_NUM_GPIO + IO_NUM_AON + IO_NUM_MSIO)
22
23 #define IO_BASE_GPIO 0U
24 #define IO_BASE_AON IO_NUM_GPIO
25 #define IO_BASE_MSIO (IO_NUM_GPIO + IO_NUM_AON)
26
27 #define IO_PULL_DEFAULT APP_IO_PULLUP
28 #define IO_MODE_DEFAULT APP_IO_MODE_OUT_PUT
29
30 struct Gr5xxGpioPortConfig {
31 app_io_mode_t mode;
32 app_io_pull_t pull;
33 app_handle_mode_t handleMode;
34 };
35
36 static struct GpioCntlr g_GpioCntlr;
37 struct Gr5xxGpioPortConfig g_portCfg[IO_NUM_MAX];
38
GpioDevPinMap(uint32_t id,uint32_t * pin)39 static inline app_io_type_t GpioDevPinMap(uint32_t id, uint32_t *pin)
40 {
41 if (id < IO_BASE_AON) {
42 *pin = 1 << (id - IO_BASE_GPIO);
43 return APP_IO_TYPE_NORMAL;
44 } else if (id < IO_BASE_MSIO) {
45 *pin = 1 << (id - IO_BASE_AON);
46 return APP_IO_TYPE_AON;
47 } else {
48 *pin = 1 << (id - IO_BASE_MSIO);
49 return APP_IO_TYPE_MSIO;
50 }
51 }
52
PortConfigInit(void)53 static void PortConfigInit(void)
54 {
55 uint16_t cnt;
56
57 for (cnt = 0; cnt < IO_NUM_MAX; cnt++) {
58 g_portCfg[cnt].pull = IO_PULL_DEFAULT;
59 g_portCfg[cnt].mode = IO_MODE_DEFAULT;
60 g_portCfg[cnt].handleMode = APP_IO_NONE_WAKEUP;
61 }
62 }
63
GpioDevSetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t dir)64 static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
65 {
66 (void)cntlr;
67 uint32_t pin = 0;
68 app_io_init_t ioInit;
69 app_io_type_t iotype;
70
71 if (gpio >= IO_NUM_MAX) {
72 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
73 return HDF_ERR_INVALID_PARAM;
74 }
75
76 iotype = GpioDevPinMap(gpio, &pin);
77 ioInit.pin = pin;
78 ioInit.pull = g_portCfg[gpio].pull;
79 ioInit.mux = APP_IO_MUX_7;
80 ioInit.mode = IO_MODE_DEFAULT;
81
82 if (dir == GPIO_DIR_IN) {
83 ioInit.mode = APP_IO_MODE_INPUT;
84 } else if (dir == GPIO_DIR_OUT) {
85 ioInit.mode = APP_IO_MODE_OUT_PUT;
86 }
87
88 g_portCfg[gpio].mode = ioInit.mode;
89 if (APP_DRV_SUCCESS == app_io_init(iotype, &ioInit)) {
90 return HDF_SUCCESS;
91 } else {
92 return HDF_FAILURE;
93 }
94 }
95
GpioDevGetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * dir)96 static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
97 {
98 (void)cntlr;
99 if (gpio >= IO_NUM_MAX) {
100 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
101 return HDF_ERR_INVALID_PARAM;
102 }
103
104 *dir = g_portCfg[gpio].mode;
105
106 return HDF_SUCCESS;
107 }
108
GpioDevWrite(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t val)109 static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
110 {
111 (void)cntlr;
112 uint32_t pin = 0;
113 app_io_type_t ioType;
114
115 if (gpio >= IO_NUM_MAX) {
116 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
117 return HDF_ERR_INVALID_PARAM;
118 }
119
120 ioType = GpioDevPinMap(gpio, &pin);
121 if (val == GPIO_VAL_LOW) {
122 app_io_write_pin(ioType, pin, APP_IO_PIN_RESET);
123 } else if (val == GPIO_VAL_HIGH) {
124 app_io_write_pin(ioType, pin, APP_IO_PIN_SET);
125 }
126
127 return HDF_SUCCESS;
128 }
129
GpioDevRead(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * val)130 static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
131 {
132 (void)cntlr;
133 uint32_t pin = 0;
134 app_io_type_t ioType;
135 app_io_pin_state_t ioState;
136
137 if (val == NULL) {
138 HDF_LOGE("%s, value buffer is null", __func__);
139 return HDF_ERR_INVALID_PARAM;
140 }
141
142 if (gpio >= IO_NUM_MAX) {
143 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
144 return HDF_ERR_INVALID_PARAM;
145 }
146 ioType = GpioDevPinMap(gpio, &pin);
147 ioState = app_io_read_pin(ioType, pin);
148 if (APP_IO_PIN_RESET == ioState) {
149 *val = GPIO_VAL_LOW;
150 } else {
151 *val = GPIO_VAL_HIGH;
152 }
153
154 return HDF_SUCCESS;
155 }
156
GetPinIndex(uint32_t pin)157 static int32_t GetPinIndex(uint32_t pin)
158 {
159 int32_t index = 0;
160 while ((pin & 1) != 1) {
161 index++;
162 pin = pin >> 1;
163 }
164 return index;
165 }
166
GR5xxGpioIrqHdl(app_gpiote_evt_t * event)167 static void GR5xxGpioIrqHdl(app_gpiote_evt_t *event)
168 {
169 uint32_t gpio = 0;
170
171 if (event == NULL) {
172 HDF_LOGE("%s, event is NULL", __func__);
173 return;
174 }
175
176 if (event->type == APP_IO_TYPE_NORMAL) {
177 gpio = GetPinIndex(event->pin);
178 } else if (event->type == APP_IO_TYPE_AON) {
179 gpio = GetPinIndex(event->pin) + IO_BASE_AON;
180 } else {
181 HDF_LOGE("%s, event type error", __func__);
182 }
183
184 GpioCntlrIrqCallback(&g_GpioCntlr, gpio);
185 }
186
GpioDevEnableIrq(struct GpioCntlr * cntlr,uint16_t gpio)187 static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
188 {
189 (void)cntlr;
190 uint32_t pin = 0;
191 app_io_type_t ioType;
192 app_gpiote_param_t gpioteParam;
193
194 if (gpio >= IO_NUM_MAX) {
195 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
196 return HDF_ERR_INVALID_PARAM;
197 }
198
199 ioType = GpioDevPinMap(gpio, &pin);
200 gpioteParam.type = ioType;
201 gpioteParam.pin = pin;
202 gpioteParam.pull = g_portCfg[gpio].pull;
203 gpioteParam.mode = g_portCfg[gpio].mode;
204 gpioteParam.handle_mode = g_portCfg[gpio].handleMode;
205 gpioteParam.io_evt_cb = GR5xxGpioIrqHdl;
206 app_gpiote_init(&gpioteParam, 1);
207
208 return HDF_SUCCESS;
209 }
210
GpioDevDisableIrq(struct GpioCntlr * cntlr,uint16_t gpio)211 static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
212 {
213 (void)cntlr;
214 uint32_t pin = 0;
215 app_io_type_t ioType;
216 app_gpiote_param_t gpioteParam;
217
218 if (gpio >= IO_NUM_MAX) {
219 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
220 return HDF_ERR_INVALID_PARAM;
221 }
222
223 ioType = GpioDevPinMap(gpio, &pin);
224 gpioteParam.type = ioType;
225 gpioteParam.pin = pin;
226 gpioteParam.pull = g_portCfg[gpio].pull;
227 gpioteParam.mode = g_portCfg[gpio].mode;
228 gpioteParam.handle_mode = APP_IO_NONE_WAKEUP;
229 gpioteParam.io_evt_cb = NULL;
230 app_gpiote_init(&gpioteParam, 1);
231
232 return HDF_SUCCESS;
233 }
234
GpioDevSetIrq(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t mode)235 static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)
236 {
237 (void)cntlr;
238 uint32_t pin = 0;
239 app_io_type_t ioType;
240
241 if (gpio >= IO_NUM_MAX) {
242 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
243 return HDF_ERR_INVALID_PARAM;
244 }
245
246 ioType = GpioDevPinMap(gpio, &pin);
247 if (APP_IO_TYPE_MSIO == ioType) {
248 HDF_LOGE("%s, IO type not support", __func__);
249 return HDF_ERR_INVALID_PARAM;
250 }
251
252 switch (mode) {
253 case GPIO_IRQ_TRIGGER_RISING:
254 g_portCfg[gpio].mode = APP_IO_MODE_IT_RISING;
255 break;
256 case GPIO_IRQ_TRIGGER_FALLING:
257 g_portCfg[gpio].mode = APP_IO_MODE_IT_FALLING;
258 break;
259 case GPIO_IRQ_TRIGGER_HIGH:
260 g_portCfg[gpio].mode = APP_IO_MODE_IT_HIGH;
261 break;
262 case GPIO_IRQ_TRIGGER_LOW:
263 g_portCfg[gpio].mode = APP_IO_MODE_IT_LOW;
264 break;
265 default:
266 HDF_LOGE("%s, IRQ mode not support", __func__);
267 return HDF_ERR_INVALID_PARAM;
268 }
269
270 return HDF_SUCCESS;
271 }
272
GpioDevUnSetIrq(struct GpioCntlr * cntlr,uint16_t gpio)273 static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio)
274 {
275 (void)cntlr;
276 uint32_t pin = 0;
277 app_io_type_t ioType;
278 app_gpiote_param_t gpioteParam;
279
280 if (gpio >= IO_NUM_MAX) {
281 HDF_LOGE("%s, gpio index is greater than the maximum", __func__);
282 return HDF_ERR_INVALID_PARAM;
283 }
284
285 ioType = GpioDevPinMap(gpio, &pin);
286 gpioteParam.type = ioType;
287 gpioteParam.pin = pin;
288 gpioteParam.mode = g_portCfg[gpio].mode;
289 gpioteParam.pull = g_portCfg[gpio].pull;
290 gpioteParam.handle_mode = APP_IO_NONE_WAKEUP;
291 gpioteParam.io_evt_cb = NULL;
292
293 app_gpiote_init(&gpioteParam, 1);
294
295 return HDF_SUCCESS;
296 }
297
298 static struct GpioMethod g_GpioCntlrMethod = {
299 .request = NULL,
300 .release = NULL,
301 .write = GpioDevWrite,
302 .read = GpioDevRead,
303 .setDir = GpioDevSetDir,
304 .getDir = GpioDevGetDir,
305 .toIrq = NULL,
306 .setIrq = GpioDevSetIrq,
307 .unsetIrq = GpioDevUnSetIrq,
308 .enableIrq = GpioDevEnableIrq,
309 .disableIrq = GpioDevDisableIrq,
310 };
311
GetGpioResourceData(const struct DeviceResourceNode * node,const char * resName,uint32_t index)312 static uint16_t GetGpioResourceData(const struct DeviceResourceNode *node, const char *resName, uint32_t index)
313 {
314 int32_t ret;
315 uint16_t resData;
316 struct DeviceResourceIface *drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
317
318 if (drsOps == NULL || drsOps->GetUint16ArrayElem == NULL) {
319 HDF_LOGE("%s: invalid drsOps!", __func__);
320 return HDF_FAILURE;
321 }
322
323 ret = drsOps->GetUint16ArrayElem(node, resName, index, &resData, 0);
324 if (ret != HDF_SUCCESS) {
325 HDF_LOGE("%s: read %s fail!", __func__, resName);
326 return 0;
327 }
328
329 return resData;
330 }
331
GetGpioDeviceResource(const struct DeviceResourceNode * node)332 static int32_t GetGpioDeviceResource(const struct DeviceResourceNode *node)
333 {
334 int32_t ret;
335 uint16_t configNum = 0;
336 uint16_t gpioIndex;
337 uint16_t pullConfig;
338 uint16_t handleModeConfig;
339
340 if (node == NULL) {
341 HDF_LOGE("%s, device resource node is NULL", __func__);
342 return HDF_ERR_INVALID_PARAM;
343 }
344
345 struct DeviceResourceIface *drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
346 if (drsOps == NULL || drsOps->GetUint16 == NULL || drsOps->GetUint16ArrayElem == NULL) {
347 HDF_LOGE("%s: invalid drs ops fail!", __func__);
348 return HDF_FAILURE;
349 }
350 ret = drsOps->GetUint16(node, "configNum", &configNum, 0);
351 if (ret != HDF_SUCCESS) {
352 HDF_LOGE("%s: read configNum fail!", __func__);
353 return ret;
354 }
355 if (configNum >= IO_NUM_MAX) {
356 HDF_LOGE("%s: configNum(%d) invalid!", __func__, configNum);
357 return HDF_ERR_INVALID_PARAM;
358 }
359 for (int32_t i = 0; i < configNum; i++) {
360 gpioIndex = GetGpioResourceData(node, "gpioIndex", i);
361 pullConfig = GetGpioResourceData(node, "pull", i);
362 handleModeConfig = GetGpioResourceData(node, "handleMode", i);
363 if (gpioIndex >= IO_NUM_MAX) {
364 HDF_LOGE("%s: gpioIndex(%d) invalid!", __func__, gpioIndex);
365 return HDF_ERR_INVALID_PARAM;
366 }
367 if (pullConfig >= APP_IO_PULL_MAX) {
368 HDF_LOGE("%s: pullConfig(%d) invalid!", __func__, pullConfig);
369 return HDF_ERR_INVALID_PARAM;
370 }
371 if (handleModeConfig > APP_IO_ENABLE_WAKEUP) {
372 HDF_LOGE("%s: handleModeConfig(%d) invalid!", __func__, handleModeConfig);
373 return HDF_ERR_INVALID_PARAM;
374 }
375 g_portCfg[gpioIndex].pull = pullConfig;
376 g_portCfg[gpioIndex].handleMode = handleModeConfig;
377 }
378
379 return HDF_SUCCESS;
380 }
381
GpioDriverBind(struct HdfDeviceObject * device)382 static int32_t GpioDriverBind(struct HdfDeviceObject *device)
383 {
384 (void)device;
385 return HDF_SUCCESS;
386 }
387
GpioDriverInit(struct HdfDeviceObject * device)388 static int32_t GpioDriverInit(struct HdfDeviceObject *device)
389 {
390 int32_t ret;
391 struct GpioCntlr *gpioCntlr = &g_GpioCntlr;
392
393 if (device == NULL || device->property == NULL) {
394 HDF_LOGE("%s: device or property null!", __func__);
395 return HDF_ERR_INVALID_OBJECT;
396 }
397
398 PortConfigInit();
399 ret = GetGpioDeviceResource(device->property);
400 if (ret != HDF_SUCCESS) {
401 HDF_LOGE("%s: read drs fail:%d", __func__, ret);
402 return ret;
403 }
404
405 gpioCntlr->count = IO_NUM_MAX;
406 gpioCntlr->priv = (void *)device->property;
407 gpioCntlr->ops = &g_GpioCntlrMethod;
408 (void)PlatformDeviceBind(&gpioCntlr->device, device);
409 ret = GpioCntlrAdd(gpioCntlr);
410 if (ret != HDF_SUCCESS) {
411 HDF_LOGE("%s: err add controller:%d", __func__, ret);
412 return ret;
413 }
414
415 return HDF_SUCCESS;
416 }
417
GpioDriverRelease(struct HdfDeviceObject * device)418 static void GpioDriverRelease(struct HdfDeviceObject *device)
419 {
420 struct GpioCntlr *gpioCntlr = NULL;
421
422 if (device == NULL) {
423 HDF_LOGE("%s: device is null!", __func__);
424 return;
425 }
426
427 gpioCntlr = GpioCntlrFromHdfDev(device);
428 if (gpioCntlr == NULL) {
429 HDF_LOGE("%s: no service binded!", __func__);
430 return;
431 }
432
433 app_gpiote_deinit();
434 GpioCntlrRemove(gpioCntlr);
435 }
436
437 struct HdfDriverEntry g_gpioDriverEntry = {
438 .moduleVersion = 1,
439 .moduleName = "HDF_PLATFORM_GPIO",
440 .Bind = GpioDriverBind,
441 .Init = GpioDriverInit,
442 .Release = GpioDriverRelease,
443 };
444
445 HDF_INIT(g_gpioDriverEntry);
446