• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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 
83     dev = &g_gpioPinMap[gpio];
84     if ((uint16_t)dev->port >= ASR_GPIO_TOTAL_NUM) {
85         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (uint16_t)dev->port);
86         return;
87     }
88     GpioCntlrIrqCallback(&g_gpioCntlr, gpio);
89 }
90 
91 /* dispatch */
GpioDispatch(struct HdfDeviceIoClient * client,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)92 int32_t GpioDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
93 {
94     (void)cmdId;
95     if (client == NULL || client->device == NULL || data == NULL || reply == NULL) {
96         HDF_LOGE("%s: client or client->device is NULL", __func__);
97         return HDF_ERR_INVALID_PARAM;
98     }
99     return HDF_SUCCESS;
100 }
101 
102 /* dev api */
GpioDevWrite(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t val)103 static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
104 {
105     (void)cntlr;
106     uint32_t ret = 0;
107     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
108 
109     if (val) {
110         ret = asr_gpio_output_high(dev);
111     } else {
112         ret = asr_gpio_output_low(dev);
113     }
114     if (EIO == ret) {
115         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
116         return HDF_ERR_NOT_SUPPORT;
117     }
118 
119     return HDF_SUCCESS;
120 }
121 
GpioDevRead(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * val)122 static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
123 {
124     (void)cntlr;
125     uint32_t ret = 0;
126     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
127 
128     if ((cntlr == NULL) || (val == NULL)) {
129         return HDF_ERR_INVALID_PARAM;
130     }
131     ret = asr_gpio_input_get(dev, val);
132     if (EIO == ret) {
133         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
134         return HDF_ERR_NOT_SUPPORT;
135     }
136 
137     return HDF_SUCCESS;
138 }
139 
GpioDevSetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t dir)140 static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
141 {
142     (void)cntlr;
143     uint32_t ret = 0;
144     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
145 
146     if (cntlr == NULL) {
147         return HDF_ERR_INVALID_PARAM;
148     }
149     dev->config = (asr_gpio_config_t)dir;
150     ret = asr_gpio_init(dev);
151     if (EIO == ret) {
152         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
153         return HDF_ERR_NOT_SUPPORT;
154     }
155 
156     return HDF_SUCCESS;
157 }
158 
GpioDevGetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * dir)159 static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
160 {
161     (void)cntlr;
162     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
163 
164     if ((cntlr == NULL) || (dir == NULL)) {
165         return HDF_ERR_INVALID_PARAM;
166     }
167     if (dev->port >= ASR_GPIO_TOTAL_NUM) {
168         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
169         return HDF_ERR_NOT_SUPPORT;
170     }
171     *dir = (uint16_t)dev->config;
172 
173     return HDF_SUCCESS;
174 }
175 
GpioDevSetIrq(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t mode)176 static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)
177 {
178     (void)cntlr;
179     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
180 
181     HDF_LOGE("%s %d, pin:%d", __func__, __LINE__, (uint16_t)dev->port);
182     if (dev->port >= ASR_GPIO_TOTAL_NUM) {
183         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
184         return HDF_ERR_NOT_SUPPORT;
185     }
186 
187     if ((mode == OSAL_IRQF_TRIGGER_RISING) || (mode == OSAL_IRQF_TRIGGER_FALLING)
188         || (mode == (OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING))) {
189         g_gpioIrqCfg[gpio] = (asr_gpio_config_t)mode;
190     } else {
191         HDF_LOGE("%s %d, error mode:%d", __func__, __LINE__, mode);
192         return HDF_ERR_NOT_SUPPORT;
193     }
194 
195     return HDF_SUCCESS;
196 }
197 
GpioDevUnSetIrq(struct GpioCntlr * cntlr,uint16_t gpio)198 static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio)
199 {
200     (void)cntlr;
201     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
202 
203     if (dev->port >= ASR_GPIO_TOTAL_NUM) {
204         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, dev->port);
205         return HDF_ERR_NOT_SUPPORT;
206     }
207 
208     return HDF_SUCCESS;
209 }
210 
GpioDevEnableIrq(struct GpioCntlr * cntlr,uint16_t gpio)211 static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
212 {
213     (void)cntlr;
214     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
215 
216     if ((uint16_t)dev->port >= ASR_GPIO_TOTAL_NUM) {
217         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (uint16_t)dev->port);
218         return HDF_ERR_NOT_SUPPORT;
219     }
220 
221     dev->config = ASR_IRQ_MODE;
222     asr_gpio_init(dev);
223     asr_gpio_enable_irq(dev, g_gpioIrqCfg[gpio], OemGpioIrqHdl, (void *)gpio);
224     HDF_LOGE("%s %d, pin:%d", __func__, __LINE__, (uint16_t)dev->port);
225 
226     return HDF_SUCCESS;
227 }
228 
GpioDevDisableIrq(struct GpioCntlr * cntlr,uint16_t gpio)229 static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
230 {
231     (void)cntlr;
232     asr_gpio_dev_t *dev = &g_gpioPinMap[gpio];
233 
234     if ((uint16_t)dev->port >= ASR_GPIO_TOTAL_NUM) {
235         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (uint16_t)dev->port);
236         return HDF_ERR_NOT_SUPPORT;
237     }
238     asr_gpio_disable_irq(dev);
239 
240     return HDF_SUCCESS;
241 }
242 
243 struct GpioMethod g_GpioCntlrMethod = {
244     .request = NULL,
245     .release = NULL,
246     .write = GpioDevWrite,
247     .read = GpioDevRead,
248     .setDir = GpioDevSetDir,
249     .getDir = GpioDevGetDir,
250     .toIrq = NULL,
251     .setIrq = GpioDevSetIrq,
252     .unsetIrq = GpioDevUnSetIrq,
253     .enableIrq = GpioDevEnableIrq,
254     .disableIrq = GpioDevDisableIrq,
255 };
256 
InitGpioDevice(struct GpioDevice * device)257 static int InitGpioDevice(struct GpioDevice *device)
258 {
259     uint32_t ret = 0;
260 
261     if (device == NULL) {
262         HDF_LOGE("%s: device is NULL", __func__);
263         return HDF_ERR_INVALID_PARAM;
264     }
265 
266     HDF_LOGE("%s %d, pin:%d, mode:%d", __func__, __LINE__, device->dev.port, device->dev.config);
267     ret = asr_gpio_init(&device->dev);
268     if (EIO == ret) {
269         HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, device->dev.port);
270         return HDF_ERR_NOT_SUPPORT;
271     }
272 
273     return HDF_SUCCESS;
274 }
275 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
276 #define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config)
GetGpioDeviceResource(struct GpioDevice * device)277 static uint32_t GetGpioDeviceResource(struct GpioDevice *device)
278 {
279     uint32_t relPin;
280     int32_t ret;
281     struct GpioResource *resource = NULL;
282     if (device == NULL) {
283         HDF_LOGE("%s: device is NULL", __func__);
284         return HDF_ERR_INVALID_PARAM;
285     }
286     resource = &device->resource;
287     if (resource == NULL) {
288         HDF_LOGE("%s: resource is NULL", __func__);
289         return HDF_ERR_INVALID_OBJECT;
290     }
291     resource->pinNum = HCS_PROP(PLATFORM_GPIO_CONFIG, pinNum);
292     uint32_t pins[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, pin));
293     uint32_t realPins[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, realPin));
294     uint32_t configs[] = HCS_ARRAYS(HCS_NODE(PLATFORM_GPIO_CONFIG, config));
295     for (size_t i = 0; i < resource->pinNum; i++) {
296         resource->pin = pins[i];
297         resource->realPin = realPins[i];
298         resource->config = configs[i];
299 
300         relPin = resource->realPin;// / DECIMALNUM * OCTALNUM + resource->realPin % DECIMALNUM;
301         g_gpioPinMap[resource->pin].port = (uint8_t)relPin;
302         g_gpioPinMap[resource->pin].config = (asr_gpio_config_t)resource->config;
303         device->dev.config = (asr_gpio_config_t)resource->config;
304         resource->pin = relPin;
305         device->dev.port = relPin;
306 
307         ret = InitGpioDevice(device);
308         if (ret != HDF_SUCCESS) {
309             HDF_LOGE("InitGpioDevice FAIL\r\n");
310             return HDF_FAILURE;
311         }
312     }
313 
314     return HDF_SUCCESS;
315 }
316 #else
GetGpioDeviceResource(struct GpioDevice * device,const struct DeviceResourceNode * resourceNode)317 static uint32_t GetGpioDeviceResource(
318     struct GpioDevice *device, const struct DeviceResourceNode *resourceNode)
319 {
320     uint32_t relPin;
321     int32_t ret;
322     struct GpioResource *resource = NULL;
323     struct DeviceResourceIface *dri = NULL;
324     if (device == NULL || resourceNode == NULL) {
325         HDF_LOGE("%s: device is NULL", __func__);
326         return HDF_ERR_INVALID_PARAM;
327     }
328     resource = &device->resource;
329     if (resource == NULL) {
330         HDF_LOGE("%s: resource is NULL", __func__);
331         return HDF_ERR_INVALID_OBJECT;
332     }
333     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
334     if (dri == NULL || dri->GetUint32 == NULL) {
335         HDF_LOGE("DeviceResourceIface is invalid");
336         return HDF_ERR_INVALID_OBJECT;
337     }
338 
339     if (dri->GetUint32(resourceNode, "pinNum", &resource->pinNum, 0) != HDF_SUCCESS) {
340         HDF_LOGE("gpio config read pinNum fail");
341         return HDF_FAILURE;
342     }
343 
344     for (size_t i = 0; i < resource->pinNum; i++) {
345         if (dri->GetUint32ArrayElem(resourceNode, "pin", i, &resource->pin, 0) != HDF_SUCCESS) {
346             HDF_LOGE("gpio config read pin fail");
347             return HDF_FAILURE;
348         }
349 
350         if (dri->GetUint32ArrayElem(resourceNode, "realPin", i, &resource->realPin, 0) != HDF_SUCCESS) {
351             HDF_LOGE("gpio config read realPin fail");
352             return HDF_FAILURE;
353         }
354 
355         if (dri->GetUint32ArrayElem(resourceNode, "config", i, &resource->config, 0) != HDF_SUCCESS) {
356             HDF_LOGE("gpio config read config fail");
357             return HDF_FAILURE;
358         }
359 
360         relPin = resource->realPin;// / DECIMALNUM * OCTALNUM + resource->realPin % DECIMALNUM;
361         g_gpioPinMap[resource->pin].port = (uint8_t)relPin;
362         g_gpioPinMap[resource->pin].config = (asr_gpio_config_t)resource->config;
363         device->dev.config = (asr_gpio_config_t)resource->config;
364         device->dev.port = relPin;
365         resource->pin = relPin;
366 
367         ret = InitGpioDevice(device);
368         if (ret != HDF_SUCCESS) {
369             HDF_LOGE("InitGpioDevice FAIL\r\n");
370             return HDF_FAILURE;
371         }
372     }
373 
374     return HDF_SUCCESS;
375 }
376 #endif
377 
378 
AttachGpioDevice(struct GpioCntlr * gpioCntlr,const struct HdfDeviceObject * device)379 static int32_t AttachGpioDevice(struct GpioCntlr *gpioCntlr, const struct HdfDeviceObject *device)
380 {
381     int32_t ret;
382 
383     struct GpioDevice *gpioDevice = NULL;
384 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
385     if (device == NULL) {
386 #else
387     if (device == NULL || device->property == NULL) {
388 #endif
389         HDF_LOGE("%s: param is NULL", __func__);
390         return HDF_ERR_INVALID_PARAM;
391     }
392 
393     gpioDevice = (struct GpioDevice *)OsalMemAlloc(sizeof(struct GpioDevice));
394     if (gpioDevice == NULL) {
395         HDF_LOGE("%s: OsalMemAlloc gpioDevice error", __func__);
396         return HDF_ERR_MALLOC_FAIL;
397     }
398 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
399     ret = GetGpioDeviceResource(gpioDevice);
400 #else
401     ret = GetGpioDeviceResource(gpioDevice, device->property);
402 #endif
403     if (ret != HDF_SUCCESS) {
404         (void)OsalMemFree(gpioDevice);
405         return HDF_FAILURE;
406     }
407 
408     (void)OsalMemFree(gpioDevice);
409     gpioCntlr->count = gpioDevice->resource.pinNum;
410 
411     return HDF_SUCCESS;
412 }
413 
414 static int32_t GpioDriverInit(struct HdfDeviceObject *device)
415 {
416     int32_t ret;
417     struct GpioCntlr *gpioCntlr = NULL;
418 
419     if (device == NULL) {
420         HDF_LOGE("%s: device is NULL", __func__);
421         return HDF_ERR_INVALID_PARAM;
422     }
423 
424     ret = PlatformDeviceBind(&g_gpioCntlr.device, device);
425     if (ret != HDF_SUCCESS) {
426         HDF_LOGE("%s: bind hdf device failed:%d", __func__, ret);
427         return ret;
428     }
429 
430     gpioCntlr = GpioCntlrFromHdfDev(device);
431     if (gpioCntlr == NULL) {
432         HDF_LOGE("GpioCntlrFromHdfDev fail\r\n");
433         return HDF_DEV_ERR_NO_DEVICE_SERVICE;
434     }
435 
436     ret = AttachGpioDevice(gpioCntlr, device); // GpioCntlr add GpioDevice to priv
437     if (ret != HDF_SUCCESS) {
438         HDF_LOGE("AttachGpioDevice fail\r\n");
439         return HDF_DEV_ERR_ATTACHDEV_FAIL;
440     }
441 
442     gpioCntlr->ops = &g_GpioCntlrMethod; // register callback
443     ret = GpioCntlrAdd(gpioCntlr);
444     if (ret != HDF_SUCCESS) {
445         HDF_LOGE("GpioCntlrAdd fail %d\r\n", gpioCntlr->start);
446         return HDF_FAILURE;
447     }
448     return HDF_SUCCESS;
449 }
450 
451 static void GpioDriverRelease(struct HdfDeviceObject *device)
452 {
453     struct GpioCntlr *gpioCntlr = NULL;
454 
455     if (device == NULL) {
456         HDF_LOGE("%s: device is NULL", __func__);
457         return;
458     }
459 
460     gpioCntlr = GpioCntlrFromHdfDev(device);
461     if (gpioCntlr == NULL) {
462         HDF_LOGE("GpioCntlrFromHdfDev fail\r\n");
463         return;
464     }
465 
466     (void)OsalMemFree(gpioCntlr->priv);
467     gpioCntlr->count = 0;
468 }
469 
470 /* HdfDriverEntry definitions */
471 struct HdfDriverEntry g_GpioDriverEntry = {
472     .moduleVersion = 1,
473     .moduleName = "ASR_GPIO_MODULE_HDF",
474     .Init = GpioDriverInit,
475     .Release = GpioDriverRelease,
476 };
477 HDF_INIT(g_GpioDriverEntry);
478