#ifdef __KERNEL__ #define __DLOG_IMPLEMENTAION_MODULE__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../mdss_dsi.h" #include "../mdss_mdp.h" #include "../mdss_fb.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../mdss_panel.h" #include "../mdss_mdp.h" #include "../mdss_edp.h" #include "../mdss_debug.h" #include #include "linux/debugfs.h" #define CFAKE_DEVICE_NAME "ddebugger" #else #include #include #include #include #include #include #include #include #include #include #include #include #define pr_debug(fmt,...) dprintf(CRITICAL,fmt,##__VA_ARGS__); #define pr_info(fmt,...) dprintf(CRITICAL,fmt,##__VA_ARGS__); #define MIPI_INP(X) readl(X); #endif #include "../mdss.h" #include "dlog.h" #ifndef __KERNEL__ u32 __debug_mdp_phys = 0x7FD00000; #else u32 __debug_mdp_phys = 0x00000; #endif //void sec_debug_display_klog_addr(unsigned int *buffer_addr); //static u32 klog_addr; static u32 dump_size; struct debug_mdp *debug_mdp; //MDP Instace Variable #ifdef __KERNEL__ #ifdef CONFIG_SEC_DEBUG_SCHED_LOG extern struct sec_debug_log *secdbg_log; extern struct sec_debug_subsys_data_krait *secdbg_krait; extern struct _dlogdebug __start___dlog[]; extern struct _dlogdebug __stop___dlog[]; extern struct mdss_data_type *mdss_res; #endif static spinlock_t xlock; extern struct msm_mdp_interface mdp5; static int sec_debug_level = 1; #endif #define DLOG_BUFFER_SIZE 2000 #define DLOG_BUFFER_SIZE_SHIP 200 #define REGISTER_LOG_LEN 110 #define EVENT_DESC_LEN 10 #define CLOCK_DUMP_LEN 2 #if defined(CONFIG_ARCH_MSM8974) #define CHIP_GPIO_COUNT_8974 146 static struct reg_desc mdss_reg_desc[]= { {0xFD900000,0x22100}, //mdp {0xFD922804,0x0600}, //dsi0 {0xFD922E04,0x0600}, //dsi1 {0xFD923404,0x0700}, //edp {0xFD511000,(CHIP_GPIO_COUNT_8974*4*4)} //gpio }; #elif defined(CONFIG_ARCH_MSM8226) #define CHIP_GPIO_COUNT_8226 117 static struct reg_desc mdss_reg_desc[]= { {0xFD900000,0x22100}, //mdp {0xFD922804,0x0600}, //dsi0 {0xFD511000,(CHIP_GPIO_COUNT_8226*4*4)} //gpio }; #elif defined(CONFIG_ARCH_MSM8916) #define CHIP_GPIO_COUNT_8916 122 static struct reg_desc mdss_reg_desc[]= { {0x1a00000,0x90000}, //mdp {0x1a98000,0x25c}, //dsi0 {0x1000000,(CHIP_GPIO_COUNT_8916*4*4)} //gpio }; #endif /* mdp_reg_info.txt contains the values to be initialized */ int read_ongoing; volatile u32 mdp_reg_info[354] = {16777216,4084,5246976,1052704,4140,4152,4176,4184,10489968,10490144,3150288,2101744,2101760,2101776,10490504,4816,5247716,4896,12587832,7345008,5247896,1053648,3150816,7348208,1056800,7348720,1057312,7349232,1057824,7349744,1058336,7350256,1058848,1069552,11555328,21056,21072,21088,19944056,21200,21216,21232,20992768,1069920,24560,25584,10506224,3166240,4214840,20576,4214932,2117824,2117840,2117872,2117888,2117904,1077744,11563520,29248,29264,29280,19952248,29392,29408,29424,21000960,1078112,32752,10514416,3174432,4223032,28768,4223124,2126016,2126032,2126064,2126080,2126096,1085936,11571712,37440,37456,37472,19960440,37584,37600,37616,21009152,1086304,40944,41968,10522608,3182624,4231224,36960,4231316,2134208,2134224,2134256,2134272,2134288,1135344,10571760,3231776,4280376,86112,4280468,2183360,2183376,2183408,2183424,2183440,1143536,10579952,3239968,4288568,94304,4288660,2191552,2191568,2191600,2191616,2191632,1151728,10588144,3248160,4296760,102496,4296852,2199744,2199760,2199792,2199808,2199824,2379760,282624,10768400,10768448,10768496,27545760,2380048,2380064,1331696,1331712,2380304,1332080,2383856,286720,10772496,10772544,10772592,27549856,2384144,2384160,1335792,1335808,2384400,1336176,2387952,290816,10776592,10776640,10776688,27553952,2388240,2388256,1339888,1339904,2388496,1340272,2392048,294912,10780688,10780736,10780784,27558048,2392336,2392352,1343984,1344000,2392592,1344368,2396144,299008,10784784,10784832,10784880,27562144,2396432,2396448,1348080,1348096,2396688,1348464,348144,348192,348208,348224,348240,348256,348272,348288,348304,348320,348336,348352,348368,348480,3494228,4542976,25514524,2445984,2446000,2446016,352240,353264,356336,356384,356400,356416,356432,356448,356464,356480,356496,356512,356528,356544,356560,356672,3502420,4551168,25522716,2454176,2454192,2454208,360432,361456,364528,364576,364592,364608,364624,364640,364656,364672,364688,364704,364720,364736,364752,364864,3510612,4559360,25530908,2462368,2462384,2462400,368624,369648,9850864,3559456,413752,413764,1462372,17191504,414368,9852912,3561504,415800,415812,1464420,17193552,416416,9854960,3563552,417848,417860,1466468,17195600,418464,9857008,3565600,419896,419908,1468516,17197648,420512,9859056,3567648,421944,421956,1470564,17199696,422560,21409776,1486920,438388,438400,2535576,438624,7778672,21411824,1488968,440436,440448,2537624,440672,7780720,21413872,1491016,442484,442496,2539672,442720,7782768,21415920,1493064,444532,444544,2541720,444768,7784816,13045744,13047792,13049840,49778672,6787256,4690136,23564528,49780720,6789304,4692184,23566576}; u32 mdp_reg_vaddr[354]; /*TODO: Optimize/correct this function*/ int check_duplicate_event(u32 *event_buff, u32 address) { int i; for (i=0; i< (debug_mdp->event_desc.len/sizeof(u32)); i++) { if(event_buff[i] == address) return -1; i+=15; //as the event dump struct is 64 bytes } return 0; } void inc_put(u32 *buff,u32 l){ buff[debug_mdp->log_buff.last] = l; debug_mdp->log_buff.last++; debug_mdp->log_buff.last %= (debug_mdp->log_buff.len/sizeof(u32)); if(debug_mdp->log_buff.last == debug_mdp->log_buff.first) { int count = buff[debug_mdp->log_buff.first] &0x1F; debug_mdp->log_buff.first += count; debug_mdp->log_buff.first %= (debug_mdp->log_buff.len/sizeof(u32)); } pr_debug("[DDEBUGGER] buff:%p, first:%d, last:%d, Val: %x\n",buff,debug_mdp->log_buff.first,debug_mdp->log_buff.last,(u32)l); return ; } #if defined(CONFIG_ARCH_MSM8974) static struct dclock clock_list[] = { {"mdss_ahb_clk",HWIO_MMSS_MDSS_AHB_CBCR_ADDR,CLK_TEST_MDSS_AHB_CLK,0}, {"mdss_axi_clk",HWIO_MMSS_MDSS_AXI_CBCR_ADDR,CLK_TEST_MDSS_AXI_CLK,0}, {"mdss_byte0_clk",HWIO_MMSS_MDSS_BYTE0_CBCR_ADDR,CLK_TEST_MDSS_BYTE0_CLK,0}, {"mdss_byte1_clk",HWIO_MMSS_MDSS_BYTE1_CBCR_ADDR,CLK_TEST_MDSS_BYTE1_CLK,0}, {"mdss_edpaux_clk",HWIO_MMSS_MDSS_EDPAUX_CBCR_ADDR,CLK_TEST_MDSS_EDPAUX_CLK,0}, {"mdss_edplink_clk",HWIO_MMSS_MDSS_EDPLINK_CBCR_ADDR,CLK_TEST_MDSS_EDPLINK_CLK,0}, {"mdss_edppixel_clk",HWIO_MMSS_MDSS_EDPPIXEL_CBCR_ADDR,CLK_TEST_MDSS_EDPPIXEL_CLK,0}, {"mdss_esc0_clk",HWIO_MMSS_MDSS_ESC0_CBCR_ADDR,CLK_TEST_MDSS_ESC0_CLK,0}, {"mdss_esc1_clk",HWIO_MMSS_MDSS_ESC1_CBCR_ADDR,CLK_TEST_MDSS_ESC1_CLK,0}, {"mdss_extpclk_clk",HWIO_MMSS_MDSS_EXTPCLK_CBCR_ADDR,CLK_TEST_MDSS_EXTPCLK_CLK,0}, {"mdss_hdmi_ahb_clk",HWIO_MMSS_MDSS_HDMI_AHB_CBCR_ADDR,CLK_TEST_MDSS_HDMI_AHB_CLK,0}, {"mdss_hdmi_clk",HWIO_MMSS_MDSS_HDMI_CBCR_ADDR,CLK_TEST_MDSS_HDMI_CLK,0}, {"mdss_mdp_clk",HWIO_MMSS_MDSS_MDP_CBCR_ADDR,CLK_TEST_MDSS_MDP_CLK,0}, {"mdss_mdp_lut_clk",HWIO_MMSS_MDSS_MDP_LUT_CBCR_ADDR,CLK_TEST_MDSS_MDP_LUT_CLK,0}, {"mdss_pclk0_clk",HWIO_MMSS_MDSS_PCLK0_CBCR_ADDR,CLK_TEST_MDSS_PCLK0_CLK,0}, {"mdss_pclk1_clk",HWIO_MMSS_MDSS_PCLK1_CBCR_ADDR,CLK_TEST_MDSS_PCLK1_CLK,0}, {"mdss_vsync_clk",HWIO_MMSS_MDSS_VSYNC_CBCR_ADDR,CLK_TEST_MDSS_VSYNC_CLK,0}, }; #elif defined(CONFIG_ARCH_MSM8226) static struct dclock clock_list[] = { {"mdss_ahb_clk",HWIO_MMSS_MDSS_AHB_CBCR_ADDR,CLK_TEST_MDSS_AHB_CLK,0}, {"mdss_axi_clk",HWIO_MMSS_MDSS_AXI_CBCR_ADDR,CLK_TEST_MDSS_AXI_CLK,0}, {"mdss_byte0_clk",HWIO_MMSS_MDSS_BYTE0_CBCR_ADDR,CLK_TEST_MDSS_BYTE0_CLK,0}, {"mdss_esc0_clk",HWIO_MMSS_MDSS_ESC0_CBCR_ADDR,CLK_TEST_MDSS_ESC0_CLK,0}, {"mdss_mdp_clk",HWIO_MMSS_MDSS_MDP_CBCR_ADDR,CLK_TEST_MDSS_MDP_CLK,0}, {"mdss_mdp_lut_clk",HWIO_MMSS_MDSS_MDP_LUT_CBCR_ADDR,CLK_TEST_MDSS_MDP_LUT_CLK,0}, {"mdss_pclk0_clk",HWIO_MMSS_MDSS_PCLK0_CBCR_ADDR,CLK_TEST_MDSS_PCLK0_CLK,0}, {"mdss_vsync_clk",HWIO_MMSS_MDSS_VSYNC_CBCR_ADDR,CLK_TEST_MDSS_VSYNC_CLK,0}, }; #elif defined(CONFIG_ARCH_MSM8916) /* static struct dclock clock_list[] = { {"mdss_ahb_clk",HWIO_MMSS_MDSS_AHB_CBCR_ADDR,CLK_TEST_MDSS_AHB_CLK,0}, }; */ //TODO .. define clocks here. #endif #define writelx(r,v) writel((v),(r)) void *vHWIO_GCC_DEBUG_CLK_CTL_ADDR = (void*)0xfc401880; void *vHWIO_MMSS_DEBUG_CLK_CTL_ADDR = (void*)0xfd8c0900; void *vHWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR = (void*)0xfc401888; void *vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR =(void*) 0xfc401884; void *vHWIO_GCC_XO_DIV4_CBCR_ADDR = (void*)0xfc4010c8; #if !defined(CONFIG_ARCH_MSM8916) static long read_clock(u32 clk_test,u32 clk_reg){ long clock_val; pr_debug("%s: test:0x%x reg:%x\n",__func__,clk_test,clk_reg); //Print_Clk_Info_Line { u32 is_on=0; u32 clk_freq=0; //u32 clk_freq_val=0; if(clk_reg != 0){ if((readl_relaxed((void*)clk_reg) & 0x80000000) == 0x0) is_on = 1; } pr_debug("%s:is_on:%d\n",__func__,is_on); if(!is_on) return 0; //Program Clock Test { u32 testval = clk_test & CLK_TEST_TYPE_MASK; u32 setval = clk_test & CLK_TEST_SEL_MASK; //u32 submuxval = clk_test & CLK_TEST_SUB_MUX_MASK; if(setval == CLK_MMSS_TEST) { writelx(vHWIO_GCC_DEBUG_CLK_CTL_ADDR,0x00013000|(0x2c&0x000001FF)); writelx(vHWIO_MMSS_DEBUG_CLK_CTL_ADDR,0x00010000|(testval&0x00000FFF)); } } pr_debug("%s:2\n",__func__); //Calc_Clk_Freq { //Configure l2cpuclkselr...for accuaracy u32 xo_div4_cbcr = readl_relaxed(vHWIO_GCC_XO_DIV4_CBCR_ADDR); u32 multiplier = 4; u32 tcxo_count = 0x800; u32 measure_ctl = 0; u32 short_clock_count; u32 clock_count = 0; u32 dbg_clk_ctl = 0; u32 temp = 0; //Measure a short run //Config XO DIV4 comparator clock writelx(vHWIO_GCC_XO_DIV4_CBCR_ADDR,readl_relaxed(vHWIO_GCC_XO_DIV4_CBCR_ADDR)|0x1); // Start with the counter disabled measure_ctl=readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR) ; measure_ctl=measure_ctl&~0x1FFFFF ; writelx(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR,measure_ctl); // Program the starting counter value, high enough to get good accuracy pr_debug("%s:measure_ctl:0x%x xo_div4_cbcr:0x%x \n",__func__,measure_ctl ,xo_div4_cbcr); measure_ctl= measure_ctl| tcxo_count; //Start the counting measure_ctl=measure_ctl|0x100000; writelx(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR,measure_ctl); pr_debug("HWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR:0x%X", readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR) ); //Wait for the counters to finish mdelay(1); while ((temp = readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR)&0x2000000)==0) pr_debug("HWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR:0x%X\n",temp); pr_debug("%s:4\n",__func__); // Turn off the test clock and read the clock count measure_ctl = readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR); writelx(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR, measure_ctl&~0x100000); pr_debug("%s:5\n",__func__); short_clock_count=readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR)&0x1FFFFFF; //Restore the register writelx(vHWIO_GCC_XO_DIV4_CBCR_ADDR,xo_div4_cbcr); pr_debug("%s:6:short_clock_count: %d\n",__func__,short_clock_count); //Longer count and compare xo_div4_cbcr = readl_relaxed(vHWIO_GCC_XO_DIV4_CBCR_ADDR); multiplier = 4; tcxo_count = 0x8000; //Config XO DIV4 comparator clock writelx(vHWIO_GCC_XO_DIV4_CBCR_ADDR,readl_relaxed(vHWIO_GCC_XO_DIV4_CBCR_ADDR)|0x1); pr_debug("%s:7\n",__func__); // Start with the counter disabled measure_ctl=readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR) ; measure_ctl=measure_ctl&~0x1FFFFF ; writelx(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR,measure_ctl); // Program the starting counter value, high enough to get good accuracy pr_debug("%s:8\n",__func__); measure_ctl= measure_ctl| tcxo_count; //Start the counting measure_ctl=measure_ctl|0x100000; writelx(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR,measure_ctl); pr_debug("%s:9\n",__func__); //Wait for the counters to finish mdelay(1); while ((readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR)&0x2000000)==0) ; // Turn off the test clock and read the clock count measure_ctl = readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR); writelx(vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR, measure_ctl&~0x100000); pr_debug("%s:10\n",__func__); clock_count=readl_relaxed(vHWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR)&0x1FFFFFF; if( clock_count == short_clock_count) clk_freq = 0; else clk_freq = (48*(2*multiplier)/10)*(2*clock_count+3)*2/(2*tcxo_count+7); /* need this for furthur implementation*/ //Restore the register writelx(vHWIO_GCC_XO_DIV4_CBCR_ADDR,xo_div4_cbcr); pr_debug("%s:11\n",__func__); //Clear the divide by 4 in DEBUG_CLK_CTL to make the scope view of the clock //the correct frequency dbg_clk_ctl=readl_relaxed(vHWIO_GCC_DEBUG_CLK_CTL_ADDR); dbg_clk_ctl=dbg_clk_ctl&~0x00003000; writelx(vHWIO_GCC_DEBUG_CLK_CTL_ADDR, dbg_clk_ctl); pr_debug("%s:12\n",__func__); //store freq clock_val = clock_count; } } return clock_val; } #endif #if !defined(CONFIG_ARCH_MSM8916) static int init_clock_va(void){ int i = 0; u32 clock_base_phy = 0xfd8c2300; u32 clock_base_virt = (u32)devm_ioremap(&mdss_res->pdev->dev, 0xfd8c2300,0xFF); if(!clock_base_virt) pr_err("Error Mapping Clock adress for %s",clock_list[i].name); for(;i < sizeof(clock_list)/sizeof(struct dclock);i++){ pr_debug("Mapping: clk: %s addr: %x\n",clock_list[i].name,clock_list[i].reg_addr); #ifdef __KERNEL__ if((clock_list[i].reg_addr - clock_base_phy) < 0) pr_err("Check clock base @@@@@@@@@@@@@!!!!!!!!!!!!!!!!\n"); else clock_list[i].vreg_addr = clock_base_virt + (clock_list[i].reg_addr - clock_base_phy); #else clock_list[i].vreg_addr = clock_list[i].reg_addr; #endif } for(i = 1; i < sizeof(mdss_reg_desc)/sizeof(struct reg_desc) ; i++){ mdss_reg_desc[i].vaddr = (u32)devm_ioremap(&mdss_res->pdev->dev, mdss_reg_desc[i].base,mdss_reg_desc[i].len*4); } return 0; } void dump_clock_state(void) { static u32 *buff = NULL; int i = 0; if(debug_mdp && debug_mdp->clock_state.len == 0) return; if(debug_mdp && buff == NULL) { buff = (u32 *)((char *)debug_mdp + (sizeof(struct debug_mdp) + debug_mdp->clock_state.offset)); } else if(!debug_mdp){ pr_debug("Debug module not Initialized\n"); return ; } pr_debug("debug_mdp : %p buff: %p end: %p",debug_mdp,buff,buff+ debug_mdp->clock_state.len); for(;i < sizeof(clock_list)/sizeof(struct dclock);i++){ u32 clock_val ; char *clk_ptr ; pr_debug("reading: %s i = %d, last: %d\n",clock_list[i].name,i,debug_mdp->clock_state.last); clk_ptr = (char *) &buff[debug_mdp->clock_state.last]; memcpy(clk_ptr,clock_list[i].name,sizeof(clock_list[i].name)); clock_val = read_clock(clock_list[i].test_reg, clock_list[i].vreg_addr); debug_mdp->clock_state.last += sizeof(clock_list[i].name)/sizeof(u32); pr_debug(" %s : %u :last : %d\n",clk_ptr,clock_val,debug_mdp->clock_state.last); buff[debug_mdp->clock_state.last++] = clock_val; pr_debug("buff[debug_mdp->clock_state.last++]: %p",&buff[debug_mdp->clock_state.last-1]); } } #else static int init_clock_va(void){ int i =0; //---------------------------- //TODO //Code for Clock_list is yet to be written here //TODO //----------------------------- for(i = 1; i < sizeof(mdss_reg_desc)/sizeof(struct reg_desc) ; i++){ mdss_reg_desc[i].vaddr = (u32)devm_ioremap(&mdss_res->pdev->dev, mdss_reg_desc[i].base,mdss_reg_desc[i].len*4); } return 0; } void dump_clock_state(void) { static u32 *buff = NULL; if(debug_mdp && debug_mdp->clock_state.len == 0) return; if(debug_mdp && buff == NULL) { buff = (u32 *)((char *)debug_mdp + (sizeof(struct debug_mdp) + debug_mdp->clock_state.offset)); } else if(!debug_mdp){ pr_debug("Debug module not Initialized\n"); return ; } pr_debug("debug_mdp : %p buff: %p end: %p",debug_mdp,buff,buff+ debug_mdp->clock_state.len); } #endif int fill_reg_log(u32 *buff, u32 base, int len) { int i; unsigned char *buf; #ifdef __KERNEL__ buf = (void*)base; #else buf = base; #endif // printk("value of Reg: 0x%X\n",base); for(i = 0; i < len/4; i++){ // printk("value of i = %d \n",i); pr_debug("buff:%p ",&buff[debug_mdp->reg_log.last]); buff[debug_mdp->reg_log.last] = MIPI_INP(buf+i*4); debug_mdp->reg_log.last++; } return 0; } /* void klog(void) is used to dump register values of dsi0, dsi1, edp and mdp registers respectively. Each section is identified by START_MAGIC followed by start address of registers. For mdp case the detailed information of register adresses is found in mdp_reg_addrs_and_len.txt */ void klog(void) { int i; static u32 *buff = NULL; int mdp_reg_count = 0; struct mdss_panel_data *pdata = NULL; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int mdp_reg_dump_en; unsigned long flags; /* NULL Checks */ if(mdata == NULL) return; if(mdata->ctl_off == NULL) return; pdata = (mdata->ctl_off+0)->panel_data; if(pdata ==NULL) return; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mdp_reg_dump_en = (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT); if(debug_mdp->reg_log.last*4 >= debug_mdp->reg_log.len ) return; if(debug_mdp->reg_log.len == 0) return; pr_debug("KK: -----------> Inside %s",__func__); #ifdef __KERNEL__ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); spin_lock_irqsave(&xlock, flags); #else if((readl_relaxed(HWIO_MMSS_MDSS_AHB_CBCR_ADDR) & 0x80000000) != 0x0) { pr_info("AHB Clock not ON, Cannot Read MDP Regs\n"); } //Switch on clcok #endif if(debug_mdp && buff == NULL){ buff = (u32 *)((char *)debug_mdp + (sizeof(struct debug_mdp) + debug_mdp->reg_log.offset)); } else if(!debug_mdp){ pr_info("Debug module not Initialized\n"); return ; } pr_debug("KK:------------------->(%s)::>> first: %x \t last: %x buff:%p-%p\n", __func__, debug_mdp->reg_log.first, debug_mdp->reg_log.last,buff,buff+debug_mdp->reg_log.len); if(!mdp_reg_dump_en) i = sizeof(mdss_reg_desc)/sizeof(struct reg_desc) -1; else i = 1; for(; i < sizeof(mdss_reg_desc)/sizeof(struct reg_desc) ; i++){ buff[debug_mdp->reg_log.last++] = START_MAGIC; buff[debug_mdp->reg_log.last++] = mdss_reg_desc[i].base; #if defined(__KERNEL__) //printk("kernel dump:for i=%d\n ",i); if(fill_reg_log(buff, mdss_reg_desc[i].vaddr, mdss_reg_desc[i].len)) pr_info("failed to dump lcd regs at %x ----------> KK\n",mdss_reg_desc[i].base); #else if(fill_reg_log(buff, base, len*4)) pr_info("failed to dump lcd regs at %x ----------> KK\n",base); #endif } #if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8916) if(mdp_reg_dump_en){ buff[debug_mdp->reg_log.last++] = START_MAGIC; buff[debug_mdp->reg_log.last++] = mdss_reg_desc[0].base; // printk("mdp base:%X",(u32)mdss_res->mdp_base); for(i = 0; i < sizeof(mdp_reg_info)/sizeof(u32)-1; i++){ int len; u32 base; len = mdp_reg_info[i] & 0xfff00000; len = len >> 20; len += 1; mdp_reg_count += len; base = mdp_reg_info[i] & 0x000fffff; // remove below addition TODO base += 0x10; #if defined(__KERNEL__) // printk("kernel dump:for mdp:0x%x\n ",mdp_reg_info[i]); if(fill_reg_log(buff, (u32) mdss_res->mdp_base +base, len*4)) pr_info("failed to dump lcd regs at %x ----------> KK\n",base); #else base = base | mdss_reg_desc[0].base; if(fill_reg_log(buff, base, len*4)) pr_info("failed to dump lcd regs at %x ----------> KK\n",base); #endif } } #endif #ifdef __KERNEL__ spin_unlock_irqrestore(&xlock, flags); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); #else //Switch off clock #endif pr_debug("total mdp regs: %d\n",mdp_reg_count); } void dlog(struct _dlogdebug *desc, ...) { va_list argp; static u32 *buff = NULL; unsigned long flags; int ev_idx = desc - __start___dlog; int para_count = 0; int temp_main_idx = 0 ; #ifdef __KERNEL__ ktime_t time; if(!debug_mdp) return; spin_lock_irqsave(&xlock, flags); if(read_ongoing) { spin_unlock_irqrestore(&xlock, flags); return; } #else time_t time; #endif if(debug_mdp && buff == NULL ) { buff= (u32 *)((char *)debug_mdp + (sizeof(struct debug_mdp) + debug_mdp->log_buff.offset)); } else if(!debug_mdp){ #ifdef __KERNEL__ spin_unlock_irqrestore(&xlock, flags); #endif pr_info("Debug Module Not Initialized\n"); return; } //Store the reference of 32bit header temp_main_idx = debug_mdp->log_buff.last; inc_put(buff,(current->pid<<16)|(ev_idx<<5)); #ifdef __KERNEL__ time = ktime_get(); inc_put(buff,(u32)ktime_to_us(time)); #else time = current_time(); inc_put(buff,(u32)time); #endif va_start(argp,(u32) desc); do{ u32 l = va_arg(argp, u32); // pr_info("[DLOG],%pS: %x\n",__builtin_return_address(0),l); if(l==0xBABEBABE) break; inc_put(buff,l); para_count++; }while(1); va_end(argp); para_count += 2;// 1 for main indx, 1 for time //Put the length buff[temp_main_idx] = buff[temp_main_idx] | (para_count & 0x1F); //5 bits for length #ifdef __KERNEL__ spin_unlock_irqrestore(&xlock, flags); #endif } #ifdef __KERNEL__ static unsigned long read_byte; /* * Called when a process tries to open the device file, like * "cat /dev/mycharfile" */ static int device_open(struct inode *inode, struct file *file) { read_byte = 0; printk(" Dlogger Opened>>>\n"); return 0; } static enum { DLOG_BUFFER_READING, KLOG_BUFFER_READING, SECLOG_BUFFER_READING, }read_state; int dlog_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { ssize_t retval = 0; unsigned long flags; int ret = 0; if(*f_pos == 0) { pr_info("===DLogger Header=====\n"); pr_info(" DUMP SIZE: %u, read: %lu\n",debug_mdp->size,read_byte); pr_info("[0] first: %d last: %d off: %d size: %d\n", debug_mdp->log_buff.first, debug_mdp->log_buff.last, debug_mdp->log_buff.offset, debug_mdp->log_buff.len); pr_info("[1] first: %d last: %d off: %d size: %d\n", debug_mdp->event_desc.first, debug_mdp->event_desc.last, debug_mdp->event_desc.offset, debug_mdp->event_desc.len); pr_info("[2] first: %d last: %d off: %d size: %d\n", debug_mdp->reg_log.first, debug_mdp->reg_log.last, debug_mdp->reg_log.offset, debug_mdp->reg_log.len); pr_info("[3] first: %d last: %d off: %d size: %d\n", debug_mdp->clock_state.first, debug_mdp->clock_state.last, debug_mdp->clock_state.offset, debug_mdp->clock_state.len); #ifdef __KERNEL__ spin_lock_irqsave(&xlock, flags); read_ongoing = 1; debug_mdp->reserv = CONFIG_NR_CPUS; #ifdef CONFIG_SEC_DEBUG_SCHED_LOG debug_mdp->klog_size =secdbg_krait->log.size; debug_mdp->seclog_size = 0; pr_debug("Klog Size: %d SecLog Size: %d\n", debug_mdp->klog_size, debug_mdp->seclog_size); #endif // sec_debug_display_klog_addr(&klog_addr); spin_unlock_irqrestore(&xlock, flags); #endif } if(read_state == DLOG_BUFFER_READING && read_byte >= debug_mdp->size ) { #ifdef __KERNEL__ spin_lock_irqsave(&xlock, flags); read_ongoing = 0; debug_mdp->reg_log.first = 0; debug_mdp->reg_log.last = 0; debug_mdp->clock_state.first = 0; debug_mdp->clock_state.last = 0; read_state = KLOG_BUFFER_READING; spin_unlock_irqrestore(&xlock, flags); #endif #ifndef CONFIG_SEC_DEBUG_SCHED_LOG read_state = DLOG_BUFFER_READING; read_byte = 0; pr_info("Reading complete...\n"); return 0; #endif } if(read_state == DLOG_BUFFER_READING) { pr_debug("(count + *f_pos - 1):=%llu\n",(count + *f_pos - 1)); retval = ((count + *f_pos - 1)< debug_mdp->size)? count-1:(debug_mdp->size - *f_pos); ret = copy_to_user(buf, (char *)debug_mdp + *f_pos, retval); if(ret < 0) return 0; read_byte += retval; *f_pos = read_byte; pr_debug("-read: %lu, fpos = %llu :count = %d:retval: %d: dump_size: %d\n",read_byte,*f_pos,count,retval,debug_mdp->size); } #ifdef CONFIG_SEC_DEBUG_SCHED_LOG if(read_state == KLOG_BUFFER_READING && read_byte >= debug_mdp->size + debug_mdp->klog_size ) { read_state = DLOG_BUFFER_READING; read_byte = 0; pr_info("Reading complete...\n"); } if(read_state == KLOG_BUFFER_READING) { #if 0 int start = *f_pos - debug_mdp->size; #endif retval = ((count + *f_pos - 1)< debug_mdp->size +debug_mdp->klog_size)? count-1:(debug_mdp->size +debug_mdp->klog_size- *f_pos); #if 0 ret = copy_to_user(buf, ((char *)klog_addr) + start, retval); #endif if(ret < 0) return 0; read_byte += retval; *f_pos = read_byte; } #endif return retval; } static int reg_open(struct inode *inode, struct file *file) { pr_info("Register dump opened\n"); return 0; } int reg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { //dump_clock_state(); klog(); return 0; } static const struct file_operations reg_fops = { .open = reg_open, .release = NULL, .read = reg_read, .write = NULL, }; static const struct file_operations dlog_fops = { .open = device_open, .release = NULL, .read = dlog_read, .write = NULL, }; static int __init setup_debug_memory(char *mode) { __debug_mdp_phys = 0; if(!sscanf(mode,"%x", &(__debug_mdp_phys))) pr_err("Error parsing display logging mem base:%s\n",mode); else pr_info("Display Logging base: %x\n",__debug_mdp_phys); return 1; } /* Get the size of description section needed */ static int get_desc_size(void){ int len = __stop___dlog - __start___dlog; int i = 0; int str_len = 0; for(; i < len; i++) { struct _dlogdebug *ptr = __start___dlog + i; str_len += strlen(ptr->filename) + 1; str_len += strlen(ptr->format) + 1; str_len += strlen(ptr->function) + 1; str_len += 4; //flags + lineno } return str_len; } /* Initialize event descriptor section */ static void init_event_desc(char *buff,int length){ int len = __stop___dlog - __start___dlog; int i = 0; int str_len = 0; memset(buff,0x0,length); for(; (i < len && str_len < length); i++) { struct _dlogdebug *ptr = __start___dlog + i; int *line_ptr = 0; str_len += (snprintf(buff+str_len,length-str_len,"%s", ptr->filename) + 1); str_len += (snprintf(buff+str_len,length-str_len,"%s", ptr->format) + 1); str_len += (snprintf(buff+str_len,length-str_len,"%s", ptr->function) + 1); line_ptr = (int *) (buff + str_len); *line_ptr = ptr->lineno | ptr->flags<<24; str_len += 4; //flags + lineno if(str_len >= length) break; } } int dlog_sec_get_debug_level(void) { return sec_debug_level; } __setup("lcd_dlog_base=", setup_debug_memory); #endif #ifdef __KERNEL__ static int __init mdss_debug_init(void) { #else int mdss_debug_init(void) { #endif u32 log_buff_len = DLOG_BUFFER_SIZE_SHIP*1024 - sizeof(struct debug_mdp); u32 event_desc_len = 0; u32 reg_log_len = 0; u32 clock_state_len = 0; struct dentry *dent = debugfs_create_dir("dlog", NULL); #if defined(CONFIG_SEC_DEBUG) sec_debug_level = sec_debug_is_enabled(); #endif if(sec_debug_level){ log_buff_len = DLOG_BUFFER_SIZE*1024; event_desc_len = get_desc_size(); reg_log_len = REGISTER_LOG_LEN*1024; clock_state_len = CLOCK_DUMP_LEN*1024; } dump_size = log_buff_len + event_desc_len+ reg_log_len \ +clock_state_len+ sizeof(struct debug_mdp); #ifdef __KERNEL__ if(mdss_res && __debug_mdp_phys){ debug_mdp = devm_ioremap(&mdss_res->pdev->dev, __debug_mdp_phys, CARVEOUT_MEM_SIZE); pr_info("Using MDSS debug memory from LK:Phys: %x, VA: %p\n",__debug_mdp_phys,debug_mdp); } if(!__debug_mdp_phys || !debug_mdp) { debug_mdp = kzalloc (dump_size, GFP_KERNEL); if(!debug_mdp) { pr_err("Memory allocation failed for MDP DEBUG MODULE\n"); return -1; } } //debug_mdp->log_buff.offset = 0; pr_info(KERN_INFO "MDP debug init:debug_mdp: %p \n",debug_mdp); #else debug_mdp = __debug_mdp_phys; memset(debug_mdp,0x0,CARVEOUT_MEM_SIZE); #endif if(!__debug_mdp_phys || (__debug_mdp_phys == (u32)debug_mdp)){ /* Initialize buffer header */ debug_mdp->log_buff.len = log_buff_len; debug_mdp->event_desc.offset = debug_mdp->log_buff.offset + debug_mdp->log_buff.len; debug_mdp->event_desc.len = event_desc_len; debug_mdp->reg_log.offset = debug_mdp->event_desc.offset + debug_mdp->event_desc.len; debug_mdp->reg_log.len = reg_log_len; debug_mdp->clock_state.offset = debug_mdp->reg_log.offset + debug_mdp->reg_log.len; debug_mdp->clock_state.len = clock_state_len; debug_mdp->size = dump_size; pr_info("size:%d",sizeof(debug_mdp->size)); strncpy(debug_mdp->marker,"*#$$_START_OF_MDP_DEBUG_DUMP##$", sizeof("*#$$_START_OF_MDP_DEBUG_DUMP##$")); if(debug_mdp !=NULL) init_event_desc((char *)debug_mdp + (sizeof(struct debug_mdp) + debug_mdp->event_desc.offset), debug_mdp->event_desc.len); }else { pr_info("===DLogger Header=====\n"); pr_info(" DUMP SIZE: %u\n",debug_mdp->size); pr_info("[0] first: %d last: %d off: %d size: %d\n", debug_mdp->log_buff.first, debug_mdp->log_buff.last, debug_mdp->log_buff.offset, debug_mdp->log_buff.len); pr_info("[1] first: %d last: %d off: %d size: %d\n", debug_mdp->event_desc.first, debug_mdp->event_desc.last, debug_mdp->event_desc.offset, debug_mdp->event_desc.len); pr_info("[2] first: %d last: %d off: %d size: %d\n", debug_mdp->reg_log.first, debug_mdp->reg_log.last, debug_mdp->reg_log.offset, debug_mdp->reg_log.len); pr_info("[2] first: %d last: %d off: %d size: %d\n", debug_mdp->clock_state.first, debug_mdp->clock_state.last, debug_mdp->clock_state.offset, debug_mdp->clock_state.len); } #ifdef __KERNEL__ spin_lock_init(&xlock); { if(mdss_res && sec_debug_level) { init_clock_va(); vHWIO_GCC_DEBUG_CLK_CTL_ADDR = devm_ioremap(&mdss_res->pdev->dev, 0xfc401880, 4); vHWIO_MMSS_DEBUG_CLK_CTL_ADDR = devm_ioremap(&mdss_res->pdev->dev, 0xfd8c0900, 4); vHWIO_GCC_CLOCK_FRQ_MEASURE_STATUS_ADDR = devm_ioremap(&mdss_res->pdev->dev, 0xfc401888, 4); vHWIO_GCC_CLOCK_FRQ_MEASURE_CTL_ADDR = devm_ioremap(&mdss_res->pdev->dev, 0xfc401884, 4); vHWIO_GCC_XO_DIV4_CBCR_ADDR = devm_ioremap(&mdss_res->pdev->dev, 0xfc4010c8, 4); if (debugfs_create_file("reg_dump", 0644, dent, 0, ®_fops) == NULL) { printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n", __FILE__, __LINE__); return -1; } pr_info("Init Section: %p",__start___dlog); } if (debugfs_create_file("dlogger", 0644, dent, 0, &dlog_fops) == NULL) { printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n", __FILE__, __LINE__); return -1; } } #endif return 0; } #ifdef __KERNEL__ arch_initcall(mdss_debug_init); #endif