blob: d7c0744070555fa446c70df7bc58095a6ec60c41 [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];
203 if (info->type != trig_type) {
204 if (ioctl(irq_fd(line), SC_IRQ_SET_TYPE, trig_type) < 0) {
205 return -EPERM;
206 }
207 }
208
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
311int lynq_irq_install(int line, irq_handler irq_test_handler, int trig_type)
312{
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)
319 line = line-117;
b.liu5fa9e772023-11-23 18:00:55 +0800320
r.xiaod94654a2024-04-22 02:47:51 -0700321 if (line < 0)
322 {
323 LOGE("lynq_irq_install error line:%d", line);
324 return -1;
325 }
326
r.xiao06db9a12024-04-14 18:51:15 -0700327#endif
328
329 ret = sc_irq_install(line, irq_test_handler, trig_type);
330 if (ret != 0)
331 {
332 LOGE("do_install_irq failed, ret:%d", ret);
333 return ret;
334 }
b.liu5fa9e772023-11-23 18:00:55 +0800335 return 0;
336}
337
r.xiao06db9a12024-04-14 18:51:15 -0700338
339/*****************************************
340* @brief:lynq_irq_uninstall
341* @param count [IN]:2
342* @param sum [OUT]:NA
343* @return :success 0, failed other
344* @todo:NA
345* @see:NA
346* @warning:NA
347******************************************/
348
349int lynq_irq_uninstall(int line)
b.liu5fa9e772023-11-23 18:00:55 +0800350{
r.xiaod94654a2024-04-22 02:47:51 -0700351#if defined(MBTK_PROJECT_T108)
352 line = line-117;
353#endif
354
r.xiao06db9a12024-04-14 18:51:15 -0700355 int ret;
356 ret = sc_irq_uninstall(line);
357 if (ret != 0)
358 {
359 LOGE("unistall failed, ret:%d", ret);
360 return ret;
361 }
362 LOGI("uninstall irq(%d) ok", line);
b.liu5fa9e772023-11-23 18:00:55 +0800363 return 0;
364}
365
r.xiao06db9a12024-04-14 18:51:15 -0700366
367/*****************************************
368* @brief:lynq_irq_set_type
369* @param count [IN]:2
370* @param sum [OUT]:NA
371* @return :success 0, failed other
372* @todo:NA
373* @see:NA
374* @warning:NA
375******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800376int lynq_irq_set_type(int line, int trig_type)
377{
r.xiaod94654a2024-04-22 02:47:51 -0700378#if defined(MBTK_PROJECT_T108)
379 line = line-117;
380#endif
381
r.xiao06db9a12024-04-14 18:51:15 -0700382 int ret;
383 if(trig_type < 0)
384 {
385 return -1;
386 }
387 ret = sc_irq_set_type(line, trig_type);
388 if (ret != 0)
389 {
390 LOGE("set_type failed, ret:%d", ret);
391 return ret;
392 }
b.liu5fa9e772023-11-23 18:00:55 +0800393 return 0;
r.xiao06db9a12024-04-14 18:51:15 -0700394
b.liu5fa9e772023-11-23 18:00:55 +0800395}
396
r.xiao06db9a12024-04-14 18:51:15 -0700397/*****************************************
398* @brief:lynq_irq_get_type
399* @param count [IN]:1
400* @param sum [OUT]:NA
401* @return :success >= 0, failed other
402* @todo:NA
403* @see:NA
404* @warning:NA
405******************************************/
406int lynq_irq_get_type(int line)
b.liu5fa9e772023-11-23 18:00:55 +0800407{
r.xiaod94654a2024-04-22 02:47:51 -0700408#if defined(MBTK_PROJECT_T108)
409 line = line-117;
410#endif
411
r.xiao06db9a12024-04-14 18:51:15 -0700412 int ret;
413 int trig_type;
414 ret = sc_irq_get_type(line, &trig_type);
r.xiaod94654a2024-04-22 02:47:51 -0700415 if (ret != 0)
r.xiao06db9a12024-04-14 18:51:15 -0700416 {
417 LOGE("get_type failed, ret:%d", ret);
418 return ret;
419 }
420 LOGI("get_type readback(%d)", trig_type);
421 return trig_type;
422}
b.liu5fa9e772023-11-23 18:00:55 +0800423
r.xiao06db9a12024-04-14 18:51:15 -0700424
425/*****************************************
426* @brief:lynq_irq_set_wake
427* @param count [IN]:2
428* @param sum [OUT]:NA
429* @return :success 0, failed other
430* @todo:NA
431* @see:NA
432* @warning:NA
433******************************************/
434int lynq_irq_set_wake(int line, int en)
435{
r.xiaod94654a2024-04-22 02:47:51 -0700436#if defined(MBTK_PROJECT_T108)
437 line = line-117;
438#endif
439
r.xiao06db9a12024-04-14 18:51:15 -0700440 int ret;
441 if((en != 0) && (en != 1))
442 {
443 LOGE("wake_state is not 0 or 1");
444 return -1;
445 }
r.xiaod94654a2024-04-22 02:47:51 -0700446
r.xiao06db9a12024-04-14 18:51:15 -0700447 ret = sc_irq_set_wake(line, en);
448 if (ret != 0)
449 {
450 LOGE("set_wake failed, ret:%d", ret);
451 return ret;
452 }
b.liu5fa9e772023-11-23 18:00:55 +0800453 return 0;
454}
455
r.xiao06db9a12024-04-14 18:51:15 -0700456/*****************************************
457* @brief:lynq_irq_get_wake
458* @param count [IN]:1
459* @param sum [OUT]:NA
460* @return :success >= 0, failed other
461* @todo:NA
462* @see:NA
463* @warning:NA
464******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800465int lynq_irq_get_wake(int line)
466{
r.xiaod94654a2024-04-22 02:47:51 -0700467#if defined(MBTK_PROJECT_T108)
468 line = line-117;
469#endif
470
r.xiao06db9a12024-04-14 18:51:15 -0700471 int ret;
472 int en;
473 ret = sc_irq_get_wake(line, &en);
474 if (ret != 0)
475 {
476 LOGE("get_wake failed, ret:%d", ret);
477 return ret;
478 }
r.xiaod94654a2024-04-22 02:47:51 -0700479
r.xiao06db9a12024-04-14 18:51:15 -0700480 LOGI("get_wake readback(%d)", en);
481 return en;
b.liu5fa9e772023-11-23 18:00:55 +0800482}
483
484
r.xiao06db9a12024-04-14 18:51:15 -0700485