2 #include <linux/module.h>
3 #include <linux/file.h>
5 #include <linux/cdev.h>
6 #include <linux/miscdevice.h>
7 #include <linux/kernel.h> //min()
8 #include <linux/uaccess.h> //copy_to_user()
9 #include <linux/sched.h> //TASK_INTERRUPTIBLE/signal_pending/schedule
10 #include <linux/poll.h>
11 #include <linux/io.h> //ioremap()
12 #include <linux/of_fdt.h>
13 #include <linux/seq_file.h>
14 #include <asm/setup.h>
15 #include <linux/interrupt.h>
16 #include <linux/proc_fs.h>
17 #include <asm/atomic.h>
19 #define ATF_LOG_CTRL_BUF_SIZE 256
20 #define ATF_CRASH_MAGIC_NO 0xdead1abf
21 //#define atf_log_lock() atomic_inc(&(atf_buf_vir_ctl->info.atf_buf_lock))
22 //#define atf_log_unlock() atomic_dec(&(atf_buf_vir_ctl->info.atf_buf_lock))
24 #define atf_log_lock() ((void)0)
25 #define atf_log_unlock() ((void)0)
26 static int has_dumped
;
27 static unsigned char *atf_log_buffer
;
28 static unsigned char *atf_crash_log_buf
;
29 static wait_queue_head_t atf_log_wq
;
32 static void *_memcpy(void *dest
, const void *src
, size_t count
)
42 #define memcpy _memcpy
45 typedef union atf_log_ctl
{
47 unsigned int atf_buf_addr
;
48 unsigned int atf_buf_size
;
49 unsigned int atf_write_pos
;
50 unsigned int atf_read_pos
;
51 //atf_spinlock_t atf_buf_lock;
52 unsigned int atf_buf_lock
;
53 unsigned int atf_buf_unread_size
;
54 unsigned int atf_irq_count
;
55 unsigned int atf_reader_alive
;
56 unsigned long long atf_write_seq
;
57 unsigned long long atf_read_seq
;
58 unsigned int atf_aee_dbg_buf_addr
;
59 unsigned int atf_aee_dbg_buf_size
;
60 unsigned int atf_crash_log_addr
;
61 unsigned int atf_crash_log_size
;
62 unsigned int atf_crash_flag
;
64 unsigned char data
[ATF_LOG_CTRL_BUF_SIZE
];
68 struct ipanic_atf_log_rec
{
71 unsigned long start_idx
;
74 atf_log_ctl_t
*atf_buf_vir_ctl
;
75 unsigned long atf_buf_phy_ctl
;
76 unsigned int atf_buf_len
;
77 unsigned char *atf_log_vir_addr
;
78 unsigned int atf_log_len
;
79 unsigned int write_index
;
80 unsigned int read_index
;
82 static void show_data(unsigned long addr
, int nbytes
, const char *name
);
83 static unsigned int pos_to_index(unsigned int pos
)
85 return pos
- (atf_buf_phy_ctl
+ ATF_LOG_CTRL_BUF_SIZE
);
88 static unsigned int index_to_pos(unsigned int index
)
90 return (atf_buf_phy_ctl
+ ATF_LOG_CTRL_BUF_SIZE
) + index
;
93 static size_t atf_log_dump_nolock(unsigned char *buffer
, unsigned int start
, size_t size
)
98 unsigned char *p
= atf_log_vir_addr
+ start
;
99 write_index
= pos_to_index(atf_buf_vir_ctl
->info
.atf_write_pos
);
100 least
= (write_index
+ atf_buf_len
- start
) % atf_buf_len
;
103 len
= min(size
, atf_log_len
- start
);
105 memcpy(buffer
, atf_log_vir_addr
+ start
, size
);
107 size_t right
= atf_log_len
- start
;
108 while (skip
< right
) {
114 //pr_notice("skip:%d, right:%d, %p\n", skip, right, p);
115 memcpy(buffer
, p
, right
- skip
);
116 memcpy(buffer
, atf_log_vir_addr
, size
- right
);
123 static size_t atf_log_dump_nolock(unsigned char *buffer
, struct ipanic_atf_log_rec
*rec
, size_t size
)
127 write_index
= pos_to_index(atf_buf_vir_ctl
->info
.atf_write_pos
);
128 //find the first letter to read
129 while ((write_index
+ atf_log_len
- rec
->start_idx
) % atf_log_len
> 0) {
130 if (*(atf_log_vir_addr
+ rec
->start_idx
) != 0)
133 if (rec
->start_idx
== atf_log_len
)
136 least
= (write_index
+ atf_buf_len
- rec
->start_idx
) % atf_buf_len
;
139 len
= min(size
, atf_log_len
- rec
->start_idx
);
141 memcpy(buffer
, atf_log_vir_addr
+ rec
->start_idx
, size
);
143 size_t right
= atf_log_len
- rec
->start_idx
;
144 memcpy(buffer
, atf_log_vir_addr
+ rec
->start_idx
, right
);
145 memcpy(buffer
, atf_log_vir_addr
, size
- right
);
147 rec
->start_idx
+= size
;
148 rec
->start_idx
%= atf_log_len
;
151 //static size_t atf_log_dump(unsigned char *buffer, unsigned int start, size_t size)
152 static size_t atf_log_dump(unsigned char *buffer
, struct ipanic_atf_log_rec
*rec
, size_t size
)
156 //ret = atf_log_dump_nolock(buffer, start, size);
157 ret
= atf_log_dump_nolock(buffer
, rec
, size
);
159 //show_data(atf_log_vir_addr, 24*1024, "atf_buf");
163 size_t ipanic_atflog_buffer(void *data
, unsigned char *buffer
, size_t sz_buffer
)
165 if (atf_buf_len
== 0)
167 static bool last_read
= false;
169 struct ipanic_atf_log_rec
*rec
= (struct ipanic_atf_log_rec
*)data
;
170 //pr_notice("ipanic_atf_log: need %d, rec:%d, %d, %lu\n", sz_buffer, rec->total_size, rec->has_read, rec->start_idx);
171 if (rec
->total_size
== rec
->has_read
|| last_read
) {
175 if (rec
->has_read
== 0) {
176 if (atf_buf_vir_ctl
->info
.atf_write_seq
< atf_log_len
&& atf_buf_vir_ctl
->info
.atf_write_seq
< sz_buffer
)
180 write_index
= pos_to_index(atf_buf_vir_ctl
->info
.atf_write_pos
);
182 rec
->start_idx
= (write_index
+ atf_log_len
- rec
->total_size
) % atf_log_len
;
185 //count = atf_log_dump_nolock(buffer, (rec->start_idx + rec->has_read) % atf_log_len, sz_buffer);
186 //count = atf_log_dump_nolock(buffer, rec, sz_buffer);
187 count
= atf_log_dump(buffer
, rec
, sz_buffer
);
188 //pr_notice("ipanic_atf_log: dump %d\n", count);
189 rec
->has_read
+= count
;
190 if (count
!= sz_buffer
)
195 static ssize_t
atf_log_write(struct kiocb
*iocb
, const struct iovec
*iov
, unsigned long nr_segs
, loff_t ppos
)
197 wake_up_interruptible(&atf_log_wq
);
201 static ssize_t
do_read_log_to_usr(char __user
*buf
, size_t count
)
205 write_index
= pos_to_index(atf_buf_vir_ctl
->info
.atf_write_pos
);
206 read_index
= pos_to_index(atf_buf_vir_ctl
->info
.atf_read_pos
);
207 least
= (write_index
+ atf_buf_len
- read_index
) % atf_buf_len
;
210 len
= min(count
, atf_log_len
- read_index
);
212 if (copy_to_user(buf
, atf_log_vir_addr
+ read_index
, count
))
215 size_t right
= atf_log_len
- read_index
;
216 if (copy_to_user(buf
, atf_log_vir_addr
+ read_index
, right
))
218 if (copy_to_user(buf
, atf_log_vir_addr
, count
- right
))
221 read_index
= (read_index
+ count
) % atf_log_len
;
225 static int atf_log_fix_reader()
227 if (atf_buf_vir_ctl
->info
.atf_write_seq
< atf_log_len
) {
228 atf_buf_vir_ctl
->info
.atf_read_seq
= 0;
229 atf_buf_vir_ctl
->info
.atf_read_pos
= index_to_pos(0);
231 atf_buf_vir_ctl
->info
.atf_read_seq
= atf_buf_vir_ctl
->info
.atf_write_seq
;
232 atf_buf_vir_ctl
->info
.atf_read_pos
= atf_buf_vir_ctl
->info
.atf_write_pos
;
237 static int atf_log_open(struct inode
*inode
, struct file
*file
)
240 ret
= nonseekable_open(inode
, file
);
243 file
->private_data
= NULL
;
245 if (!atf_buf_vir_ctl
->info
.atf_reader_alive
) {
246 atf_log_fix_reader();
248 atf_buf_vir_ctl
->info
.atf_reader_alive
++;
253 static int atf_log_release(struct inode
*ignored
, struct file
*file
)
255 atf_buf_vir_ctl
->info
.atf_reader_alive
--;
259 static ssize_t
atf_log_read(struct file
*file
, char __user
*buf
, size_t count
, loff_t
*pos
)
262 unsigned int write_pos
;
263 unsigned int read_pos
;
269 write_pos
= atf_buf_vir_ctl
->info
.atf_write_pos
;
270 read_pos
= atf_buf_vir_ctl
->info
.atf_read_pos
;
271 //pr_notice("atf_log_read: wait in wq\n");
272 prepare_to_wait(&atf_log_wq
, &wait
, TASK_INTERRUPTIBLE
);
273 ret
= (write_pos
== read_pos
);
277 if (file
->f_flags
& O_NONBLOCK
) {
281 if (signal_pending(current
)) {
287 finish_wait(&atf_log_wq
, &wait
);
288 //pr_notice("atf_log_read: finish wait\n");
292 if (unlikely(write_pos
== read_pos
)) {
296 ret
= do_read_log_to_usr(buf
, count
);
297 atf_buf_vir_ctl
->info
.atf_read_pos
= index_to_pos(read_index
);
298 atf_buf_vir_ctl
->info
.atf_read_seq
+= ret
;
300 //pr_notice("atf_log_read: return %d, idx: %lu, readpos: %p, writepos: %p\n", ret, read_index, atf_buf_vir_ctl->info.atf_read_pos, atf_buf_vir_ctl->info.atf_write_pos);
304 static unsigned int atf_log_poll(struct file
*file
, poll_table
*wait
)
306 unsigned int ret
= POLLOUT
| POLLWRNORM
;
307 if (!(file
->f_mode
& FMODE_READ
))
309 poll_wait(file
, &atf_log_wq
, wait
);
311 if (atf_buf_vir_ctl
->info
.atf_write_pos
!= atf_buf_vir_ctl
->info
.atf_read_pos
)
312 ret
|= POLLIN
| POLLRDNORM
;
317 long atf_log_ioctl(struct file
*flip
, unsigned int cmd
, unsigned long arg
)
321 static struct file_operations atf_log_fops
= {
322 .owner
= THIS_MODULE
,
323 .unlocked_ioctl
= atf_log_ioctl
,
324 .poll
= atf_log_poll
,
325 .read
= atf_log_read
,
326 .open
= atf_log_open
,
327 .release
= atf_log_release
,
328 .write
= atf_log_write
,
331 static struct miscdevice atf_log_dev
= {
332 .minor
= MISC_DYNAMIC_MINOR
,
334 .fops
= &atf_log_fops
,
338 static int dt_scan_memory(unsigned long node
, const char *uname
, int depth
, void *data
)
340 char *type
= of_get_flat_dt_prop(node
, "device_type", NULL
);
344 /* We are scanning "memory" nodes only */
347 * The longtrail doesn't have a device_type on the
348 * /memory node, so look for the node called /memory@0.
350 if (depth
!= 1 || strcmp(uname
, "memory@0") != 0)
352 } else if (strcmp(type
, "memory") != 0)
355 reg
= of_get_flat_dt_prop(node
, "reg", &l
);
359 endp
= reg
+ (l
/ sizeof(__be32
));
361 while ((endp
- reg
) >= (dt_root_addr_cells
+ dt_root_size_cells
)) {
364 base
= dt_mem_next_cell(dt_root_addr_cells
, ®
);
365 size
= dt_mem_next_cell(dt_root_size_cells
, ®
);
370 // "[PHY layout]DRAM size (dt) : 0x%llx - 0x%llx (0x%llx)\n",
371 // (unsigned long long)base,
372 // (unsigned long long)base + (unsigned long long)size - 1,
373 // (unsigned long long)size);
375 *(unsigned long *)data
= node
;
379 unsigned long long atf_get_from_dt(unsigned long *phy_addr
, unsigned int *len
) {
380 unsigned long node
= 0;
381 mem_desc_t
*mem_desc
;
382 if (of_scan_flat_dt(dt_scan_memory
, &node
)) {
383 mem_desc
= (mem_desc_t
*)of_get_flat_dt_prop(node
, "tee_reserved_mem", NULL
);
384 if (mem_desc
&& mem_desc
->size
) {
385 pr_notice("ATF reserved memory: 0x%08llx - 0x%08llx (0x%llx)\n", mem_desc
->start
, mem_desc
->start
+mem_desc
->size
- 1, mem_desc
->size
); }
387 *phy_addr
= mem_desc
->start
;
388 *len
= mem_desc
->size
;
392 void show_atf_log_ctl() {
393 pr_notice("atf_buf_addr(%p) = 0x%x\n", &(atf_buf_vir_ctl
->info
.atf_buf_addr
), atf_buf_vir_ctl
->info
.atf_buf_addr
);
394 pr_notice("atf_buf_size(%p) = 0x%x\n", &(atf_buf_vir_ctl
->info
.atf_buf_size
), atf_buf_vir_ctl
->info
.atf_buf_size
);
395 pr_notice("atf_write_pos(%p) = %u\n", &(atf_buf_vir_ctl
->info
.atf_write_pos
), atf_buf_vir_ctl
->info
.atf_write_pos
);
396 pr_notice("atf_read_pos(%p) = %u\n", &(atf_buf_vir_ctl
->info
.atf_read_pos
), atf_buf_vir_ctl
->info
.atf_read_pos
);
397 pr_notice("atf_buf_lock(%p) = %u\n", &(atf_buf_vir_ctl
->info
.atf_buf_lock
), atf_buf_vir_ctl
->info
.atf_buf_lock
);
398 pr_notice("atf_buf_unread_size(%p) = %u\n", &(atf_buf_vir_ctl
->info
.atf_buf_unread_size
), atf_buf_vir_ctl
->info
.atf_buf_unread_size
);
399 pr_notice("atf_irq_count(%p) = %u\n", &(atf_buf_vir_ctl
->info
.atf_irq_count
), atf_buf_vir_ctl
->info
.atf_irq_count
);
400 pr_notice("atf_reader_alive(%p) = %u\n", &(atf_buf_vir_ctl
->info
.atf_reader_alive
), atf_buf_vir_ctl
->info
.atf_reader_alive
);
401 pr_notice("atf_write_seq(%p) = %llu\n", &(atf_buf_vir_ctl
->info
.atf_write_seq
), atf_buf_vir_ctl
->info
.atf_write_seq
);
402 pr_notice("atf_read_seq(%p) = %llu\n", &(atf_buf_vir_ctl
->info
.atf_read_seq
), atf_buf_vir_ctl
->info
.atf_read_seq
);
405 static void show_data(unsigned long addr
, int nbytes
, const char *name
)
412 * don't attempt to dump non-kernel addresses or
413 * values that are probably just small negative numbers
415 if (addr
< PAGE_OFFSET
|| addr
> -256UL)
418 printk("\n%s: %#lx:\n", name
, addr
);
421 * round address down to a 32 bit boundary
422 * and always dump a multiple of 32 bytes
424 p
= (u32
*)(addr
& ~(sizeof(u32
) - 1));
425 nbytes
+= (addr
& (sizeof(u32
) - 1));
426 nlines
= (nbytes
+ 31) / 32;
429 for (i
= 0; i
< nlines
; i
++) {
431 * just display low 16 bits of address to keep
432 * each line of the dump < 80 characters
434 printk("%04lx ", (unsigned long)p
& 0xffff);
435 for (j
= 0; j
< 8; j
++) {
437 if (probe_kernel_address(p
, data
)) {
440 printk(" %08x", data
);
448 static irqreturn_t
ATF_log_irq_handler(int irq
, void *dev_id
)
450 if (!atf_buf_vir_ctl
->info
.atf_reader_alive
) {
451 pr_err("No alive reader, but still recieve irq\n");
453 pr_info("ATF_log_irq triggered!\n");
455 wake_up_interruptible(&atf_log_wq
);
459 static const struct file_operations proc_atf_log_file_operations
= {
460 .owner
= THIS_MODULE
,
461 .open
= atf_log_open
,
462 .read
= atf_log_read
,
463 .unlocked_ioctl
= atf_log_ioctl
,
464 .release
= atf_log_release
,
465 .poll
= atf_log_poll
,
468 static int atf_crash_show(struct seq_file
*m
, void *v
)
470 seq_write(m
, atf_crash_log_buf
, atf_buf_vir_ctl
->info
.atf_crash_log_size
);
474 static int atf_crash_file_open(struct inode
*inode
, struct file
*file
)
476 return single_open(file
, atf_crash_show
, inode
->i_private
);
479 static const struct file_operations proc_atf_crash_file_operations
= {
480 .owner
= THIS_MODULE
,
481 .open
= atf_crash_file_open
,
484 .release
= seq_release
,
487 static struct proc_dir_entry
*atf_log_proc_dir
;
488 static struct proc_dir_entry
*atf_log_proc_file
;
489 static struct proc_dir_entry
*atf_crash_proc_file
;
491 static int __init
atf_log_init(void)
493 //register module driver
495 err
= misc_register(&atf_log_dev
);
497 pr_err("atf_log: failed to register device");
500 pr_notice("atf_log: inited");
502 //get atf reserved memory(atf_buf_phy_ctl) from device
503 atf_get_from_dt(&atf_buf_phy_ctl
, &atf_buf_len
); //TODO
504 if (atf_buf_len
== 0) {
505 pr_err("No atf_log_buffer!\n");
508 // map control header
509 atf_buf_vir_ctl
= ioremap_wc(atf_buf_phy_ctl
, ATF_LOG_CTRL_BUF_SIZE
);
510 atf_log_len
= atf_buf_vir_ctl
->info
.atf_buf_size
;
512 atf_log_vir_addr
= ioremap_wc(atf_buf_phy_ctl
+ ATF_LOG_CTRL_BUF_SIZE
, atf_log_len
);
513 pr_notice("atf_buf_phy_ctl: 0x%lu\n", atf_buf_phy_ctl
);
514 pr_notice("atf_buf_len: %u\n", atf_buf_len
);
515 pr_notice("atf_buf_vir_ctl: %p\n", atf_buf_vir_ctl
);
516 pr_notice("atf_log_vir_addr: %p\n", atf_log_vir_addr
);
517 pr_notice("atf_log_len: %u\n", atf_log_len
);
518 //show_atf_log_ctl();
519 //show_data(atf_buf_vir_ctl, 512, "atf_buf");
520 atf_buf_vir_ctl
->info
.atf_reader_alive
= 0;
521 atf_buf_vir_ctl
->info
.atf_read_seq
= 0;
523 init_waitqueue_head(&atf_log_wq
);
524 if (request_irq(281, (irq_handler_t
)ATF_log_irq_handler
, IRQF_TRIGGER_NONE
, "ATF_irq",NULL
) != 0) {
525 pr_crit("Fail to request ATF_log_irq interrupt!\n");
528 // create /proc/atf_log
529 atf_log_proc_dir
= proc_mkdir("atf_log", NULL
);
530 if (atf_log_proc_dir
== NULL
) {
531 pr_err("atf_log proc_mkdir failed\n");
534 // create /proc/atf_log/atf_log
535 atf_log_proc_file
= proc_create("atf_log", 0444, atf_log_proc_dir
, &proc_atf_log_file_operations
);
536 if (atf_log_proc_file
== NULL
) {
537 pr_err("atf_log proc_create failed at atf_log\n");
541 if (atf_buf_vir_ctl
->info
.atf_crash_flag
== ATF_CRASH_MAGIC_NO
) {
542 atf_crash_proc_file
= proc_create("atf_crash", 0444, atf_log_proc_dir
, &proc_atf_crash_file_operations
);
543 if (atf_crash_proc_file
== NULL
) {
544 pr_err("atf_log proc_create failed at atf_crash\n");
547 atf_buf_vir_ctl
->info
.atf_crash_flag
= 0;
548 atf_crash_log_buf
= ioremap_wc(atf_buf_vir_ctl
->info
.atf_crash_log_addr
, atf_buf_vir_ctl
->info
.atf_crash_log_size
);
554 static void __exit
atf_log_exit(void)
556 //deregister module driver
558 err
= misc_deregister(&atf_log_dev
);
560 pr_err("atf_log: failed to unregister device");
562 pr_notice("atf_log: exited");
565 module_init(atf_log_init
);
566 module_exit(atf_log_exit
);
568 MODULE_DESCRIPTION("MEDIATEK Module ATF Logging Driver");
569 MODULE_AUTHOR("Ji Zhang<ji.zhang@mediatek.com>");