1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 #include "device_resource_if.h"
20 #include "gpio/gpio_core.h"
21 #include "hdf_device_desc.h"
22 #include "osal.h"
23
24 #include <B91/gpio.h>
25
26 #include <b91_irq.h>
27
28 #define GPIO_INDEX_MAX ((sizeof(g_GpioIndexToActualPin) / sizeof(gpio_pin_e)))
29
30 struct B91GpioCntlr {
31 struct GpioCntlr cntlr;
32
33 uint8_t *pinReflectionMap;
34
35 struct {
36 bool irq_enabled;
37 }* config;
38
39 uint8_t pinNum;
40 };
41
42 static struct B91GpioCntlr g_B91GpioCntlr = {};
43
44 static const gpio_pin_e g_GpioIndexToActualPin[] = {
45 GPIO_PA0, /* 0 */
46 GPIO_PA1, /* 1 */
47 GPIO_PA2, /* 2 */
48 GPIO_PA3, /* 3 */
49 GPIO_PA4, /* 4 */
50 GPIO_PA5, /* 5 */
51 GPIO_PA6, /* 6 */
52 GPIO_PA7, /* 7 */
53
54 GPIO_PB0, /* 8 */
55 GPIO_PB1, /* 9 */
56 GPIO_PB2, /* 10 */
57 GPIO_PB3, /* 11 */
58 GPIO_PB4, /* 12 */
59 GPIO_PB5, /* 13 */
60 GPIO_PB6, /* 14 */
61 GPIO_PB7, /* 15 */
62
63 GPIO_PC0, /* 16 */
64 GPIO_PC1, /* 17 */
65 GPIO_PC2, /* 18 */
66 GPIO_PC3, /* 19 */
67 GPIO_PC4, /* 20 */
68 GPIO_PC5, /* 21 */
69 GPIO_PC6, /* 22 */
70 GPIO_PC7, /* 23 */
71
72 GPIO_PD0, /* 24 */
73 GPIO_PD1, /* 25 */
74 GPIO_PD2, /* 26 */
75 GPIO_PD3, /* 27 */
76 GPIO_PD4, /* 28 */
77 GPIO_PD5, /* 29 */
78 GPIO_PD6, /* 30 */
79 GPIO_PD7, /* 31 */
80
81 GPIO_PE0, /* 32 */
82 GPIO_PE1, /* 33 */
83 GPIO_PE2, /* 34 */
84 GPIO_PE3, /* 35 */
85 GPIO_PE4, /* 36 */
86 GPIO_PE5, /* 37 */
87 GPIO_PE6, /* 38 */
88 GPIO_PE7, /* 39 */
89
90 GPIO_PF0, /* 40 */
91 GPIO_PF1, /* 41 */
92 GPIO_PF2, /* 42 */
93 GPIO_PF3, /* 43 */
94 };
95
96 #define RETURN_ERR_IF_OUT_OF_RANGE(gpio) \
97 do { \
98 if (gpio >= pB91GpioCntlr->pinNum) { \
99 return HDF_ERR_INVALID_PARAM; \
100 } \
101 if (pB91GpioCntlr->pinReflectionMap[gpio] >= GPIO_INDEX_MAX) { \
102 return HDF_ERR_INVALID_PARAM; \
103 } \
104 } while (0)
105
106 static int32_t GpioDriverBind(struct HdfDeviceObject *device);
107 static int32_t GpioDriverInit(struct HdfDeviceObject *device);
108 static void GpioDriverRelease(struct HdfDeviceObject *device);
109
110 struct HdfDriverEntry g_GpioDriverEntry = {
111 .moduleVersion = 1,
112 .moduleName = "TELINK_HDF_PLATFORM_GPIO",
113 .Bind = GpioDriverBind,
114 .Init = GpioDriverInit,
115 .Release = GpioDriverRelease,
116 };
117
118 HDF_INIT(g_GpioDriverEntry);
119
120 static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val);
121 static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val);
122 static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir);
123 static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir);
124 static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode);
125 static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t local);
126 static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t local);
127 static int32_t GpioDevUnsetIrq(struct GpioCntlr *cntlr, uint16_t local);
128
129 /* GpioMethod Definitions */
130 struct GpioMethod g_GpioCntlrMethod = {
131 .request = NULL,
132 .release = NULL,
133 .write = GpioDevWrite,
134 .read = GpioDevRead,
135 .setDir = GpioDevSetDir,
136 .getDir = GpioDevGetDir,
137 .toIrq = NULL,
138 .setIrq = GpioDevSetIrq,
139 .unsetIrq = GpioDevUnsetIrq,
140 .enableIrq = GpioDevEnableIrq,
141 .disableIrq = GpioDevDisableIrq,
142 };
143
GpioIrqHandler(void)144 _attribute_ram_code_ static void GpioIrqHandler(void)
145 {
146 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
147
148 for (size_t i = 0; i < pB91GpioCntlr->pinNum; ++i) {
149 if (pB91GpioCntlr->config[i].irq_enabled) {
150 GpioCntlrIrqCallback(&pB91GpioCntlr->cntlr, i);
151 }
152 }
153
154 gpio_clr_irq_status(FLD_GPIO_IRQ_CLR);
155 }
156
GetGpioDeviceResource(struct B91GpioCntlr * cntlr,const struct DeviceResourceNode * resourceNode)157 static int32_t GetGpioDeviceResource(struct B91GpioCntlr *cntlr, const struct DeviceResourceNode *resourceNode)
158 {
159 uint32_t pinIndex;
160 struct DeviceResourceIface *dri = NULL;
161
162 dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
163 if (dri == NULL) {
164 HDF_LOGE("DeviceResourceIface is invalid!");
165 return HDF_ERR_INVALID_OBJECT;
166 }
167
168 if (dri->GetUint8(resourceNode, "pinNum", &cntlr->pinNum, 0) != HDF_SUCCESS) {
169 HDF_LOGE("Failed to read pinNum!");
170 return HDF_FAILURE;
171 }
172
173 cntlr->pinReflectionMap = (uint8_t *)OsalMemAlloc(sizeof(uint8_t) * cntlr->pinNum);
174 if (cntlr->pinReflectionMap == NULL) {
175 HDF_LOGE("%s: OsalMemAlloc error", __func__);
176 return HDF_ERR_MALLOC_FAIL;
177 }
178
179 cntlr->config = OsalMemAlloc(sizeof(cntlr->config[0]) * cntlr->pinNum);
180 if (cntlr->config == NULL) {
181 HDF_LOGE("%s: OsalMemAlloc error", __func__);
182 return HDF_ERR_MALLOC_FAIL;
183 }
184
185 for (uint32_t i = 0; i < cntlr->pinNum; i++) {
186 if (dri->GetUint32ArrayElem(resourceNode, "pinMap", i, &pinIndex, 0) != HDF_SUCCESS) {
187 HDF_LOGE("Failed to read pinMap!");
188 return HDF_FAILURE;
189 }
190
191 cntlr->pinReflectionMap[i] = pinIndex;
192 }
193
194 return HDF_SUCCESS;
195 }
196
GpioDriverInit(struct HdfDeviceObject * device)197 static int32_t GpioDriverInit(struct HdfDeviceObject *device)
198 {
199 int32_t ret;
200 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
201
202 HDF_LOGD("%s: Enter", __func__);
203
204 if (device == NULL || device->property == NULL) {
205 HDF_LOGE("%s: device or property NULL!", __func__);
206 return HDF_ERR_INVALID_OBJECT;
207 }
208
209 ret = GetGpioDeviceResource(pB91GpioCntlr, device->property);
210 if (ret != HDF_SUCCESS) {
211 HDF_LOGE("%s: GetGpioDeviceResource failed: %ld", __func__, ret);
212 return ret;
213 }
214
215 pB91GpioCntlr->cntlr.count = pB91GpioCntlr->pinNum;
216 pB91GpioCntlr->cntlr.priv = (void *)device->property;
217 pB91GpioCntlr->cntlr.ops = &g_GpioCntlrMethod;
218
219 struct GpioCntlr *gpioCntlr = &pB91GpioCntlr->cntlr;
220 (void)PlatformDeviceBind(&gpioCntlr->device, device);
221
222 ret = GpioCntlrAdd(&pB91GpioCntlr->cntlr);
223 if (ret != HDF_SUCCESS) {
224 HDF_LOGE("%s: GpioCntlrAdd failed: %ld", __func__, ret);
225 return ret;
226 }
227
228 B91IrqRegister(IRQ25_GPIO, (HWI_PROC_FUNC)GpioIrqHandler, 0);
229 plic_interrupt_enable(IRQ25_GPIO);
230
231 HDF_LOGD("%s: dev service:%s init success!", __func__, HdfDeviceGetServiceName(device));
232 return ret;
233 }
234
GpioDriverRelease(struct HdfDeviceObject * device)235 static void GpioDriverRelease(struct HdfDeviceObject *device)
236 {
237 struct GpioCntlr *gpioCntlr = NULL;
238 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
239
240 HDF_LOGD("%s: Enter", __func__);
241
242 if (device == NULL) {
243 HDF_LOGE("%s: device is null!", __func__);
244 return;
245 }
246
247 if (pB91GpioCntlr->pinReflectionMap) {
248 OsalMemFree(pB91GpioCntlr->pinReflectionMap);
249 pB91GpioCntlr->pinReflectionMap = NULL;
250 }
251
252 gpioCntlr = GpioCntlrFromHdfDev(device);
253 if (gpioCntlr == NULL) {
254 HDF_LOGE("%s: no service bound!", __func__);
255 return;
256 }
257 GpioCntlrRemove(gpioCntlr);
258 }
259
GpioDriverBind(struct HdfDeviceObject * device)260 static int32_t GpioDriverBind(struct HdfDeviceObject *device)
261 {
262 (void)device;
263
264 return HDF_SUCCESS;
265 }
266
GpioDevWrite(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t val)267 static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
268 {
269 (void)cntlr;
270 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
271
272 RETURN_ERR_IF_OUT_OF_RANGE(gpio);
273
274 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[gpio]];
275 HDF_LOGD("%s: %d - %d", __func__, gpioPin, val);
276
277 if (val == GPIO_VAL_HIGH) {
278 gpio_set_level(gpioPin, 1);
279 } else if (val == GPIO_VAL_LOW) {
280 gpio_set_level(gpioPin, 0);
281 } else {
282 return HDF_ERR_NOT_SUPPORT;
283 }
284
285 return HDF_SUCCESS;
286 }
287
GpioDevRead(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * val)288 static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
289 {
290 (void)cntlr;
291 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
292
293 RETURN_ERR_IF_OUT_OF_RANGE(gpio);
294
295 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[gpio]];
296 HDF_LOGD("%s: %d", __func__, gpioPin);
297
298 if (gpio_get_level(gpioPin) == 1) {
299 *val = GPIO_VAL_HIGH;
300 } else {
301 *val = GPIO_VAL_LOW;
302 }
303
304 return HDF_SUCCESS;
305 }
306
GpioDevSetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t dir)307 static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
308 {
309 (void)cntlr;
310 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
311
312 RETURN_ERR_IF_OUT_OF_RANGE(gpio);
313
314 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[gpio]];
315 HDF_LOGD("%s: %d - %d", __func__, gpioPin, dir);
316
317 if (dir == GPIO_DIR_OUT) {
318 gpio_function_en(gpioPin);
319 gpio_input_dis(gpioPin);
320 gpio_output_en(gpioPin);
321 } else if (dir == GPIO_DIR_IN) {
322 gpio_function_en(gpioPin);
323 gpio_input_en(gpioPin);
324 gpio_output_dis(gpioPin);
325 } else {
326 return HDF_ERR_NOT_SUPPORT;
327 }
328
329 return HDF_SUCCESS;
330 }
331
GpioDevGetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * dir)332 static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
333 {
334 (void)cntlr;
335 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
336
337 RETURN_ERR_IF_OUT_OF_RANGE(gpio);
338
339 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[gpio]];
340 HDF_LOGD("%s: %d", __func__, gpio);
341
342 if (gpio_is_input_en(gpioPin)) {
343 *dir = GPIO_DIR_IN;
344 } else if (gpio_is_output_en(gpioPin)) {
345 *dir = GPIO_DIR_OUT;
346 } else {
347 *dir = GPIO_DIR_ERR;
348 }
349
350 return HDF_SUCCESS;
351 }
352
GpioDevSetIrq(struct GpioCntlr * cntlr,uint16_t local,uint16_t mode)353 static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode)
354 {
355 (void)cntlr;
356 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
357
358 RETURN_ERR_IF_OUT_OF_RANGE(local);
359
360 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[local]];
361 HDF_LOGD("%s: %d", __func__, local);
362
363 switch (mode & 0x0F) {
364 case GPIO_IRQ_TRIGGER_HIGH: {
365 gpio_set_irq(gpioPin, INTR_HIGH_LEVEL);
366 break;
367 }
368 case GPIO_IRQ_TRIGGER_LOW: {
369 gpio_set_irq(gpioPin, INTR_LOW_LEVEL);
370 break;
371 }
372 case GPIO_IRQ_TRIGGER_RISING: {
373 gpio_set_irq(gpioPin, INTR_RISING_EDGE);
374 break;
375 }
376 case GPIO_IRQ_TRIGGER_FALLING: {
377 gpio_set_irq(gpioPin, INTR_FALLING_EDGE);
378 break;
379 }
380 default: {
381 return HDF_ERR_BSP_PLT_API_ERR;
382 }
383 }
384
385 return HDF_SUCCESS;
386 }
387
GpioDevUnsetIrq(struct GpioCntlr * cntlr,uint16_t local)388 static int32_t GpioDevUnsetIrq(struct GpioCntlr *cntlr, uint16_t local)
389 {
390 (void)cntlr;
391 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
392
393 RETURN_ERR_IF_OUT_OF_RANGE(local);
394
395 return HDF_SUCCESS;
396 }
397
GpioDevEnableIrq(struct GpioCntlr * cntlr,uint16_t local)398 static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t local)
399 {
400 (void)cntlr;
401 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
402
403 RETURN_ERR_IF_OUT_OF_RANGE(local);
404
405 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[local]];
406 HDF_LOGD("%s: %d", __func__, local);
407
408 gpio_irq_en(gpioPin);
409
410 pB91GpioCntlr->config[local].irq_enabled = true;
411
412 return HDF_SUCCESS;
413 }
414
GpioDevDisableIrq(struct GpioCntlr * cntlr,uint16_t local)415 static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t local)
416 {
417 (void)cntlr;
418 struct B91GpioCntlr *pB91GpioCntlr = &g_B91GpioCntlr;
419
420 RETURN_ERR_IF_OUT_OF_RANGE(local);
421
422 gpio_pin_e gpioPin = g_GpioIndexToActualPin[pB91GpioCntlr->pinReflectionMap[local]];
423 HDF_LOGD("%s: %d", __func__, local);
424
425 gpio_irq_dis(gpioPin);
426
427 pB91GpioCntlr->config[local].irq_enabled = false;
428
429 return HDF_SUCCESS;
430 }
431