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