1 /*
2  * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
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 <stdlib.h>
10 #include "gpio_core.h"
11 #include "hdf_core_log.h"
12 #include "osal_irq.h"
13 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
14 #include "hcs_macro.h"
15 #include "hdf_config_macro.h"
16 #else
17 #include "device_resource_if.h"
18 #endif
19 #include "duet_gpio.h"
20 
21 #define ASR_GPIO_TOTAL_NUM    DUET_GPIO_TOTAL_NUM
22 #define asr_gpio_config_t duet_gpio_config_t
23 #define ASR_ANALOG_MODE DUET_ANALOG_MODE
24 #define ASR_IRQ_MODE DUET_IRQ_MODE
25 #define ASR_INPUT_PULL_UP DUET_INPUT_PULL_UP
26 #define ASR_INPUT_PULL_DOWN DUET_INPUT_PULL_DOWN
27 #define ASR_INPUT_HIGH_IMPEDANCE DUET_INPUT_HIGH_IMPEDANCE
28 #define ASR_OUTPUT_PUSH_PULL DUET_OUTPUT_PUSH_PULL
29 #define ASR_OUTPUT_OPEN_DRAIN_NO_PULL DUET_OUTPUT_OPEN_DRAIN_NO_PULL
30 #define ASR_OUTPUT_OPEN_DRAIN_PULL_UP DUET_OUTPUT_OPEN_DRAIN_PULL_UP
31 
32 #define asr_gpio_dev_t duet_gpio_dev_t
33 #define asr_gpio_irq_trigger_t duet_gpio_irq_trigger_t
34 #define asr_gpio_irq_handler_t duet_gpio_irq_handler_t
35 #define asr_gpio_cb_t duet_gpio_cb_t
36 #define asr_gpio_init duet_gpio_init
37 #define asr_gpio_output_high duet_gpio_output_high
38 #define asr_gpio_output_low duet_gpio_output_low
39 #define asr_gpio_output_toggle duet_gpio_output_toggle
40 #define asr_gpio_input_get duet_gpio_input_get
41 #define asr_gpio_enable_irq duet_gpio_enable_irq
42 #define asr_gpio_disable_irq duet_gpio_disable_irq
43 #define asr_gpio_clear_irq duet_gpio_clear_irq
44 #define asr_gpio_finalize duet_gpio_finalize
45 
46 #define HDF_LOG_TAG GPIO_ASR
47 
48 struct GpioResource {
49     uint32_t pin;
50     uint32_t realPin;
51     uint32_t config;
52     uint32_t pinNum;
53     uint32_t type; /**< Type of the input event EV_KEY */
54     uint32_t code; /**< Specific code item of the input event KEY_POWER*/
55     unsigned long physBase;
56 };
57 
58 enum GpioDeviceState {
59     GPIO_DEVICE_UNINITIALIZED = 0x0u,
60     GPIO_DEVICE_INITIALIZED = 0x1u,
61 };
62 
63 struct GpioDevice {
64     asr_gpio_dev_t dev;
65     struct GpioResource resource;
66 };
67 
68 static struct GpioCntlr g_gpioCntlr;
69 struct OemGpioIrqHandler {
70     uint8_t port;
71     GpioIrqFunc func;
72     void *arg;
73 };
74 
75 static asr_gpio_dev_t g_gpioPinMap[ASR_GPIO_TOTAL_NUM] = {0};
76 static asr_gpio_irq_trigger_t g_gpioIrqCfg[ASR_GPIO_TOTAL_NUM] = {0};
77 
OemGpioIrqHdl(uint16_t *arg)78 static void OemGpioIrqHdl(uint16_t *arg)
79 {
80     asr_gpio_dev_t *dev = NULL;
81     uint16_t gpio = (uint16_t)arg;
82     if (gpio > ASR_GPIO_TOTAL_NUM) {
83         HDF_LOGE("invalid gpio");
84         return;
85     }
86 
87     dev = &g_gpioPinMap[gpio];
88     if ((uint16_t)dev->port >= ASR_GPIO_TOTAL_NUM) {
89         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (uint16_t)dev->port);
90         return;
91     }
92     GpioCntlrIrqCallback(&g_gpioCntlr, gpio);
93 }
94 
95 /* dispatch */
GpioDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)96 int32_t GpioDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
97 {
98     (void)cmdId;
99     if (client == NULL || client->device == NULL || data == NULL || reply == NULL) {
100         HDF_LOGE("%s: client or client->device is NULL", __func__);
101         return HDF_ERR_INVALID_PARAM;
102     }
103     return HDF_SUCCESS;
104 }
105 
106 /* dev api */
GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)107 static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
108 {
109     (void)cntlr;
110     uint32_t ret = 0;
111     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
112 
113     if (val) {
114         ret = asr_gpio_output_high(dev);
115     } else {
116         ret = asr_gpio_output_low(dev);
117     }
118     if (EIO == ret) {
119         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
120         return HDF_ERR_NOT_SUPPORT;
121     }
122 
123     return HDF_SUCCESS;
124 }
125 
GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)126 static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
127 {
128     (void)cntlr;
129     uint32_t ret = 0;
130     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
131 
132     if ((cntlr == NULL) || (val == NULL)) {
133         return HDF_ERR_INVALID_PARAM;
134     }
135     ret = asr_gpio_input_get(dev, val);
136     if (EIO == ret) {
137         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
138         return HDF_ERR_NOT_SUPPORT;
139     }
140 
141     return HDF_SUCCESS;
142 }
143 
GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)144 static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
145 {
146     (void)cntlr;
147     uint32_t ret = 0;
148     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
149 
150     if (cntlr == NULL) {
151         return HDF_ERR_INVALID_PARAM;
152     }
153     dev->config = (asr_gpio_config_t)dir;
154     ret = asr_gpio_init(dev);
155     if (EIO == ret) {
156         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
157         return HDF_ERR_NOT_SUPPORT;
158     }
159 
160     return HDF_SUCCESS;
161 }
162 
GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)163 static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
164 {
165     (void)cntlr;
166     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
167 
168     if ((cntlr == NULL) || (dir == NULL)) {
169         return HDF_ERR_INVALID_PARAM;
170     }
171     if (dev->port >= ASR_GPIO_TOTAL_NUM) {
172         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
173         return HDF_ERR_NOT_SUPPORT;
174     }
175     *dir = (uint16_t)dev->config;
176 
177     return HDF_SUCCESS;
178 }
179 
GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)180 static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)
181 {
182     (void)cntlr;
183     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
184 
185     HDF_LOGE("%s %d, pin:%d", __func__, __LINE__, (uint16_t)dev->port);
186     if (dev->port >= ASR_GPIO_TOTAL_NUM) {
187         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
188         return HDF_ERR_NOT_SUPPORT;
189     }
190 
191     if ((mode == OSAL_IRQF_TRIGGER_RISING) || (mode == OSAL_IRQF_TRIGGER_FALLING)
192         || (mode == (OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING))) {
193         g_gpioIrqCfg[gpio] = (asr_gpio_config_t)mode;
194     } else {
195         HDF_LOGE("%s %d, error mode:%d", __func__, __LINE__, mode);
196         return HDF_ERR_NOT_SUPPORT;
197     }
198 
199     return HDF_SUCCESS;
200 }
201 
GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio)202 static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio)
203 {
204     (void)cntlr;
205     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
206 
207     if (dev->port >= ASR_GPIO_TOTAL_NUM) {
208         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
209         return HDF_ERR_NOT_SUPPORT;
210     }
211 
212     return HDF_SUCCESS;
213 }
214 
GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio)215 static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
216 {
217     (void)cntlr;
218     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
219 
220     if ((uint16_t)dev->port >= ASR_GPIO_TOTAL_NUM) {
221         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (uint16_t)dev->port);
222         return HDF_ERR_NOT_SUPPORT;
223     }
224 
225     dev->config = ASR_IRQ_MODE;
226     asr_gpio_init(dev);
227     asr_gpio_enable_irq(dev, g_gpioIrqCfg[gpio], OemGpioIrqHdl, (void *)gpio);
228     HDF_LOGE("%s %d, pin:%d", __func__, __LINE__, (uint16_t)dev->port);
229 
230     return HDF_SUCCESS;
231 }
232 
GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio)233 static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
234 {
235     (void)cntlr;
236     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
237 
238     if ((uint16_t)dev->port >= ASR_GPIO_TOTAL_NUM) {
239         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (uint16_t)dev->port);
240         return HDF_ERR_NOT_SUPPORT;
241     }
242     asr_gpio_disable_irq(dev);
243 
244     return HDF_SUCCESS;
245 }
246 
247 struct GpioMethod g_GpioCntlrMethod = {
248     .request = NULL,
249     .release = NULL,
250     .write = GpioDevWrite,
251     .read = GpioDevRead,
252     .setDir = GpioDevSetDir,
253     .getDir = GpioDevGetDir,
254     .toIrq = NULL,
255     .setIrq = GpioDevSetIrq,
256     .unsetIrq = GpioDevUnSetIrq,
257     .enableIrq = GpioDevEnableIrq,
258     .disableIrq = GpioDevDisableIrq,
259 };
260 
InitGpioDevice(struct GpioDevice *device)261 static int InitGpioDevice(struct GpioDevice *device)
262 {
263     uint32_t ret = 0;
264 
265     if (device == NULL) {
266         HDF_LOGE("%s: device is NULL", __func__);
267         return HDF_ERR_INVALID_PARAM;
268     }
269 
270     HDF_LOGE("%s %d, pin:%d, mode:%d", __func__, __LINE__, device->dev.port, device->dev.config);
271     ret = asr_gpio_init(&device->dev);
272     if (EIO == ret) {
273         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, device->dev.port);
274         return HDF_ERR_NOT_SUPPORT;
275     }
276 
277     return HDF_SUCCESS;
278 }
279 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
280 #define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config)
GetGpioDeviceResource(struct GpioDevice *device)281 static uint32_t GetGpioDeviceResource(struct GpioDevice *device)
282 {
283     uint32_t relPin;
284     int32_t ret;
285     struct GpioResource *resource = NULL;
286     if (device == NULL) {
287         HDF_LOGE("%s: device is NULL", __func__);
288         return HDF_ERR_INVALID_PARAM;
289     }
290     resource = &device->resource;
291     if (resource == NULL) {
292         HDF_LOGE("%s: resource is NULL", __func__);
293         return HDF_ERR_INVALID_OBJECT;
294     }
295     resource->pinNum = HCS_PROP(PLATFORM_GPIO_CONFIG, pinNum);
296     uint32_t pins[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, pin));
297     uint32_t realPins[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, realPin));
298     uint32_t configs[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, config));
299     for (size_t i = 0; i < resource->pinNum; i++) {
300         resource->pin = pins[i];
301         resource->realPin = realPins[i];
302         resource->config = configs[i];
303 
304         relPin = resource->realPin;// / DECIMALNUM * OCTALNUM + resource->realPin % DECIMALNUM;
305         g_gpioPinMap[resource->pin].port = (uint8_t)relPin;
306         g_gpioPinMap[resource->pin].config = (asr_gpio_config_t)resource->config;
307         device->dev.config = (asr_gpio_config_t)resource->config;
308         resource->pin = relPin;
309         device->dev.port = relPin;
310 
311         ret = InitGpioDevice(device);
312         if (ret != HDF_SUCCESS) {
313             HDF_LOGE("InitGpioDevice FAIL\r\n");
314             return HDF_FAILURE;
315         }
316     }
317 
318     return HDF_SUCCESS;
319 }
320 #else
GetGpioDeviceResource( struct GpioDevice *device, const struct DeviceResourceNode *resourceNode)321 static uint32_t GetGpioDeviceResource(
322     struct GpioDevice *device, const struct DeviceResourceNode *resourceNode)
323 {
324     uint32_t relPin;
325     int32_t ret;
326     struct GpioResource *resource = NULL;
327     struct DeviceResourceIface *dri = NULL;
328     if (device == NULL || resourceNode == NULL) {
329         HDF_LOGE("%s: device is NULL", __func__);
330         return HDF_ERR_INVALID_PARAM;
331     }
332     resource = &device->resource;
333     if (resource == NULL) {
334         HDF_LOGE("%s: resource is NULL", __func__);
335         return HDF_ERR_INVALID_OBJECT;
336     }
337     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
338     if (dri == NULL || dri->GetUint32 == NULL) {
339         HDF_LOGE("DeviceResourceIface is invalid");
340         return HDF_ERR_INVALID_OBJECT;
341     }
342 
343     if (dri->GetUint32(resourceNode, "pinNum", &resource->pinNum, 0) != HDF_SUCCESS) {
344         HDF_LOGE("gpio config read pinNum fail");
345         return HDF_FAILURE;
346     }
347 
348     for (size_t i = 0; i < resource->pinNum; i++) {
349         if (dri->GetUint32ArrayElem(resourceNode, "pin", i, &resource->pin, 0) != HDF_SUCCESS) {
350             HDF_LOGE("gpio config read pin fail");
351             return HDF_FAILURE;
352         }
353 
354         if (dri->GetUint32ArrayElem(resourceNode, "realPin", i, &resource->realPin, 0) != HDF_SUCCESS) {
355             HDF_LOGE("gpio config read realPin fail");
356             return HDF_FAILURE;
357         }
358 
359         if (dri->GetUint32ArrayElem(resourceNode, "config", i, &resource->config, 0) != HDF_SUCCESS) {
360             HDF_LOGE("gpio config read config fail");
361             return HDF_FAILURE;
362         }
363 
364         relPin = resource->realPin;// / DECIMALNUM * OCTALNUM + resource->realPin % DECIMALNUM;
365         g_gpioPinMap[resource->pin].port = (uint8_t)relPin;
366         g_gpioPinMap[resource->pin].config = (asr_gpio_config_t)resource->config;
367         device->dev.config = (asr_gpio_config_t)resource->config;
368         device->dev.port = relPin;
369         resource->pin = relPin;
370 
371         ret = InitGpioDevice(device);
372         if (ret != HDF_SUCCESS) {
373             HDF_LOGE("InitGpioDevice FAIL\r\n");
374             return HDF_FAILURE;
375         }
376     }
377 
378     return HDF_SUCCESS;
379 }
380 #endif
381 
382 
AttachGpioDevice(struct GpioCntlr *gpioCntlr, const struct HdfDeviceObject *device)383 static int32_t AttachGpioDevice(struct GpioCntlr *gpioCntlr, const struct HdfDeviceObject *device)
384 {
385     int32_t ret;
386 
387     struct GpioDevice *gpioDevice = NULL;
388 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
389     if (device == NULL) {
390 #else
391     if (device == NULL || device->property == NULL) {
392 #endif
393         HDF_LOGE("%s: param is NULL", __func__);
394         return HDF_ERR_INVALID_PARAM;
395     }
396 
397     gpioDevice = (struct GpioDevice *)OsalMemAlloc(sizeof(struct GpioDevice));
398     if (gpioDevice == NULL) {
399         HDF_LOGE("%s: OsalMemAlloc gpioDevice error", __func__);
400         return HDF_ERR_MALLOC_FAIL;
401     }
402 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
403     ret = GetGpioDeviceResource(gpioDevice);
404 #else
405     ret = GetGpioDeviceResource(gpioDevice, device->property);
406 #endif
407     if (ret != HDF_SUCCESS) {
408         (void)OsalMemFree(gpioDevice);
409         return HDF_FAILURE;
410     }
411 
412     (void)OsalMemFree(gpioDevice);
413     gpioCntlr->count = gpioDevice->resource.pinNum;
414 
415     return HDF_SUCCESS;
416 }
417 
418 static int32_t GpioDriverInit(struct HdfDeviceObject *device)
419 {
420     int32_t ret;
421     struct GpioCntlr *gpioCntlr = NULL;
422 
423     if (device == NULL) {
424         HDF_LOGE("%s: device is NULL", __func__);
425         return HDF_ERR_INVALID_PARAM;
426     }
427 
428     ret = PlatformDeviceBind(&g_gpioCntlr.device, device);
429     if (ret != HDF_SUCCESS) {
430         HDF_LOGE("%s: bind hdf device failed:%d", __func__, ret);
431         return ret;
432     }
433 
434     gpioCntlr = GpioCntlrFromHdfDev(device);
435     if (gpioCntlr == NULL) {
436         HDF_LOGE("GpioCntlrFromHdfDev fail\r\n");
437         return HDF_DEV_ERR_NO_DEVICE_SERVICE;
438     }
439 
440     ret = AttachGpioDevice(gpioCntlr, device); // GpioCntlr add GpioDevice to priv
441     if (ret != HDF_SUCCESS) {
442         HDF_LOGE("AttachGpioDevice fail\r\n");
443         return HDF_DEV_ERR_ATTACHDEV_FAIL;
444     }
445 
446     gpioCntlr->ops = &g_GpioCntlrMethod; // register callback
447     ret = GpioCntlrAdd(gpioCntlr);
448     if (ret != HDF_SUCCESS) {
449         HDF_LOGE("GpioCntlrAdd fail %d\r\n", gpioCntlr->start);
450         return HDF_FAILURE;
451     }
452     return HDF_SUCCESS;
453 }
454 
455 static void GpioDriverRelease(struct HdfDeviceObject *device)
456 {
457     struct GpioCntlr *gpioCntlr = NULL;
458 
459     if (device == NULL) {
460         HDF_LOGE("%s: device is NULL", __func__);
461         return;
462     }
463 
464     gpioCntlr = GpioCntlrFromHdfDev(device);
465     if (gpioCntlr == NULL) {
466         HDF_LOGE("GpioCntlrFromHdfDev fail\r\n");
467         return;
468     }
469 
470     (void)OsalMemFree(gpioCntlr->priv);
471     gpioCntlr->count = 0;
472 }
473 
474 /* HdfDriverEntry definitions */
475 struct HdfDriverEntry g_GpioDriverEntry = {
476     .moduleVersion = 1,
477     .moduleName = "ASR_GPIO_MODULE_HDF",
478     .Init = GpioDriverInit,
479     .Release = GpioDriverRelease,
480 };
481 HDF_INIT(g_GpioDriverEntry);
482