u32 de_pll_enable(__disp_clk_id_t clk_id, s32 bOnOff) { u32 i; u32 count; u32 reg_val; count = sizeof(disp_clk_pll_tbl) / sizeof(clk_pll_para); for(i = 0; i < count; i++) { if(disp_clk_pll_tbl[i].clk_id == clk_id) { reg_val = smc_readl(disp_clk_pll_tbl[i].pll_adr); if(bOnOff) { pll_enable_count[i]++; if(pll_enable_count[i] == 1) { reg_val = SET_BITS(disp_clk_pll_tbl[i].enable_shift, 1, reg_val, 1); modify_cpu_source_ctrl(); smc_writel(reg_val, disp_clk_pll_tbl[i].pll_adr); restore_cpu_source_ctrl(); if(disp_clk_pll_tbl[i].src_id) { de_pll_enable(disp_clk_pll_tbl[i].src_id, bOnOff); } } __inf("enable pll %d\n", clk_id); return 1; } else { if(pll_enable_count[i] == 0) { __wrn("pll %d is already disable\n", clk_id); } pll_enable_count[i]--; if(pll_enable_count[i] == 0) { reg_val = SET_BITS(disp_clk_pll_tbl[i].enable_shift, 1, reg_val, 0); modify_cpu_source_ctrl(); smc_writel(reg_val, disp_clk_pll_tbl[i].pll_adr); restore_cpu_source_ctrl(); if(disp_clk_pll_tbl[i].src_id) { de_pll_enable(disp_clk_pll_tbl[i].src_id, bOnOff); } } __inf("disable pll %d\n", clk_id); return 1; } } } return 0; }
void de_clk_init_pll(void) { u32 i; u32 count; count = sizeof(disp_clk_pll_tbl) / sizeof(clk_pll_para); for(i = 0; i < count; i++) { if(disp_clk_pll_tbl[i].freq) de_set_pll_rate(disp_clk_pll_tbl[i].clk_id, disp_clk_pll_tbl[i].freq); } /* PLL BIAS default config */ smc_writel(0x00040000, PLL7_BIAS); smc_writel(0x00040000, PLL8_BIAS); }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void sunxi_clear_fel_flag(void) { volatile uint reg_val; do { smc_writel((1<<16), SUNXI_RPRCM_BASE + 0x1f0); smc_writel((1<<16) | (1U<<31), SUNXI_RPRCM_BASE + 0x1f0); __usdelay(10); CP15ISB; CP15DMB; smc_writel((1<<16), SUNXI_RPRCM_BASE + 0x1f0); reg_val = smc_readl(SUNXI_RPRCM_BASE + 0x1f0); } while((reg_val & 0xff) != 0); }
u32 de_set_pll_rate(__disp_clk_id_t clk_id, u32 freq) { u32 fac_N, fac_M, ext_fac; u32 reg_val; if(clk_id == SYS_CLK_PLL7) { reg_val = smc_readl(disp_clk_pll_tbl[0].pll_adr); calc_src_coef2(&fac_M, &fac_N, freq); reg_val = SET_BITS(disp_clk_pll_tbl[0].fac_shift, disp_clk_pll_tbl[0].fac_bit_num, reg_val, fac_N); reg_val = SET_BITS(disp_clk_pll_tbl[0].div_shift, disp_clk_pll_tbl[0].div_bit_num, reg_val, fac_M); smc_writel(reg_val, disp_clk_pll_tbl[0].pll_adr); return 1; } else if(clk_id == SYS_CLK_PLL8) { reg_val = smc_readl(disp_clk_pll_tbl[1].pll_adr); calc_pll8_coef(&fac_M, &ext_fac, &fac_N, freq); if(freq == 297000000) { fac_N = 0xc6; fac_M = 0x1; ext_fac = 0x3; } reg_val = SET_BITS(disp_clk_pll_tbl[1].fac_shift, disp_clk_pll_tbl[1].fac_bit_num, reg_val, fac_N); reg_val = SET_BITS(disp_clk_pll_tbl[1].div_shift, disp_clk_pll_tbl[1].div_bit_num, reg_val, fac_M); reg_val = SET_BITS(disp_clk_pll_tbl[1].ext_div_shift, disp_clk_pll_tbl[1].ext_div_bit_num, reg_val, ext_fac); smc_writel(reg_val, disp_clk_pll_tbl[1].pll_adr); return 1; } else if(clk_id == SYS_CLK_PLL10) { reg_val = smc_readl(disp_clk_pll_tbl[2].pll_adr); calc_src_coef3(&fac_M, &ext_fac, &fac_N, freq); reg_val = SET_BITS(disp_clk_pll_tbl[2].fac_shift, disp_clk_pll_tbl[2].fac_bit_num, reg_val, fac_N); reg_val = SET_BITS(disp_clk_pll_tbl[2].div_shift, disp_clk_pll_tbl[2].div_bit_num, reg_val, fac_M); reg_val = SET_BITS(disp_clk_pll_tbl[2].ext_div_shift, disp_clk_pll_tbl[2].ext_div_bit_num, reg_val, ext_fac); smc_writel(reg_val, disp_clk_pll_tbl[2].pll_adr); return 1; } else { } __wrn("set pll freq fail!\n"); return 0; }
void restore_cpu_source_ctrl(void) { u32 reg_val; reg_val = smc_readl(CCM_CPU_SOURCECTRL); reg_val |= 1; smc_writel(reg_val, CCM_CPU_SOURCECTRL); __usdelay(1000); dmb(); isb(); }
void modify_cpu_source_ctrl(void) { u32 reg_val; reg_val = smc_readl(CCM_CPU_SOURCECTRL); reg_val &= ~1; smc_writel(reg_val, CCM_CPU_SOURCECTRL); __usdelay(10); dmb(); isb(); }
u32 de_set_mclk_src(__hdle clk_hdl) { u32 i; u32 count; u32 reg_val; clk_mod_para *hdl = (clk_mod_para*)clk_hdl; count = sizeof(disp_clk_mod_tbl) / sizeof(clk_mod_para); for(i = 0; i < count; i++) { if(disp_clk_mod_tbl[i].clk_id == hdl->clk_id) { reg_val = smc_readl(disp_clk_mod_tbl[i].mod_adr); if(disp_clk_mod_tbl[i].src_id == SYS_CLK_PLL7) { reg_val = SET_BITS(disp_clk_mod_tbl[i].mod_src_shift, disp_clk_mod_tbl[i].mod_src_bit_num, reg_val, 8); smc_writel(reg_val, disp_clk_mod_tbl[i].mod_adr); return 1; } else if(disp_clk_mod_tbl[i].src_id == SYS_CLK_PLL8) { reg_val = SET_BITS(disp_clk_mod_tbl[i].mod_src_shift, disp_clk_mod_tbl[i].mod_src_bit_num, reg_val, 9); smc_writel(reg_val, disp_clk_mod_tbl[i].mod_adr); return 1; } else if(disp_clk_mod_tbl[i].src_id == SYS_CLK_PLL10) { reg_val = SET_BITS(disp_clk_mod_tbl[i].mod_src_shift, disp_clk_mod_tbl[i].mod_src_bit_num, reg_val, 11); smc_writel(reg_val, disp_clk_mod_tbl[i].mod_adr); return 1; } else { break; } } } __wrn("set mod clock %d src fail!\n", hdl->clk_id); return 0; }
u32 de_set_mclk_freq(__hdle clk_hdl, u32 nFreq) { u32 i; u32 count; u32 src_freq; u32 div; __disp_clk_id_t src_id; u32 reg_val; src_id = de_get_mclk_src(clk_hdl); if(!src_id) { __wrn("get mode clk src fail!\n"); return 0; } src_freq = de_get_pll_rate(src_id); if(!src_freq) { __wrn("get src freq fail!\n"); return 0; } clk_mod_para *hdl = (clk_mod_para*)clk_hdl; count = sizeof(disp_clk_mod_tbl) / sizeof(clk_mod_para); for(i = 0; i < count; i++) { if(disp_clk_mod_tbl[i].clk_id == hdl->clk_id) { if(nFreq == 0) { nFreq = disp_clk_mod_tbl[i].freq; } if(nFreq == 0) { __wrn("get mode clk %d freq from table fail\n", hdl->clk_id); return 0; } div = (src_freq + nFreq / 2 - 1) / nFreq; if((div > 16) || (div < 1)) { __wrn("div is overflow\n"); return 0; } reg_val = smc_readl(disp_clk_mod_tbl[i].mod_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].mod_div_shift, disp_clk_mod_tbl[i].mod_div_bit_num, reg_val, (div - 1)); smc_writel(reg_val, disp_clk_mod_tbl[i].mod_adr); return 1; } } __wrn("get clk %d hdl fail\n", hdl->clk_id); return 0; }
s32 bsp_disp_init(__disp_bsp_init_para * para) { u32 num_screens, screen_id; #if defined(CONFIG_ARCH_SUN9IW1P1) u32 temp; #endif memset(&gdisp,0x00,sizeof(__disp_dev_t)); memcpy(&gdisp.init_para,para,sizeof(__disp_bsp_init_para)); para->shadow_protect = bsp_disp_shadow_protect; disp_init_feat(); num_screens = bsp_disp_feat_get_num_screens(); for(screen_id = 0; screen_id < num_screens; screen_id++) { #if defined(__LINUX_PLAT__) spin_lock_init(&gdisp.screen[screen_id].flag_lock); #endif } #if defined(CONFIG_ARCH_SUN9IW1P1) //for_test // temp = *((volatile u32*)(0x060005a8)); // temp = temp | 0x4; // *((volatile u32*)(0x060005a8)) = temp; temp = smc_readl(0x060005a8); temp |= 4; smc_writel(temp, 0x060005a8); #endif //bsp_disp_set_print_level(DEFAULT_PRINT_LEVLE); disp_notifier_init(); disp_init_al(para); disp_init_lcd(para); #if defined(CONFIG_ARCH_SUN9IW1P1) disp_init_hdmi(para); disp_init_cursor(para); #endif disp_init_mgr(para); disp_init_lyr(para); disp_init_smcl(para); disp_init_smbl(para); disp_init_connections(); return DIS_SUCCESS; }
int power_config_gpio_bias(void) { char gpio_bias[32], gpio_name[32]; char *gpio_name_const="pa_bias"; char port_index; char *axp=NULL, *supply=NULL, *vol=NULL; uint main_hd; uint bias_vol_set; int index, ret, i; uint port_bias_addr; uint vol_index, config_type; int pmu_vol; struct bias_set bias_vol_config[8] = { {1800, 0}, {2500, 6}, {2800, 9}, {3000, 0xa}, {3300, 0xd}, {0, 0} }; main_hd = script_parser_fetch_subkey_start("gpio_bias"); if(main_hd == 0) { printf("gpio_bias not exist\n"); return 0; } index = 0; while(1) { memset(gpio_bias, 0, 32); memset(gpio_name, 0, 32); ret = script_parser_fetch_subkey_next(main_hd, gpio_name, (int *)gpio_bias, &index); if(!ret) { lower(gpio_name); lower(gpio_bias); port_index = gpio_name[1]; gpio_name[1] = 'a'; if(strcmp(gpio_name_const, gpio_name)) { printf("invalid gpio bias name %s\n", gpio_name); continue; } gpio_name[1] = port_index; i=0; axp = gpio_bias; while( (gpio_bias[i]!=':') && (gpio_bias[i]!='\0') ) { i++; } gpio_bias[i++]='\0'; if(!strcmp(axp, "constant")) { config_type = 1; } else if(!strcmp(axp, "floating")) { printf("ignore %s bias config\n", gpio_name); continue; } else { config_type = 0; } if(config_type == 0) { supply = gpio_bias + i; while( (gpio_bias[i]!=':') && (gpio_bias[i]!='\0') ) { i++; } gpio_bias[i++]='\0'; } printf("supply=%s\n", supply); vol = gpio_bias + i; while( (gpio_bias[i]!=':') && (gpio_bias[i]!='\0') ) { i++; } bias_vol_set = simple_strtoul(vol, NULL, 10); for(i=0;i<5;i++) { if(bias_vol_config[i].vol == bias_vol_set) { break; } } if(i==5) { printf("invalid gpio bias set vol %d, at name %s\n", bias_vol_set, gpio_name); break; } vol_index = bias_vol_config[i].index; if((port_index >= 'a') && (port_index <= 'h')) { //获取寄存器地址 port_bias_addr = SUNXI_PIO_BASE + 0x300 + 0x4 * (port_index - 'a'); } else if(port_index == 'j') { //获取寄存器地址 port_bias_addr = SUNXI_PIO_BASE + 0x300 + 0x4 * (port_index - 'a'); } else if((port_index == 'l') || (port_index == 'm')) { //获取寄存器地址 port_bias_addr = SUNXI_RPIO_BASE + 0x300 + 0x4 * (port_index - 'l'); } else { printf("invalid gpio port at name %s\n", gpio_name); continue; } printf("axp=%s, supply=%s, vol=%d\n", axp, supply, bias_vol_set); if(config_type == 1) { smc_writel(vol_index, port_bias_addr); } else { pmu_vol = axp_probe_supply_status_byname(axp, supply); if(pmu_vol < 0) { printf("sunxi board read %s %s failed\n", axp, supply); continue; } if(pmu_vol > bias_vol_set) //pmu实际电压超过需要设置的电压 { //电压降低到需要电压 axp_set_supply_status_byname(axp, supply, bias_vol_set, 1); //设置寄存器 smc_writel(vol_index, port_bias_addr); } else if(pmu_vol < bias_vol_set) //pmu实际电压低于需要设置的电压 { //设置寄存器 smc_writel(vol_index, port_bias_addr); //把pmu电压调整到需要的电压 axp_set_supply_status_byname(axp, supply, bias_vol_set, 1); } else { //如果实际电压等于需要设置电压,直接设置即可 smc_writel(vol_index, port_bias_addr); } } printf("reg addr=0x%x, value=0x%x, pmu_vol=%d\n", port_bias_addr, smc_readl(port_bias_addr), bias_vol_set); } else { printf("config gpio bias voltage finish\n"); break; } } return 0; }
u32 de_top_clk_enable(__disp_clk_id_t clk_id, s32 bOnOff) { u32 i; u32 count; u32 reg_val; count = sizeof(disp_de_top_tbl) / sizeof(de_top_para); for(i = 0; i < count; i++) { if(disp_de_top_tbl[i].clk_id == clk_id) { if(bOnOff) { de_top_enable_count[i]++; if(de_top_enable_count[i] == 1) { if(disp_de_top_tbl[i].mod_enable_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].mod_adr); reg_val = SET_BITS(disp_de_top_tbl[i].mod_enable_shift, 1, reg_val, 1); smc_writel(reg_val, disp_de_top_tbl[i].mod_adr); __inf("clk %d mod enable\n", clk_id); } if(disp_de_top_tbl[i].ahb_gate_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].ahb_gate_adr); reg_val = SET_BITS(disp_de_top_tbl[i].ahb_gate_shift, 1, reg_val, 1); smc_writel(reg_val, disp_de_top_tbl[i].ahb_gate_adr); __inf("clk %d gate enable\n", clk_id); } if(disp_de_top_tbl[i].ahb_reset_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].ahb_reset_adr); reg_val = SET_BITS(disp_de_top_tbl[i].ahb_reset_shift, 1, reg_val, 1); smc_writel(reg_val, disp_de_top_tbl[i].ahb_reset_adr); __inf("clk %d reset enable\n", clk_id); } if(disp_de_top_tbl[i].dram_gate_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].dram_gate_adr); reg_val = SET_BITS(disp_de_top_tbl[i].dram_gate_shift, 1, reg_val, 1); smc_writel(reg_val, disp_de_top_tbl[i].dram_gate_adr); __inf("clk %d dram enable\n", clk_id); } } } else { if(de_top_enable_count[i] == 0) { __wrn("de top clk %d is already close\n", clk_id); return 0; } de_top_enable_count[i]--; if(de_top_enable_count[i] == 0) { if(disp_de_top_tbl[i].mod_enable_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].mod_adr); reg_val = SET_BITS(disp_de_top_tbl[i].mod_enable_shift, 1, reg_val, 0); smc_writel(reg_val, disp_de_top_tbl[i].mod_adr); __inf("clk %d mod disable\n", clk_id); } if(disp_de_top_tbl[i].ahb_gate_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].ahb_gate_adr); reg_val = SET_BITS(disp_de_top_tbl[i].ahb_gate_shift, 1, reg_val, 0); smc_writel(reg_val, disp_de_top_tbl[i].ahb_gate_adr); __inf("clk %d gate disable\n", clk_id); } if(disp_de_top_tbl[i].ahb_reset_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].ahb_reset_adr); reg_val = SET_BITS(disp_de_top_tbl[i].ahb_reset_shift, 1, reg_val, 0); smc_writel(reg_val, disp_de_top_tbl[i].ahb_reset_adr); __inf("clk %d reset disable\n", clk_id); } if(disp_de_top_tbl[i].dram_gate_shift < 32) { reg_val = smc_readl(disp_de_top_tbl[i].dram_gate_adr); reg_val = SET_BITS(disp_de_top_tbl[i].dram_gate_shift, 1, reg_val, 0); smc_writel(reg_val, disp_de_top_tbl[i].dram_gate_adr); __inf("clk %d dram disable\n", clk_id); } } } } } return 0; }
u32 de_top_clk_set_freq(__disp_clk_id_t clk_id, u32 nFreq) { u32 i; u32 count; u32 src_freq; u32 reg_val; u32 div; __hdle hdl; count = sizeof(disp_clk_mod_tbl) / sizeof(clk_mod_para); for(i = 0; i < count; i++) { if(disp_clk_mod_tbl[i].clk_id == MOD_CLK_DETOP) { hdl = (__hdle)&disp_clk_mod_tbl[i]; break; } __wrn("get detop clk fail\n"); return 0; } src_freq = de_get_mclk_freq(hdl); if(src_freq == 0) { __wrn("get mod clk freq fail\n"); return 0; } count = sizeof(disp_de_top_tbl) / sizeof(de_top_para); for(i = 0; i < count; i++) { if(disp_de_top_tbl[i].clk_id == clk_id) { nFreq = de_clk_freq; if(nFreq == 0) { nFreq = disp_de_top_tbl[i].freq; } if(nFreq == 0) { __wrn("de top set freq is 0\n"); return 0; } div = (src_freq + nFreq / 2 - 1) / nFreq; if((div > 16) || (div < 1)) { __wrn("de top clk div is overflow\n"); return 0; } reg_val = smc_readl(disp_de_top_tbl[i].mod_div_adr); reg_val = SET_BITS(disp_de_top_tbl[i].mod_div_shift, 4, reg_val, (div -1)); smc_writel(reg_val, disp_de_top_tbl[i].mod_div_adr); return 1; } } return 0; }
u32 de_mclk_enable(__hdle clk_hdl, s32 bOnOff) { u32 i; u32 count; u32 reg_val; clk_mod_para *hdl = (clk_mod_para*)clk_hdl; __inf("mod %d clock enable\n", hdl->clk_id); count = sizeof(disp_clk_mod_tbl) / sizeof(clk_mod_para); for(i = 0; i < count; i++) { if(disp_clk_mod_tbl[i].clk_id == hdl->clk_id) { if(bOnOff) { mod_enable_count[i]++; if(mod_enable_count[i] == 1) { if(disp_clk_mod_tbl[i].mod_enable_shift < 32) { reg_val = smc_readl(disp_clk_mod_tbl[i].mod_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].mod_enable_shift, 1, reg_val, 1); __inf("mod clock %d enable on\n", hdl->clk_id); smc_writel(reg_val, disp_clk_mod_tbl[i].mod_adr); } if(disp_clk_mod_tbl[i].ahb_gate_shift < 32) { reg_val = smc_readl(disp_clk_mod_tbl[i].ahb_gate_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].ahb_gate_shift, 1, reg_val, 1); __inf("mod clock %d ahb gate on\n", hdl->clk_id); smc_writel(reg_val, disp_clk_mod_tbl[i].ahb_gate_adr); } if(disp_clk_mod_tbl[i].ahb_reset_shift < 32) { reg_val = smc_readl(disp_clk_mod_tbl[i].ahb_reset_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].ahb_reset_shift, 1, reg_val, 1); __inf("mod clock %d ahb reset on\n", hdl->clk_id); smc_writel(reg_val, disp_clk_mod_tbl[i].ahb_reset_adr); } if(disp_clk_mod_tbl[i].src_id) { de_pll_enable(disp_clk_mod_tbl[i].src_id, bOnOff); } } return 1; } else { if(mod_enable_count[i] == 0) { __wrn("mod %d is already disable\n", hdl->clk_id); break; } mod_enable_count[i]--; if(mod_enable_count[i] == 0) { if(disp_clk_mod_tbl[i].mod_enable_shift < 32) { reg_val = smc_readl(disp_clk_mod_tbl[i].mod_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].mod_enable_shift, 1, reg_val, 0); __inf("mod clock %d enable off\n", hdl->clk_id); smc_writel(reg_val, disp_clk_mod_tbl[i].mod_adr); } if(disp_clk_mod_tbl[i].ahb_gate_shift < 32) { reg_val = smc_readl(disp_clk_mod_tbl[i].ahb_gate_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].ahb_gate_shift, 1, reg_val, 0); __inf("mod clock %d ahb gate off\n", hdl->clk_id); smc_writel(reg_val, disp_clk_mod_tbl[i].ahb_gate_adr); } if(disp_clk_mod_tbl[i].ahb_reset_shift < 32) { reg_val = smc_readl(disp_clk_mod_tbl[i].ahb_reset_adr); reg_val = SET_BITS(disp_clk_mod_tbl[i].ahb_reset_shift, 1, reg_val, 0); __inf("mod clock %d ahb reset off\n", hdl->clk_id); smc_writel(reg_val, disp_clk_mod_tbl[i].ahb_reset_adr); } if(disp_clk_mod_tbl[i].src_id) { de_pll_enable(disp_clk_mod_tbl[i].src_id, bOnOff); } } return 1; } } } return 0; }