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