blob: a26b05554f12868b648c3ab3ca19735ee80f5eb9 [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);
129
130 info = &irq_ctx.info[line];
131 info->line = line;
132 info->type = trig_type;
133 info->handler = handler;
134
135 if (ioctl(fd, SC_IRQ_INSTALL, trig_type) < 0) {
136 return -EPERM;
137 }
138
139 line_used(line) = 1;
140
141 if (!irq_init()) {
142 ret = libirq_init_thread();
143 if (ret) {
144 LOGE("libirq_init_thread, err:%d", ret);
145 return ret;
146 }
147
148 libirq_fd() = fd;
149 irq_init() = 1;
150 }
151
152 return 0;
153}
154
155/*
156 * free an interrupt allocated with sc_irq_install.
157 *
158 * line : The interrupt line
159 *
160 * return 0 if succeed, others failed
161 */
162int sc_irq_uninstall(unsigned int line)
163{
164 int fd;
165
166 if (line >= SC_LIBIRQ_MAX)
167 return -EINVAL;
168
169 if (!line_used(line))
170 return -ENODEV;
171
172 if (ioctl(irq_fd(line), SC_IRQ_UNINSTALL, 0) < 0) {
173 return -EPERM;
174 }
175
176 fd = libirq_fd();
177 if (fd)
178 close(fd);
179
180 line_used(line) = 0;
181
182 return 0;
183}
184
185/*
186 * set the irq trigger type for an irq.
187 *
188 * line : The interrupt line
189 * trig_type : edge or level type
190 *
191 * return 0 if succeed, others failed
192 */
193int sc_irq_set_type(unsigned int line, int trig_type)
194{
195 struct libirq_info *info;
196
197 if ((line >= SC_LIBIRQ_MAX) || (trig_type >= SC_LIBIRQ_TYPE_MAX))
198 return -EINVAL;
199
200 if (!line_used(line))
201 return -EEXIST;
202
203 info = &irq_ctx.info[line];
204 if (info->type != trig_type) {
205 if (ioctl(irq_fd(line), SC_IRQ_SET_TYPE, trig_type) < 0) {
206 return -EPERM;
207 }
208 }
209
210 info->type = trig_type;
211
212 return 0;
213}
214
215/*
216 * get the irq trigger type for an irq.
217 *
218 * line : The interrupt line
219 * trig_type : edge or level type
220 *
221 * return 0 if succeed, others failed
222 */
223int sc_irq_get_type(unsigned int line, int *trig_type)
224{
225 struct libirq_info *info;
226
227 if ((line >= SC_LIBIRQ_MAX) || !trig_type)
228 return -EINVAL;
229
230 if (!line_used(line))
231 return -EEXIST;
232
233 info = &irq_ctx.info[line];
234 *trig_type = info->type;
235
236 return 0;
237}
238
239/*
240 * control irq power management wakeup.
241 *
242 * line : The interrupt line
243 * en : enable/disable power management wakeup
244 *
245 * return 0 if succeed, others failed
246 */
247int sc_irq_set_wake(unsigned int line, int en)
248{
249 struct libirq_info *info;
250
251 if (line >= SC_LIBIRQ_MAX)
252 return -EINVAL;
253
254 if (!line_used(line))
255 return -EEXIST;
256
257 info = &irq_ctx.info[line];
258 if (info->wake != en) {
259 if (ioctl(irq_fd(line), SC_IRQ_SET_WAKE, en) < 0) {
260 return -EPERM;
261 }
262 }
263
264 info->wake = en;
265
266 return 0;
267}
268
269/*
270 * get the irq awake status for an irq.
271 *
272 * line : The interrupt line
273 * en : enable/disable power management wakeup
274 *
275 * return 0 if succeed, others failed
276 */
277int sc_irq_get_wake(unsigned int line, int *en)
278{
279 struct libirq_info *info;
280 unsigned int wake;
281
282 if (line >= SC_LIBIRQ_MAX)
283 return -EINVAL;
284
285 if (!line_used(line))
286 return -EEXIST;
287
288 if (ioctl(irq_fd(line), SC_IRQ_GET_WAKE, &wake) < 0) {
289 return -EPERM;
290 }
291
292 info = &irq_ctx.info[line];
293 info->wake = wake;
294 *en = wake;
295
296 return 0;
297}
298
299
300
301
302/*****************************************
303* @brief:lynq_irq_install
304* @param count [IN]:2
305* @param sum [OUT]:NA
306* @return :success 0, failed other
307* @todo:NA
308* @see:NA
309* @warning:NA
310******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800311
312int lynq_irq_install(int line, irq_handler irq_test_handler, int trig_type)
313{
r.xiao06db9a12024-04-14 18:51:15 -0700314 int ret;
315 if(trig_type < 0)
316 {
317 return -1;
318 }
319#if defined(MBTK_PROJECT_T108)
320 line = line-117;
b.liu5fa9e772023-11-23 18:00:55 +0800321
r.xiao06db9a12024-04-14 18:51:15 -0700322#endif
323
324 ret = sc_irq_install(line, irq_test_handler, trig_type);
325 if (ret != 0)
326 {
327 LOGE("do_install_irq failed, ret:%d", ret);
328 return ret;
329 }
b.liu5fa9e772023-11-23 18:00:55 +0800330 return 0;
331}
332
r.xiao06db9a12024-04-14 18:51:15 -0700333
334/*****************************************
335* @brief:lynq_irq_uninstall
336* @param count [IN]:2
337* @param sum [OUT]:NA
338* @return :success 0, failed other
339* @todo:NA
340* @see:NA
341* @warning:NA
342******************************************/
343
344int lynq_irq_uninstall(int line)
b.liu5fa9e772023-11-23 18:00:55 +0800345{
r.xiao06db9a12024-04-14 18:51:15 -0700346 int ret;
347 ret = sc_irq_uninstall(line);
348 if (ret != 0)
349 {
350 LOGE("unistall failed, ret:%d", ret);
351 return ret;
352 }
353 LOGI("uninstall irq(%d) ok", line);
b.liu5fa9e772023-11-23 18:00:55 +0800354 return 0;
355}
356
r.xiao06db9a12024-04-14 18:51:15 -0700357
358/*****************************************
359* @brief:lynq_irq_set_type
360* @param count [IN]:2
361* @param sum [OUT]:NA
362* @return :success 0, failed other
363* @todo:NA
364* @see:NA
365* @warning:NA
366******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800367int lynq_irq_set_type(int line, int trig_type)
368{
r.xiao06db9a12024-04-14 18:51:15 -0700369 int ret;
370 if(trig_type < 0)
371 {
372 return -1;
373 }
374 ret = sc_irq_set_type(line, trig_type);
375 if (ret != 0)
376 {
377 LOGE("set_type failed, ret:%d", ret);
378 return ret;
379 }
b.liu5fa9e772023-11-23 18:00:55 +0800380 return 0;
r.xiao06db9a12024-04-14 18:51:15 -0700381
b.liu5fa9e772023-11-23 18:00:55 +0800382}
383
r.xiao06db9a12024-04-14 18:51:15 -0700384/*****************************************
385* @brief:lynq_irq_get_type
386* @param count [IN]:1
387* @param sum [OUT]:NA
388* @return :success >= 0, failed other
389* @todo:NA
390* @see:NA
391* @warning:NA
392******************************************/
393int lynq_irq_get_type(int line)
b.liu5fa9e772023-11-23 18:00:55 +0800394{
r.xiao06db9a12024-04-14 18:51:15 -0700395 int ret;
396 int trig_type;
397 ret = sc_irq_get_type(line, &trig_type);
398 if (ret < 0)
399 {
400 LOGE("get_type failed, ret:%d", ret);
401 return ret;
402 }
403 LOGI("get_type readback(%d)", trig_type);
404 return trig_type;
405}
b.liu5fa9e772023-11-23 18:00:55 +0800406
r.xiao06db9a12024-04-14 18:51:15 -0700407
408/*****************************************
409* @brief:lynq_irq_set_wake
410* @param count [IN]:2
411* @param sum [OUT]:NA
412* @return :success 0, failed other
413* @todo:NA
414* @see:NA
415* @warning:NA
416******************************************/
417int lynq_irq_set_wake(int line, int en)
418{
419 int ret;
420 if((en != 0) && (en != 1))
421 {
422 LOGE("wake_state is not 0 or 1");
423 return -1;
424 }
425 ret = sc_irq_set_wake(line, en);
426 if (ret != 0)
427 {
428 LOGE("set_wake failed, ret:%d", ret);
429 return ret;
430 }
b.liu5fa9e772023-11-23 18:00:55 +0800431 return 0;
432}
433
r.xiao06db9a12024-04-14 18:51:15 -0700434/*****************************************
435* @brief:lynq_irq_get_wake
436* @param count [IN]:1
437* @param sum [OUT]:NA
438* @return :success >= 0, failed other
439* @todo:NA
440* @see:NA
441* @warning:NA
442******************************************/
b.liu5fa9e772023-11-23 18:00:55 +0800443int lynq_irq_get_wake(int line)
444{
r.xiao06db9a12024-04-14 18:51:15 -0700445 int ret;
446 int en;
447 ret = sc_irq_get_wake(line, &en);
448 if (ret != 0)
449 {
450 LOGE("get_wake failed, ret:%d", ret);
451 return ret;
452 }
453 LOGI("get_wake readback(%d)", en);
454 return en;
b.liu5fa9e772023-11-23 18:00:55 +0800455}
456
457
r.xiao06db9a12024-04-14 18:51:15 -0700458