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