blob: 3563b0b0c8e66feb5fdb3b4a837a0000d3fcbdb8 [file] [log] [blame]
b.liu4e243dc2023-11-27 11:20:00 +08001#include "lynq-irq.h"
2#include "mbtk_type.h"
r.xiao06db9a12024-04-14 18:51:15 -07003#include "mbtk_info_api.h"
4#include "mbtk_log.h"
5
6
7#include <ctype.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <pthread.h>
12
13#define _GNU_SOURCE
14
15#include <errno.h>
16#include <fcntl.h>
17#include <limits.h>
18#include <poll.h>
19
20#include <sys/ioctl.h>
21#include <sys/stat.h>
22#include <sys/sysmacros.h>
23#include <sys/types.h>
24#include <unistd.h>
25
26
27struct libirq_info {
28 unsigned int line;
29 unsigned int type;
30 int wake;
31 int fd;
32 irq_handler handler;
33 unsigned int used;
34};
35
36struct libirq_context {
37 unsigned int inited;
38 int fd;
39 pthread_t th;
40 struct libirq_info info[SC_LIBIRQ_MAX];
41};
42static struct libirq_context irq_ctx = {0};
43
44#define irq_init() irq_ctx.inited
45#define line_used(l) irq_ctx.info[l].used
46#define irq_fd(l) irq_ctx.info[l].fd
47#define libirq_fd() irq_ctx.fd
48
49static void *libirq_loop(void *arg)
50{
51 unsigned int int_status = 0;
52 int fd = libirq_fd();
53 int ret = 0;
54 int i;
55
56 while(1) {
57 ret = ioctl(fd, SC_IRQ_GET_STATUS, &int_status);
58 if (ret < 0) {
59 LOGE("libirq_loop get status failed:%d", ret);
60 } else {
61/* printf("libirq_loop get status :0x%x\n", int_status); */
62 }
63
64 for (i=0; i<SC_LIBIRQ_MAX; i++) {
65 if ((int_status & (1<<i)) && line_used(i) && irq_ctx.info[i].handler) {
66 irq_ctx.info[i].handler();
67
68 ret = ioctl(fd, SC_IRQ_CLEAR_STATUS, 0);
69 if (ret < 0) {
70 LOGE("libirq_loop clear status failed:%d", ret);
71 }
72 }
73 }
74 }
75
76 return NULL;
77}
78
79static int libirq_init_thread(void)
80{
81 int ret = 0;
82 pthread_attr_t attribute;
83
84 pthread_attr_init(&attribute);
85 pthread_attr_setstacksize(&attribute, 32*1024);
86
87 ret = pthread_create(&irq_ctx.th, &attribute, libirq_loop, NULL);
88 if(ret) {
89 return ret;
90 }
91
92 return 0;
93}
94
95/*
96 * Add a handler for an interrupt line.
97 *
98 * line : The interrupt line
99 * handler : Function to be called when the IRQ occurs.
100 * trig_type : rising edge or fallling edge
101 *
102 * return 0 if succeed, others failed
103 */
104int sc_irq_install(unsigned int line, irq_handler handler, int trig_type)
105{
106 int fd;
107 struct libirq_info *info;
108 char *usr_name;
109 int ret = 0;
110
111 if ((line >= SC_LIBIRQ_MAX) || (handler == NULL) || (trig_type >= SC_LIBIRQ_TYPE_MAX))
112 return -EINVAL;
113
114 if (line_used(line))
115 return -EEXIST;
116
117 ret = asprintf(&usr_name, "%s%d", SC_IRQ_DEV, line);
118 if (ret < 0) {
119 return -ENOMEM;
120 }
121
122 fd = open(usr_name, O_RDWR);
123 if(fd < 0) {
124 free(usr_name);
125 return -ENODEV;
126 }
127 irq_fd(line) = fd;
128 free(usr_name);
r.xiao06db9a12024-04-14 18:51:15 -0700129 info = &irq_ctx.info[line];
130 info->line = line;
131 info->type = trig_type;
132 info->handler = handler;
133
134 if (ioctl(fd, SC_IRQ_INSTALL, trig_type) < 0) {
135 return -EPERM;
136 }
137
138 line_used(line) = 1;
139
140 if (!irq_init()) {
141 ret = libirq_init_thread();
142 if (ret) {
143 LOGE("libirq_init_thread, err:%d", ret);
144 return ret;
145 }
146
147 libirq_fd() = fd;
148 irq_init() = 1;
149 }
150
151 return 0;
152}
153
154/*
155 * free an interrupt allocated with sc_irq_install.
156 *
157 * line : The interrupt line
158 *
159 * return 0 if succeed, others failed
160 */
161int sc_irq_uninstall(unsigned int line)
162{
163 int fd;
164
165 if (line >= SC_LIBIRQ_MAX)
166 return -EINVAL;
167
168 if (!line_used(line))
169 return -ENODEV;
170
171 if (ioctl(irq_fd(line), SC_IRQ_UNINSTALL, 0) < 0) {
172 return -EPERM;
173 }
174
175 fd = libirq_fd();
176 if (fd)
177 close(fd);
178
179 line_used(line) = 0;
180
181 return 0;
182}
183
184/*
185 * set the irq trigger type for an irq.
186 *
187 * line : The interrupt line
188 * trig_type : edge or level type
189 *
190 * return 0 if succeed, others failed
191 */
192int sc_irq_set_type(unsigned int line, int trig_type)
193{
194 struct libirq_info *info;
195
196 if ((line >= SC_LIBIRQ_MAX) || (trig_type >= SC_LIBIRQ_TYPE_MAX))
197 return -EINVAL;
198
199 if (!line_used(line))
200 return -EEXIST;
201
202 info = &irq_ctx.info[line];
n.nieb3c04722024-09-13 20:15:56 -0700203 //if (info->type != trig_type) {
r.xiao06db9a12024-04-14 18:51:15 -0700204 if (ioctl(irq_fd(line), SC_IRQ_SET_TYPE, trig_type) < 0) {
205 return -EPERM;
206 }
n.nieb3c04722024-09-13 20:15:56 -0700207 //}
r.xiao06db9a12024-04-14 18:51:15 -0700208
209 info->type = trig_type;
210
211 return 0;
212}
213
214/*
215 * get the irq trigger type for an irq.
216 *
217 * line : The interrupt line
218 * trig_type : edge or level type
219 *
220 * return 0 if succeed, others failed
221 */
222int sc_irq_get_type(unsigned int line, int *trig_type)
223{
224 struct libirq_info *info;
225
226 if ((line >= SC_LIBIRQ_MAX) || !trig_type)
227 return -EINVAL;
228
229 if (!line_used(line))
230 return -EEXIST;
231
232 info = &irq_ctx.info[line];
233 *trig_type = info->type;
234
235 return 0;
236}
237
238/*
239 * control irq power management wakeup.
240 *
241 * line : The interrupt line
242 * en : enable/disable power management wakeup
243 *
244 * return 0 if succeed, others failed
245 */
246int sc_irq_set_wake(unsigned int line, int en)
247{
248 struct libirq_info *info;
249
250 if (line >= SC_LIBIRQ_MAX)
251 return -EINVAL;
252
253 if (!line_used(line))
254 return -EEXIST;
255
256 info = &irq_ctx.info[line];
257 if (info->wake != en) {
258 if (ioctl(irq_fd(line), SC_IRQ_SET_WAKE, en) < 0) {
259 return -EPERM;
260 }
261 }
262
263 info->wake = en;
264
265 return 0;
266}
267
268/*
269 * get the irq awake status for an irq.
270 *
271 * line : The interrupt line
272 * en : enable/disable power management wakeup
273 *
274 * return 0 if succeed, others failed
275 */
276int sc_irq_get_wake(unsigned int line, int *en)
277{
278 struct libirq_info *info;
279 unsigned int wake;
280
281 if (line >= SC_LIBIRQ_MAX)
282 return -EINVAL;
283
284 if (!line_used(line))
285 return -EEXIST;
r.xiaod94654a2024-04-22 02:47:51 -0700286
r.xiao06db9a12024-04-14 18:51:15 -0700287 if (ioctl(irq_fd(line), SC_IRQ_GET_WAKE, &wake) < 0) {
288 return -EPERM;
289 }
290
291 info = &irq_ctx.info[line];
292 info->wake = wake;
293 *en = wake;
294
295 return 0;
296}
297
298
299
300
301/*****************************************
302* @brief:lynq_irq_install
303* @param count [IN]:2
304* @param sum [OUT]:NA
305* @return :success 0, failed other
306* @todo:NA
307* @see:NA
308* @warning:NA
309******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800310
r.xiao917e64f2024-04-22 04:18:28 -0700311int lynq_irq_install(int line, irq_handler irq_test_handler, trig_type_e trig_type)
b.liu5fa9e772023-11-23 18:00:55 +0800312{
r.xiao06db9a12024-04-14 18:51:15 -0700313 int ret;
314 if(trig_type < 0)
315 {
316 return -1;
317 }
318#if defined(MBTK_PROJECT_T108)
r.xiaoe3325072024-06-06 02:12:04 -0700319
r.xiao70938852024-06-12 05:35:31 -0700320 if (trig_type != 0 && trig_type != 1)
r.xiaoe3325072024-06-06 02:12:04 -0700321 {
322 LOGE("lynq_irq_install error trig_type:%d", trig_type);
323 return -1;
324 }
325
r.xiao06db9a12024-04-14 18:51:15 -0700326 line = line-117;
b.liu5fa9e772023-11-23 18:00:55 +0800327
r.xiaod94654a2024-04-22 02:47:51 -0700328 if (line < 0)
329 {
330 LOGE("lynq_irq_install error line:%d", line);
331 return -1;
332 }
333
r.xiao06db9a12024-04-14 18:51:15 -0700334#endif
335
336 ret = sc_irq_install(line, irq_test_handler, trig_type);
337 if (ret != 0)
338 {
339 LOGE("do_install_irq failed, ret:%d", ret);
340 return ret;
341 }
b.liu5fa9e772023-11-23 18:00:55 +0800342 return 0;
343}
344
r.xiao06db9a12024-04-14 18:51:15 -0700345
346/*****************************************
347* @brief:lynq_irq_uninstall
348* @param count [IN]:2
349* @param sum [OUT]:NA
350* @return :success 0, failed other
351* @todo:NA
352* @see:NA
353* @warning:NA
354******************************************/
355
356int lynq_irq_uninstall(int line)
b.liu5fa9e772023-11-23 18:00:55 +0800357{
r.xiaod94654a2024-04-22 02:47:51 -0700358#if defined(MBTK_PROJECT_T108)
359 line = line-117;
360#endif
361
r.xiao06db9a12024-04-14 18:51:15 -0700362 int ret;
363 ret = sc_irq_uninstall(line);
364 if (ret != 0)
365 {
366 LOGE("unistall failed, ret:%d", ret);
367 return ret;
368 }
369 LOGI("uninstall irq(%d) ok", line);
b.liu5fa9e772023-11-23 18:00:55 +0800370 return 0;
371}
372
r.xiao06db9a12024-04-14 18:51:15 -0700373
374/*****************************************
375* @brief:lynq_irq_set_type
376* @param count [IN]:2
377* @param sum [OUT]:NA
378* @return :success 0, failed other
379* @todo:NA
380* @see:NA
381* @warning:NA
382******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800383int lynq_irq_set_type(int line, int trig_type)
384{
r.xiaod94654a2024-04-22 02:47:51 -0700385#if defined(MBTK_PROJECT_T108)
386 line = line-117;
r.xiaoe3325072024-06-06 02:12:04 -0700387
r.xiao70938852024-06-12 05:35:31 -0700388 if (trig_type != 0 && trig_type != 1)
r.xiaoe3325072024-06-06 02:12:04 -0700389 {
390 LOGE("lynq_irq_set_type error trig_type:%d", trig_type);
391 return -1;
392 }
r.xiaod94654a2024-04-22 02:47:51 -0700393#endif
394
r.xiao06db9a12024-04-14 18:51:15 -0700395 int ret;
396 if(trig_type < 0)
397 {
398 return -1;
399 }
400 ret = sc_irq_set_type(line, trig_type);
401 if (ret != 0)
402 {
403 LOGE("set_type failed, ret:%d", ret);
404 return ret;
405 }
b.liu5fa9e772023-11-23 18:00:55 +0800406 return 0;
r.xiao06db9a12024-04-14 18:51:15 -0700407
b.liu5fa9e772023-11-23 18:00:55 +0800408}
409
r.xiao06db9a12024-04-14 18:51:15 -0700410/*****************************************
411* @brief:lynq_irq_get_type
412* @param count [IN]:1
413* @param sum [OUT]:NA
414* @return :success >= 0, failed other
415* @todo:NA
416* @see:NA
417* @warning:NA
418******************************************/
419int lynq_irq_get_type(int line)
b.liu5fa9e772023-11-23 18:00:55 +0800420{
r.xiaod94654a2024-04-22 02:47:51 -0700421#if defined(MBTK_PROJECT_T108)
422 line = line-117;
423#endif
424
r.xiao06db9a12024-04-14 18:51:15 -0700425 int ret;
426 int trig_type;
427 ret = sc_irq_get_type(line, &trig_type);
r.xiaod94654a2024-04-22 02:47:51 -0700428 if (ret != 0)
r.xiao06db9a12024-04-14 18:51:15 -0700429 {
430 LOGE("get_type failed, ret:%d", ret);
431 return ret;
432 }
433 LOGI("get_type readback(%d)", trig_type);
434 return trig_type;
435}
b.liu5fa9e772023-11-23 18:00:55 +0800436
r.xiao06db9a12024-04-14 18:51:15 -0700437
438/*****************************************
439* @brief:lynq_irq_set_wake
440* @param count [IN]:2
441* @param sum [OUT]:NA
442* @return :success 0, failed other
443* @todo:NA
444* @see:NA
445* @warning:NA
446******************************************/
447int lynq_irq_set_wake(int line, int en)
448{
r.xiaod94654a2024-04-22 02:47:51 -0700449#if defined(MBTK_PROJECT_T108)
450 line = line-117;
451#endif
452
r.xiao06db9a12024-04-14 18:51:15 -0700453 int ret;
454 if((en != 0) && (en != 1))
455 {
456 LOGE("wake_state is not 0 or 1");
457 return -1;
458 }
r.xiaod94654a2024-04-22 02:47:51 -0700459
r.xiao06db9a12024-04-14 18:51:15 -0700460 ret = sc_irq_set_wake(line, en);
461 if (ret != 0)
462 {
463 LOGE("set_wake failed, ret:%d", ret);
464 return ret;
465 }
b.liu5fa9e772023-11-23 18:00:55 +0800466 return 0;
467}
468
r.xiao06db9a12024-04-14 18:51:15 -0700469/*****************************************
470* @brief:lynq_irq_get_wake
471* @param count [IN]:1
472* @param sum [OUT]:NA
473* @return :success >= 0, failed other
474* @todo:NA
475* @see:NA
476* @warning:NA
477******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800478int lynq_irq_get_wake(int line)
479{
r.xiaod94654a2024-04-22 02:47:51 -0700480#if defined(MBTK_PROJECT_T108)
481 line = line-117;
482#endif
483
r.xiao06db9a12024-04-14 18:51:15 -0700484 int ret;
485 int en;
486 ret = sc_irq_get_wake(line, &en);
487 if (ret != 0)
488 {
489 LOGE("get_wake failed, ret:%d", ret);
490 return ret;
491 }
r.xiaod94654a2024-04-22 02:47:51 -0700492
r.xiao06db9a12024-04-14 18:51:15 -0700493 LOGI("get_wake readback(%d)", en);
494 return en;
b.liu5fa9e772023-11-23 18:00:55 +0800495}
496
497
r.xiao06db9a12024-04-14 18:51:15 -0700498