HSL: dbg:add some debug function
authorhsl <hsl@rock-chips.com>
Thu, 27 Jan 2011 08:17:35 +0000 (16:17 +0800)
committerhsl <hsl@rock-chips.com>
Thu, 27 Jan 2011 08:17:35 +0000 (16:17 +0800)
arch/arm/kernel/entry-common.S
drivers/Makefile
drivers/dbg/Makefile [new file with mode: 0644]
drivers/dbg/debug.c [new file with mode: 0644]
drivers/dbg/kobj.c [new file with mode: 0644]
drivers/dbg/wrapcall.S [new file with mode: 0644]

index a6c66f598d14e85fd7396a557de3ed1ac809ed46..8e7ad911b579763002590d3fbc38dd4a7c77d8bb 100644 (file)
@@ -22,7 +22,8 @@
  * possible here, and this includes saving r0 back into the SVC
  * stack.
  */
-ret_fast_syscall:
+/* ret_fast_syscall: */
+ENTRY(ret_fast_syscall)
  UNWIND(.fnstart       )
  UNWIND(.cantunwind    )
        disable_irq                             @ disable interrupts
index 68548675116c04e954276189b133a39a121ad613..972651f363810966f16e6e66067b1d9c1fde04bd 100644 (file)
@@ -115,3 +115,5 @@ obj-$(CONFIG_STAGING)               += staging/
 obj-y                          += platform/
 obj-y                          += ieee802154/
 obj-$(CONFIG_CMMB)             += cmmb/        
+obj-y                          += dbg/
+
diff --git a/drivers/dbg/Makefile b/drivers/dbg/Makefile
new file mode 100644 (file)
index 0000000..9d25852
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for rk_scu drivers.
+#
+obj-y     :=wrapcall.o debug.o kobj.o
+
+
+
diff --git a/drivers/dbg/debug.c b/drivers/dbg/debug.c
new file mode 100644 (file)
index 0000000..91f05c4
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ * function for test and debug
+ *
+ * Copyright (C) 2011 Rochchip, Inc.
+ * Author: Hsl
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  relative files: drivers/dbg/ , arch/arm/kernel/entry-common.S
+ *  LOG:
+ *      20110127, HSL@RK,add get user regs support and kernel io support.
+ */
+
+/* #define DEBUG */
+#include <linux/kallsyms.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+
+
+/*
+ * 20090725,hsl,some debug function start from here
+ */
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/mmzone.h>
+#include <linux/rtc.h>
+
+#include <asm/sections.h>
+#include <asm/stacktrace.h>
+#include <asm/io.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
+#else
+#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
+#endif
+
+extern int __scu_call_wrap(unsigned long *argv , int argc , int fun );
+extern void ret_fast_syscall( void );
+
+void rk28_printk_mem( unsigned int * addr , int words , unsigned int*  show_addr )
+{
+        unsigned int * reg_base = addr ;
+        if( show_addr == NULL ){
+                show_addr = addr;
+        }
+        while( words > 0 ) {
+                printk("%p:%08x  %08x  %08x  %08x\n" ,show_addr ,
+                        reg_base[0],reg_base[1],reg_base[2],reg_base[3]);
+                words -= 4;
+                reg_base += 4;
+                show_addr += 4;
+        }
+}
+
+/*
+ *  type define :
+ *  first for function name , 
+ * ',' for argument.
+ * \' : char
+ * \" : string.
+ * other : for int,short,0x for hex.0 for octal.
+ * 20090811,for easy use , 0x or 0-9 start means num , other ,means string . 
+ * len = 1 string for char.
+ * 20100420,add nagative support.
+ */
+int dbg_get_arg( char ** pp )
+{
+        char * p = *pp;
+        char *t;
+        int ret;
+        int len ;
+        int nag = 0;
+        int bnum = 0;
+        if( p[0] == '-' ) {
+                nag = 1;
+                p++;
+        }
+        if( p[0] == '0' ) {
+                if( ( p[1] == 'x' || p[1] == 'X' ) ) {
+                        p+= 2;
+                        len = sscanf(p,"%x" , &ret );
+                        p += len;
+                } else {
+                        if( p[1] == 0 || p[1] == ',' ) {
+                                ret = 0; /* only one '0' , must be zero */
+                                p++;
+                        } else {
+                                p+= 1;
+                                len = sscanf(p,"%o" , &ret );
+                                p += len;
+                        }
+                }
+                bnum = 1;
+        } else if( p[0] >= '1' && p[0] <= '9' ) {
+                len = sscanf(p,"%d" , (int*)&ret );
+                p += len;
+                bnum = 1;
+        } else if( p[0] == '\'' ) {
+                ret = p[1];
+                p++;
+        } else {  /* all for string */
+                if ( p[0] == '\"' ) {
+                        if( p[1] == '\"' ) { /* NULL string */
+                                ret = 0;
+                                p+=2;     
+                        } else {
+                                ret = (unsigned long)(p+1);
+                                t = strchr( p+1 , '\"' );
+                                if( t ) {
+                                        *t = 0;
+                                        p = t+1 ;
+                                } else  {
+                                        p++;
+                                }
+                        }
+               }  else {
+                        if( *p == ',' )  {/* empty ,as NULL string */
+                                ret = 0;
+                                p--;
+                        } else  if( *p == ' ' || *p == 0 ) /* one char string ,as char.*/
+                                ret = *p;
+                        else /* as string */
+                                ret = (unsigned long)(p);
+                        p++;
+                }
+        }
+       t = strchr( p , ',' );
+       if( t ) {
+            *t = 0;
+            *pp = t+1;
+       } else { /* p should be the last one */
+             while(*p != ' ' && *p != 0 && *p != '\n' )
+                        p++;
+       *p = 0;
+             *pp = p;
+       }
+       if( nag && bnum )
+                ret = 0-ret;
+       return ret;
+}
+int dbg_parse_cmd( char * cdb )
+{
+        unsigned long reg[6];
+        unsigned long fun;
+        int             argc = 0 ;
+        char    *p = cdb ;
+        char    *sym = p;
+        int       ret;
+        
+        //SCU_BUG("CMD=%s\n" , cdb);
+        memset( reg , 0 , sizeof reg );
+        p = strchr(p , ',');
+        if( p ) {
+                *p++ = 0;
+                while( *p && argc < 6) {
+                        reg[argc++] = (unsigned long)dbg_get_arg( &p );
+                }
+        }
+        //debug_print("sym=%s,argc=%d,db=%s\n" , sym ,argc , cdb );
+        if( sym[0] == '0' && ( sym[1] == 'x' || sym[1] == 'X' ) ) {
+                fun = 0;
+                sscanf(sym+2,"%lx" , &fun );
+        } else {
+                fun = kallsyms_lookup_name(sym);
+                //debug_print("after lookup symbols,sym=%s,fun=0x%p\n" , sym ,fun);
+        }
+        
+        /* 20100409,HSL@RK,use printk to print to buffer.
+        */
+        printk("@CALL@ %s(0x%p),argc=%d\n" , sym , (void*)fun , argc);
+        if( fun ) {
+                ret = __scu_call_wrap( reg,argc,fun);
+        } else {
+                ret = -EIO;
+        }
+        /* 20100722,"@return" for function print end tag.
+        */
+        printk("@return 0x%x(%d)\n" , ret , ret);
+        return ret;
+}
+
+#if 0
+/**
+ * check arg be a string or int or symbol addr .
+ * 1: string , 2: kernel sym , 0:other 
+ */
+int rk28_arg_string( unsigned long arg )
+{
+        if( arg > (unsigned long)&_end  && arg < 0xc8000000 )
+                return 1;
+        if( arg >= (unsigned long)&_text && arg < (unsigned long)&_end )
+                return 2;
+        return 0;
+}
+#endif
+
+static struct pt_regs * unwind_get_regs(struct task_struct *tsk)
+{
+       struct stackframe frame;
+       register unsigned long current_sp asm ("sp");
+       int found = 0;
+       //unsigned long  sc;
+       
+       if (!tsk)
+               tsk = current;
+               
+       printk("tsk = %p,comm=%s,pid=%d,pgd=0x%p\n", tsk , tsk->comm , tsk->pid , tsk->mm->pgd );
+       if (tsk == current) {
+               frame.fp = (unsigned long)__builtin_frame_address(0);
+               frame.sp = current_sp;
+               frame.lr = (unsigned long)__builtin_return_address(0);
+               frame.pc = (unsigned long)unwind_get_regs;
+       } else {
+               /* task blocked in __switch_to */
+               frame.fp = thread_saved_fp(tsk);
+               frame.sp = thread_saved_sp(tsk);
+               /*
+                * The function calling __switch_to cannot be a leaf function
+                * so LR is recovered from the stack.
+                */
+               frame.lr = 0;
+               frame.pc = thread_saved_pc(tsk);
+       }
+
+       while (1) {
+               int urc;
+               //unsigned long where = frame.pc;
+
+               urc = unwind_frame(&frame);
+               if (urc < 0)
+                       break;
+               //dump_backtrace_entry(where, frame.pc, frame.sp - 4);
+               if( frame.pc == (unsigned long)ret_fast_syscall ){
+                       found = 1;
+                       break;
+               }
+       }
+       if( !found )
+               return NULL;
+       #if 0
+       //printk("FRAME:sp=0x%lx,pc=0x%lx,lr=0x%lx,fp=0x%lx\n" , frame.sp,frame.pc,frame.lr,frame.fp );
+       //rk28_printk_mem((unsigned int*)(frame.sp-sizeof(struct pt_regs)),2*sizeof(struct pt_regs)/4+8, NULL );
+       sc =*( (unsigned long*)(frame.sp-4));
+       if( sc >= (unsigned long)&_text && sc < (unsigned long)&_end ){
+           print_symbol("sys call=%s\n",sc );
+       }
+       #endif
+       return (struct pt_regs *)(frame.sp+8); // 8 for reg r4,r5 as fifth and sixth args.
+}
+
+struct pt_regs * __scu_get_regs( void )
+{
+        return unwind_get_regs( NULL );
+}
+
+struct pt_regs * scu_get_task_regs(  int pid  )
+{
+        struct task_struct *t = FIND_TASK_BY_PID( pid );
+        return  unwind_get_regs( t );
+}
+
+/* 
+  *  f: bit0: show kernel , bit1: dump user.
+  */
+int tstack( int pid , int f)
+{
+        struct pt_regs * preg;
+        struct task_struct *t = FIND_TASK_BY_PID( pid );
+        
+        if( !t ){
+                printk("NO task found for pid %d\n" ,pid );
+                t = current ;
+        }
+        preg = unwind_get_regs( t );
+        if( f& 1 ) {
+                show_stack( t , NULL );
+        }
+        if( !preg ) {
+                printk("NO user stack found for task %s(%d)\n" , t->comm , t->pid );
+        } else {
+                //printk("user stack found for task %s(%d):\n" , t->comm , t->pid );
+                __show_regs( preg );
+                if( f & 2 ) {
+                        #define SHOW_STACK_SIZE         (2*1024)
+                        int len;
+                        unsigned int *ps = (unsigned int*)kmalloc( SHOW_STACK_SIZE , GFP_KERNEL);
+                        if( ps ) {
+                                len = access_process_vm( t , preg->ARM_sp , ps , SHOW_STACK_SIZE, 0 );
+                                rk28_printk_mem( ps , len/4 , (unsigned int* )preg->ARM_sp );
+                                kfree( ps );
+                        }
+                }
+        }
+        return pid;
+}
+
+#if 0
+void __rk_force_signal(struct task_struct *tsk, unsigned long addr,
+               unsigned int sig, int code )
+{
+       struct siginfo si;
+                printk("%s::send sig %d to task %s\n" , __func__ , sig , tsk->comm );
+       si.si_signo = sig;
+       si.si_errno = 0;
+       si.si_code = code;
+       si.si_addr = (void __user *)addr;
+       force_sig_info(sig, &si, tsk);
+}
+int rksignal( int pid , int sig )
+{
+        struct task_struct *t = FIND_TASK_BY_PID( pid );
+        if( !t )
+                t = current ;
+        __rk_force_signal( t , 0xc0002234 , sig , 0x524b4b52 );
+        return 0x201;
+}
+
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/tty_flip.h>  
+extern struct console *console_drivers;
+// like : echo rk28_uart_input,"\"pwd|ls,echo fdfdf\"">active
+int rk28_uart_input( char * str )
+{
+        char * p = str;
+        int     indx;
+        struct tty_driver *tty_drv = console_drivers->device( console_drivers , &indx );
+        struct tty_struct *tty_s = tty_drv->ttys[indx ];
+        int flag = TTY_NORMAL;
+        
+        printk("indx=%d, tty drv=%p,tty_s=%p,cur console=%s,next console=%p\n", indx , tty_drv , tty_s ,
+                console_drivers->name , console_drivers->next );
+        //printk("cmd=%s\n" , str );
+        if( !p )
+                return -EIO;
+        
+        while( *p ) {
+                if( *p == ',' )
+                        *p = '\n';
+                p++;
+        }
+        *p++ = '\n';
+        *p = 0;
+
+        p = str;
+        while( *p ) {
+                tty_insert_flip_char(tty_s, *p , flag);
+                p++;
+        }
+
+        tty_flip_buffer_push( tty_s );
+        return 0x28;
+}
+#endif
+
+#if 0
+extern int kernel_getlog( char ** start  , int * offset , int* len );
+int rk28_write_file( char *filename )
+{
+        char *procmtd = "/proc/mtd";
+        struct file                    *filp = NULL;
+        loff_t                         pos;
+        long    fd;
+        
+        ssize_t l=0;
+        char    pathname[64];
+        char    buf[1024] ;
+        mm_segment_t old_fs;
+        struct rtc_time tm;
+        ktime_t now;        
+        char *tmpbuf; 
+        int     mtdidx=0;
+        int mtdsize = 0x200000; // 2M 
+        char *log_buf;
+        int     log_len;
+
+        debug_print("%s: filename=%s\n" , __func__ , filename );
+
+        old_fs = get_fs();
+        set_fs(KERNEL_DS);        
+        fd = sys_open( procmtd , O_RDONLY , 0 );
+        if( fd >= 0 ) {
+                memset( buf , 0 , 1024 );
+                l = sys_read( fd , buf , 1024 );
+               // debug_print("/proc/mtd,total byte=%d\n" , l );
+                tmpbuf = strstr( buf , filename );
+                if( tmpbuf ) {
+                        tmpbuf[10] = 0;
+                        mtdsize = simple_strtoul(tmpbuf-19, NULL , 16);
+                        mtdidx = tmpbuf[-22];
+                        //debug_print("size=%s\n,idx=%s\nmtdsize=%x , mtdidx=%d" , tmpbuf-19 , tmpbuf - 22 ,
+                        //        mtdsize , mtdidx );
+                        mtdsize *= 512;
+                        mtdidx -= '0';
+                }
+                sys_close( fd );
+        } else {
+                debug_print("open %s failed\n" , procmtd );
+        }
+        sprintf(pathname , "/dev/block/mtdblock%d" , mtdidx );
+        filp = filp_open(pathname, O_WRONLY , 0);
+        if( IS_ERR(filp) ) {
+                debug_print("open %s failed n" , pathname  );
+                goto out_print;
+        }
+        if (!(filp->f_op->write || filp->f_op->aio_write)) {
+                debug_print("can not write file %s \n" , pathname  );
+                goto close_file;
+        }
+        now = ktime_get();
+        rtc_time_to_tm( now.tv.sec , &tm );
+        printk( "\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
+                          "++++++++++RECORD LOG AT %04d-%02d-%02d %02d:%02d:%02d++++++++++\n"
+                          "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n\n\n"
+                          ,
+                tm.tm_year+1900 , tm.tm_mon , tm.tm_mday , tm.tm_hour , tm.tm_min , tm.tm_sec );
+        /* 20090924,HSL,FTL only intial first 256M at loader , MUST write 32 sector one time */
+        //debug_print("write first pack , pos=%d\n" , pos ); /* pos = 2 ?? */
+        kernel_getlog(&log_buf , NULL ,  &log_len );
+        log_len = (log_len+(32*512-1)) / (32*512) * (32*512);
+        pos = 0;
+        l = vfs_write( filp , log_buf  , log_len , &pos );
+        do_fsync(filp, 1);
+close_file:
+        filp_close(filp , NULL);
+out_print:  
+        set_fs(old_fs);
+        debug_print("\nlog len=%d,write=%d\n" ,log_len , l);
+        return 0x2b;
+}
+#endif
+
+#if 1
+/*
+ * 
+ * 20091027,2808SDK,
+ * lcd off:byte:81748000,word:39100000.
+ * lcd on: byte:90742000,word:43158000  %9.5
+ *
+ * 20091111,2806 ruiguan,
+ * lcd off: byte: 81883000,word: 39209000
+ * lcd on: byte: 90843000,word: 43260000
+
+ * 20100516,281x, 133 ddr , lcd on.
+ * need 151432000 ns to copy 4096 Kbytes 
+ * need 85340000 ns to copy 1024 Kwords 
+ LCD OFF.
+ * need 144880000 ns to copy 4096 Kbytes 
+ * need 83100000 ns to copy 1024 Kwords 
+ 20100517,281x,200M ddr lcd on.
+ * need 90024000 ns to copy 4096 Kbytes 
+ * need 47668000 ns to copy 1024 Kwords 
+ lcd off
+ need 87564000 ns to copy 4096 Kbytes 
+ need 46956000 ns to copy 1024 Kwords 
+ 20100518,266M ddr. lcd on
+ need 84460000 ns to copy 4096 Kbytes 
+ need 41036000 ns to copy 1024 Kwords 
+
+ need 204568000 ns to copy 4096 Kbytes 
+need 116388000 ns to copy 1024 Kwords
+
+ ddr 330M,lcd on.
+ need 81944000 ns to copy 4096 Kbytes 
+ need 37640000 ns to copy 1024 Kwords
+ ahb 180M.ddr 330M.
+ need 88908000 ns to copy 4096 Kbytes 
+ need 38108000 ns to copy 1024 Kwords
+
+ ahb 200M,DDR 380M,lcd on.
+ need 79456000 ns to copy 4096 Kbytes 
+ need 34216000 ns to copy 1024 Kwords   %0.14.
+ need 79432000 ns to copy 4096 Kbytes 
+need 34204000 ns to copy 1024 Kwords
+LCD OFF.
+ need 77260000 ns to copy 4096 Kbytes 
+ need 33768000 ns to copy 1024 Kwords
+
+ need 77228000 ns to copy 4096 Kbytes 
+need 33764000 ns to copy 1024 Kwords %0.01
+ */
+
+/*
+on rk29
+dyn desktop:
+[   63.010000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[   63.100000] need 90342667 ns to copy 4096 Kbytes 
+[   63.140000] need 38885333 ns to copy 1024 Kwords 
+[   63.160000] need 13030791 ns to memcpy 4096 Kbytes 
+[   63.160000] @return 0x2c(44)
+# echo rk28_memcpy > cal 
+[   65.680000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[   65.740000] need 57542915 ns to copy 4096 Kbytes 
+[   65.770000] need 30017666 ns to copy 1024 Kwords 
+[   65.810000] need 32929083 ns to memcpy 4096 Kbytes 
+[   65.810000] @return 0x2c(44)
+# echo rk28_memcpy > cal 
+[   67.400000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[   67.460000] need 52001876 ns to copy 4096 Kbytes 
+[   67.490000] need 29809209 ns to copy 1024 Kwords 
+# [   67.510000] need 20318709 ns to memcpy 4096 Kbytes 
+[   67.510000] @return 0x2c(44)
+# echo rk28_memcpy > cal 
+[   71.800000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[   71.860000] need 57265835 ns to copy 4096 Kbytes 
+[   71.900000] need 32522127 ns to copy 1024 Kwords 
+[   71.930000] need 27615668 ns to memcpy 4096 Kbytes 
+[   71.930000] @return 0x2c(44)
+
+
+static desktop:
+
+[  171.880000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[  171.910000] need 27547043 ns to copy 4096 Kbytes 
+[  171.920000] need 8993501 ns to copy 1024 Kwords 
+[  171.930000] need 6791584 ns to memcpy 4096 Kbytes 
+[  171.930000] @return 0x2c(44)
+# echo rk28_memcpy > cal 
+[  174.050000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[  174.080000] need 26437334 ns to copy 4096 Kbytes 
+[  174.090000] need 8701667 ns to copy 1024 Kwords 
+[  174.100000] need 6639375 ns to memcpy 4096 Kbytes 
+[  174.100000] @return 0x2c(44)
+# echo rk28_memcpy > cal 
+[  176.290000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[  176.320000] need 26692502 ns to copy 4096 Kbytes 
+[  176.330000] need 8659126 ns to copy 1024 Kwords 
+[  176.340000] need 6702001 ns to memcpy 4096 Kbytes 
+[  176.340000] @return 0x2c(44)
+# echo rk28_memcpy > cal 
+[  177.710000] @CALL@ rk28_memcpy(0xc070148c),argc=0
+[  177.740000] need 27578291 ns to copy 4096 Kbytes 
+[  177.750000] need 8740042 ns to copy 1024 Kwords 
+[  177.760000] need 6727458 ns to memcpy 4096 Kbytes 
+[  177.760000] @return 0x2c(44)
+
+*/
+int rkmemcpy( void )
+{
+#define PAGE_ORDER              7
+        ktime_t         now0,now1;
+
+        unsigned long pg;
+        unsigned long src = 0xc0010000;
+        int     i = 8,k=0;
+        int     bytes = ((1<<PAGE_ORDER)*PAGE_SIZE);
+        
+        pg = __get_free_pages(GFP_KERNEL , PAGE_ORDER );
+        if( !pg ) {
+                printk("alloc %d pages total %dK bytes failed\n" , (1<<PAGE_ORDER) , bytes/(1024));
+                return -ENOMEM;
+       }
+       now0 = ktime_get();
+       while( k < i ) {
+                char *p = (char*)pg;
+                char  *q = (char*)src;
+                char  *m = q+bytes;
+                while( q < m ) 
+                        *p++ = *q++;   
+                k++;
+       }
+       now1 = ktime_get();;
+       printk("need %Ld ns to copy %d Kbytes \n" ,
+                ktime_to_ns( ktime_sub(  now1 , now0 ) ), bytes * i /1024 );
+       now0 = ktime_get();
+       k = 0;
+       while( k < i ) {
+                int *p = (int*)pg;
+                int  *q = (int*)src;
+                int  *m = q+bytes/sizeof(int);
+                while( q < m ) 
+                        *p++ = *q++;   
+                k++;
+       }
+       now1 = ktime_get();
+       
+       printk("need %Ld ns to copy %d Kwords \n" ,
+                ktime_to_ns( ktime_sub(  now1 , now0 ) ), bytes * i / sizeof (int) /1024 );
+
+       now0 = ktime_get();
+       for( k = 0 ;  k < i ; k++ )
+                memcpy((void*)pg,(void*)src , bytes );
+       now1 = ktime_get();
+       printk("need %Ld ns to memcpy %d Kbytes \n" ,
+                ktime_to_ns( ktime_sub(  now1 , now0 ) ), bytes * i / 1024 );
+
+       free_pages( pg , PAGE_ORDER );
+       return 0x2c;
+}
+#endif
+
+int rknow( int loop , int prtk )
+{
+        ktime_t ktime_now;
+        struct timespec ts;
+        struct rtc_time tm;
+
+        if( loop > 20 )
+            loop = 20;
+        do {
+        ktime_now = ktime_get();
+        getnstimeofday(&ts);
+        rtc_time_to_tm(ts.tv_sec, &tm);
+        printk("now=%lld ns "
+               "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
+               ktime_to_ns(ktime_now),
+               tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
+        udelay( 31 );
+        loop --;
+        }while( loop > 0 );
+        return 0x2c;
+}
+
+#if 0
+/* 1,2=0 , 0 = lr */
+void rk28_return( void )
+{
+        printk("return addr:\n 0: 0x%p " "1: 0x%p " "2: 0x%p\n", __builtin_return_address(0) , 
+                __builtin_return_address(1) , __builtin_return_address(2));
+}
+#endif
+
+int dl( int ms )
+{
+        mdelay( ms );
+        printk("delay %d ms\n" , ms );
+        return ms;
+}
+
+int irq_dl( int ms )
+{
+        unsigned long flags;
+        local_irq_save(flags);
+        mdelay( ms );
+        local_irq_restore(flags);
+        printk("delay %d ms\n" , ms );
+        return ms;
+}
+
+/*
+ * read a phy addr value , len is word.
+*/
+int dd( unsigned int phy_addr,int len ,unsigned  int value )
+{
+            int size = len*4;
+            unsigned int * ptr;
+            int     wr = 0;
+            int     map = 0;
+            if( !len ){
+                    printk("invalid len=%d\n" , len );
+                    return 0;
+            }
+            /* we want to write? write 0?*/
+            if( value || len == 1 ) {   
+                    size = 4;
+                    wr = 1;
+            }
+            if(phy_addr < PAGE_OFFSET ) {
+                    ptr = (unsigned int *)ioremap( phy_addr , size );
+                    if( !ptr ) {
+                            printk("map addr 0x%x failed\n" , phy_addr );
+                            return -ENOMEM;
+                    }
+                    map = 1;
+            } else {
+                    ptr = (unsigned int *)phy_addr;
+            }
+            if( wr ) {
+                    *ptr = value ;
+                    dmb();
+            }
+            rk28_printk_mem( ptr , len , (unsigned int*)phy_addr );
+            if( map ) {
+                    iounmap(ptr);
+            }
+            return size;
+}
+
diff --git a/drivers/dbg/kobj.c b/drivers/dbg/kobj.c
new file mode 100644 (file)
index 0000000..423d145
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * kobj.c
+ *
+ * (C) Copyright hsl 2009
+ *     Released under GPL v2.
+ *
+ * 
+ * log:
+ *      for debug function by sysfs 
+ *      
+ */
+
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/cdev.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/spinlock_types.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/delay.h>
+#include <linux/kallsyms.h>
+#include <linux/rtc.h>
+#include <asm/atomic.h>
+#include <asm/signal.h>
+
+static struct kobject *dbg_kobj;
+
+extern int dbg_parse_cmd( char * cdb );
+
+static char     dbg_lastcmd[512];
+
+/* default kobject attribute operations */
+static ssize_t dbg_call_attr_show(struct kobject *kobj, struct kobj_attribute *attr,
+                             char *buf)
+{
+        strcpy( buf , dbg_lastcmd );
+        strcat(buf,"\n");
+        return strlen(buf)+1;
+}
+static ssize_t dbg_call_attr_store(struct kobject *kobj, struct kobj_attribute *attr,
+                              const char *buf, size_t count)
+{
+        char    cmd[512];
+        int len = sizeof(dbg_lastcmd)>count ? count:sizeof(dbg_lastcmd);
+        //printk("count=%d,cmd=%s!\n" , count , buf );
+        strncpy( dbg_lastcmd , buf , len );
+        if( dbg_lastcmd[len-1] == '\n' ){
+            dbg_lastcmd[len-1] = 0;
+            len--;
+        }
+        strncpy( cmd , dbg_lastcmd , sizeof(cmd) );
+         dbg_parse_cmd( cmd );
+        return count;
+}
+
+
+
+static struct kobj_attribute _call_attr = {    
+       .attr   = {                             
+               .name = "dbg",  
+               .mode = 0644,                   
+       },                                      
+       .show   = dbg_call_attr_show,                   
+       .store  = dbg_call_attr_store,          
+};
+
+static struct attribute * g[] = {
+       &_call_attr.attr,
+       NULL,
+};
+
+static struct attribute_group attr_group = {
+       .attrs = g,
+};
+
+
+int dbg_init( void )
+{
+        //dbg_kobj = kobject_create_and_add("dbg", NULL ); /*kernel_kobj*/
+        //if (!dbg_kobj)
+        //        return -ENOMEM;
+        //return sysfs_create_group(dbg_kobj, &attr_group);
+        return sysfs_create_group(kernel_kobj, &attr_group);
+}
+
+late_initcall(dbg_init);
+
diff --git a/drivers/dbg/wrapcall.S b/drivers/dbg/wrapcall.S
new file mode 100644 (file)
index 0000000..0180504
--- /dev/null
@@ -0,0 +1,94 @@
+#include <linux/linkage.h>
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/vfpmacros.h>
+#include <asm/thread_notify.h>
+#include <asm/ptrace.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+
+#__scu_call_wrap:
+#
+# call to the defined funcion.
+# r0: func argument array , max = 6
+# r1: argument num.
+# r2: the function number.
+
+#;     EXPORT __scu_call_wrap
+#;     
+#;     CODE32
+#;     AREA   ||funwrap||, CODE, READONLY      
+ENTRY(__scu_call_wrap)
+       STMFD    r13!,{r4,r5,r6,lr}
+       mov             r6,r2
+       ldmia   r0, {r0-r5}
+       STMFD    r13!,{r4,r5}
+       mov     lr , pc
+       mov pc , r6
+       add     r13 , r13 ,#8
+       LDMFD    r13!,{r4,r5,r6,pc}
+
+/**
+ * 20091126,HSL@RK,change to get syscall struct pt_regs *.
+ * way: search stack frame for lr = ret_fast_syscall.
+ * code from bachtrace.S -- __backtrace.
+ * 20110126,not support at 2.6.32(no fp)
+ * 20110127,support at debug.c,use c funtion.
+ */
+#define frame  r4
+#define sv_fp  r5
+#define sv_pc  r6
+#define mask   r7
+#define offset r8
+/*      
+ENTRY(__scu_get_usr_regs)
+               mov r0, #0
+               mov     pc, lr
+*/
+
+/*
+ * 20091215,continue running from break point.
+ * r0 is the struct pt_regs *.
+ */
+ENTRY(__scu_bk_continue)
+       mov r12, r0      
+       ldr     r0, [r12, #S_PSR]               
+       msr     spsr_cxsf, r0
+       ldmia   r12, {r0 - pc}^                 @ load r0 - pc, cpsr
+       
+#if FIQ_ENABLE
+        .align
+ENTRY(rk28_fiq_handle)
+        mrs r8, spsr
+        adr r9,__fiq_save
+        stmia r9 , {r0-r8,lr}
+        mov   r0,r9     @save addr.
+        mov r5,#(SVC_MODE|PSR_I_BIT|PSR_F_BIT)
+        msr  cpsr_cxsf,r5       @ to svc mod.disable irq,fiq.
+        sub r1, sp, #(S_FRAME_SIZE)
+
+        add     r2 , r1 , #32   @ r0--r7.
+        stmia  r2,{r8-lr}       @ the svc sp not change here.
+        ldmia  r0,{r3-r10}
+        stmia  r1,{r3-r10}
+        ldr      r9,[r0,#36]     @get fiq lr.
+        sub    r9,r9,#4
+        str      r9 , [r1,#S_PC]
+        ldr      r10,[r0,#32]     @get fiq spsr.
+        str      r10, [r1,#S_PSR]
+        mov    r5,r1
+        mov    sp,r5    @stack frame 
+        mov    r0,r5
+        ldr      r11,1f
+        blx      r11
+        b        3f
+1:
+                .long           rk28_debug_fiq
+3:                
+        msr  spsr_cxsf,r10
+        ldmia r5, {r0 - pc}^
+__fiq_save:                @for save fiq spsr r0-r7,spsr,lr.
+                .long     0                
+                .previous
+#endif
+