• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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