SmartAudio/lichee/brandy/u-boot-2011.09/board/sunxi/load_check.c

504 lines
12 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (C) Copyright 2007-2013
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Jerry Wang <wangflord@allwinnertech.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <malloc.h>
#include <asm/arch/drv_display.h>
#include <bat.h>
#include <sys_config.h>
#include <asm/arch/timer.h>
#include <pmu.h>
#include <power.h>
#include "bat_cartoon.h"
#include "power_probe.h"
#include "de.h"
#include <standby.h>
DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_NO_BOOT_STANDBY
int boot_standby_action = 0;
typedef int (* standby_func)(void);
static int board_try_boot_standby(void)
{
uint func_addr = (uint)boot_standby_mode;
standby_func boot_standby_func;
//cal the real function address of boot_standby_mode
flush_dcache_all();
boot_standby_func = (standby_func)(func_addr - gd->reloc_off);
return boot_standby_func();
}
#endif
extern int efex_test;
static int board_probe_power_level(void)
{
int power_status;
int power_start;
//Çå³ýpower°´¼ü
axp_probe_key();
//»ñÈ¡µçԴ״̬
power_status = axp_get_power_vol_level();
debug("power status = %d\n", power_status);
if(power_status == BATTERY_RATIO_TOO_LOW_WITHOUT_DCIN)
{
tick_printf("battery power is low without no dc or ac, should be set off\n");
sunxi_bmp_display("bat\\low_pwr.bmp");
__msdelay(3000);
if(!efex_test)
return -1;
else
return 0;
}
power_start = 0;
//power_startµÄº¬Òå
//0: ²»ÔÊÐí²å»ðÅ£Ö±½Ó¿ª»ú£¬±ØÐëͨ¹ýÅжϣºÂú×ãÒÔÏÂÌõ¼þ¿ÉÒÔÖ±½Ó¿ª»ú£º³¤°´power°´¼ü£¬Ç°´ÎÊÇϵͳ״̬£¬Èç¹ûµç³ØµçÁ¿¹ýµÍ£¬Ôò²»ÔÊÐí¿ª»ú
//1: ÈÎÒâ״̬Ï£¬ÔÊÐí²å»ðÅ£Ö±½Ó¿ª»ú£¬Í¬Ê±ÒªÇóµç³ØµçÁ¿×ã¹»¸ß
//2: ²»ÔÊÐí²å»ðÅ£Ö±½Ó¿ª»ú£¬±ØÐëͨ¹ýÅжϣºÂú×ãÒÔÏÂÌõ¼þ¿ÉÒÔÖ±½Ó¿ª»ú£º³¤°´power°´¼ü£¬Ç°´ÎÊÇϵͳ״̬£¬²»ÒªÇóµç³ØµçÁ¿
//3: ÈÎÒâ״̬Ï£¬ÔÊÐí²å»ðÅ£Ö±½Ó¿ª»ú£¬²»ÒªÇóµç³ØµçÁ¿
script_parser_fetch(PMU_SCRIPT_NAME, "power_start", &power_start, 1);
debug("power start cause = %d\n", power_start);
if(power_start == 3)
{
return 0;
}
if(power_status == BATTERY_RATIO_TOO_LOW_WITH_DCIN_VOL_TOO_LOW)//µÍµçÁ¿µÍµçѹ£¬´øÍⲿµçԴ״̬
{
if(!(power_start & 0x02)) //¸ù¾ÝÅäÖ㬵͵ç״̬ϲ»ÔÊÐí¿ª»ú, power_start==0 | power_start==1
{
tick_printf("battery low power and vol with dc or ac, should charge longer\n");
sunxi_bmp_display("bat\\bempty.bmp");
__msdelay(3000);
return -1;
}
//µÍµç³ØµÍµçÁ¿£¬´ËʱÅäÖÃΪ2£¬½øÈë¼ì²â£¬°´¼üÔò½øÈëϵͳ£¬²åÈë»ðÅ£Ôò´ý»ú
return 1;
}
if(power_status == BATTERY_RATIO_TOO_LOW_WITH_DCIN)//µÍµçÁ¿¸ßµçѹ£¬´øÍⲿµçԴ״̬
{
//Èç¹ûÅäÖÃΪ0£¬½øÈë¼ì²â£¬°´¼üÔòÏÔʾµÍµçͼ±êÈ»ºó¹Ø»ú£¬²åÈë»ðÅ£Ôò´ý»ú
//Èç¹ûÅäÖÃΪ1£¬½øÈë¼ì²â£¬°´¼üÔòÏÔʾµÍµçͼ±êÈ»ºó¹Ø»ú£¬²åÈë»ðÅ£Ôò´ý»ú
//Èç¹ûÅäÖÃΪ2£¬½øÈë¼ì²â£¬°´¼üÔò½øÈëϵͳ£¬²åÈë»ðÅ£Ôò´ý»ú
if(!(power_start & 0x02)) //¸ù¾ÝÅäÖ㬵͵ç״̬ϲ»ÔÊÐí¿ª»ú, power_start==0 | power_start==1
{
tick_printf("battery low power with dc or ac\n");
return 2;
}
//µÍµç³ØµÍµçÁ¿£¬´ËʱÅäÖÃΪ2£¬½øÈë¼ì²â£¬°´¼üÔò½øÈëϵͳ£¬²åÈë»ðÅ£Ôò´ý»ú
return 1;
}
//µç³ØµçѹµçÁ÷¶¼×ã¹»
if(power_start == 0x01) //Èç¹ûµÚ0bitµÄֵΪ1£¬Ôò½øÈëϵͳ
{
return 0;
}
return 1;
}
static int board_probe_battery_exist(void) //»ñÈ¡µç³Ø״̬
{
int counter;
int dc_exist, bat_exist;
counter = 4;
do
{
dc_exist = 0;
bat_exist = 0;
axp_power_get_dcin_battery_exist(&dc_exist, &bat_exist);
printf("bat_exist=%d\n", bat_exist);
if(bat_exist == -1)
{
printf("bat is unknown\n");
__msdelay(500);
}
else
{
break;
}
}
while(counter --);
return bat_exist;
}
static int board_probe_poweron_cause(void)
{
int status = -1;
status = axp_probe_startup_cause();
debug("startup status = %d\n", status);
#ifdef FORCE_BOOT_STANDBY
status = 1;
#endif
return status;
}
static int board_probe_bat_status(int standby_mode)
{
int bat_cal = 1;
int ret, chargemode = 0;
//µ±Ç°¿ÉÒÔÈ·¶¨ÊÇ»ðÅ£¿ª»ú£¬µ«ÊÇÊÇ·ñ¿ª»ú»¹²»È·¶¨£¬ÐèҪȷÈϵç³ØÊÇ·ñ´æÔÚ
//µ±µç³Ø²»´æÔÚ¼´¿ª»ú£¬µç³Ø´æÔÚÔò¹Ø»ú
//ÐÂÌí¼Ó£¬¸ù¾Ý»·¾³±äÁ¿£¬ÊÇÆô¶¯µ±Ç°µÄ´ý»ú£¬»òÕßandroid´ý»ú¹¦ÄÜ
ret = script_parser_fetch("charging_type", "charging_type", &chargemode, 1);
if((!ret) && chargemode)
{
gd->chargemode = 1;
return 0;
}
if(battery_charge_cartoon_init(0) < 0)
{
tick_printf("init charge cartoon fail\n");
return -1;
}
bat_cal = axp_probe_rest_battery_capacity();
printf("bat not inited\n");
if(battery_charge_cartoon_init(bat_cal/(100/(SUNXI_BAT_BMP_MAX-1))) < 0)
{
tick_printf("init charge cartoon fail\n");
return -1;
}
if((!bat_cal) && (standby_mode))
{
bat_cal = 100;
}
return bat_cal;
}
#ifndef CONFIG_NO_BOOT_STANDBY
static int board_standby_status(int source_bat_cal)
{
int bat_cal, this_bat_cal;
int i, j, status;
int one_delay;
int ret;
boot_standby_action = 0;
this_bat_cal = source_bat_cal;
tick_printf("base bat_cal = %d\n", this_bat_cal);
if(this_bat_cal > 95)
{
this_bat_cal = 100;
}
//Æô¶¯Öжϼì²â
usb_detect_for_charge(BOOT_USB_DETECT_DELAY_TIME + 200);
//Æô¶¯axp¼ì²â
power_limit_detect_enter();
status = 1;
goto __start_case_status__;
/******************************************************************
*
* standby ·µ»Øֵ˵Ã÷
*
* -1: ½øÈëstandbyʧ°Ü
* 1: ÆÕͨ°´¼ü»½ÐÑ
* 2: µçÔ´°´¼ü¶Ì°´»½ÐÑ
* 3: µçÔ´°´¼ü³¤°´»½ÐÑ
* 4: ÍⲿµçÔ´ÒƳý»½ÐÑ
* 5: µç³Ø³äµçÍê³É
* 6: ÔÚ»½ÐÑ״̬ÏÂÍⲿµçÔ´±»ÒƳý
* 7: ÔÚ»½ÐÑ״̬ϳäµçÍê³É
*
******************************************************************/
do
{
tick_printf("enter standby\n");
board_display_layer_close();
power_limit_detect_exit();
status = board_try_boot_standby();
tick_printf("exit standby by %d\n", status);
bat_cal = axp_probe_rest_battery_capacity();
tick_printf("current bat_cal = %d\n", bat_cal);
if(bat_cal > this_bat_cal)
{
this_bat_cal = bat_cal;
}
__start_case_status__:
tick_printf("status = %d\n", status);
switch(status)
{
case 2: //¶Ì°´power°´¼üµ¼Ö»½ÐÑ
//Æô¶¯Öжϼì²â
boot_standby_action = 0;
power_limit_detect_enter();
board_display_layer_open();
case 1:
//ÖØмÆË㶯»­ÑÓʱʱ¼ä
if(this_bat_cal == 100)
{
one_delay = 1000;
}
else
{
one_delay = 1000/(10 - (this_bat_cal/10));
}
//»æÖƶ¯»­
for(j=0;j<3;j++)
{
for(i=this_bat_cal/(100/(SUNXI_BAT_BMP_MAX-1));i<SUNXI_BAT_BMP_MAX;i++)
{
battery_charge_cartoon_rate(i);
if(boot_standby_action & 0x08) //´æÔÚÍⲿµçÔ´
{
boot_standby_action &= ~0x08;
j = 0;
}
else if(boot_standby_action & 0x02) //¶Ì°´
{
boot_standby_action &= ~2;
j = 0;
}
else if(boot_standby_action & 0x01) //³¤°´
{
battery_charge_cartoon_exit();
power_limit_detect_exit();
return 0;
}
else if(boot_standby_action & 0x10) //°ÎµôÍⲿµçÔ´£¬Ã»ÓÐÍⲿµçÔ´
{
status = 10;
boot_standby_action &= ~0x10;
goto __start_case_status__;
}
__msdelay(one_delay);
}
}
//Í£Ö¹¶¯»­£¬¹Ì¶¨ÏÔʾµ±Ç°µçÁ¿
battery_charge_cartoon_rate(this_bat_cal/(100/(SUNXI_BAT_BMP_MAX-1)));
for(j=0;j<4;j++)
{
if(boot_standby_action & 0x08) //´æÔÚÍⲿµçÔ´
{
boot_standby_action &= ~0x08;
j = 0;
}
else if(boot_standby_action & 0x10) //°ÎµôÍⲿµçÔ´£¬Ã»ÓÐÍⲿµçÔ´
{
status = 10;
boot_standby_action &= ~0x10;
goto __start_case_status__;
}
else if(boot_standby_action & 0x01) //³¤°´
{
battery_charge_cartoon_exit();
power_limit_detect_exit();
return 0;
}
__msdelay(250);
}
break;
case 3: //³¤°´µçÔ´°´¼üÖ®ºó£¬¹Ø±Õµç³Øͼ±ê£¬½øÈëϵͳ
battery_charge_cartoon_exit();
return 0;
case 4: //µ±ÒƳýÍⲿµçԴʱºò£¬ÖØÐÂÏÔʾµ±Ç°µç³Øͼ±êºó£¬3Ãëºó¹Ø»ú
case 5: //µ±µç³Ø³äµçÍê³ÉµÄʱºò£¬ÐèÒª¹Ø»ú
//Æô¶¯Öжϼì²â
boot_standby_action = 0;
power_limit_detect_enter();
board_display_layer_open();
battery_charge_cartoon_rate(this_bat_cal/(100/(SUNXI_BAT_BMP_MAX-1)));
case 6:
case 7:
if((status != 4) && (status != 5))
{
board_display_layer_open();
battery_charge_cartoon_rate(this_bat_cal/(100/(SUNXI_BAT_BMP_MAX-1)));
}
case 10:
battery_charge_cartoon_rate(this_bat_cal/(100/(SUNXI_BAT_BMP_MAX-1)));
__msdelay(500);
do
{
if(!(boot_standby_action & 0x04))
{
ret = battery_charge_cartoon_degrade(5);
}
else
{
status = 1;
battery_charge_cartoon_reset();
goto __start_case_status__;
}
}
while(!ret);
battery_charge_cartoon_exit();
power_limit_detect_exit();
return -1;
case 8: //standby¹ý³ÌÖмì²âµ½vbus´æÔڱ仯
{
usb_detect_for_charge(BOOT_USB_DETECT_DELAY_TIME + 200);
}
break;
case 9: //standby¹ý³ÌÖмì²âµ½vbusÒƳý£¬Í¬Ê±´æÔÚÆÕͨdc
{
// power_set_usbpc();
}
break;
default:
break;
}
}
while(1);
}
#endif
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters : standby_mode: 0, ÆÕͨģʽ£¬ÐèÒª¼ì²âµçԴ״̬
*
* 1, ²âÊÔģʽ£¬Ç¿ÖƽøÈëstandbyģʽ£¬²»ÂÛµçԴ״̬
*
* return :
*
* note : probe power and other condition
*
*
*
************************************************************************************************************
*/
void board_status_probe(int standby_mode)
{
int ret;
int start_condition = 0;
int bat_exist;
//Çå³ýpower°´¼ü
axp_probe_key();
//Æô¶¯Ìõ¼þÅжϣ¬µÚÒ»½×¶Î£¬¼ì²âµçÔ´µçѹ״̬
if(!standby_mode)
{
ret = board_probe_power_level(); //¸ºÊý£º¹Ø»ú£»0£º½øÈëϵͳ£»ÕýÊý£º¼ì²â
debug("stage1 resule %d\n", ret);
if(ret < 0)
{
do_shutdown(NULL, 0, 1, NULL);
}
else if(!ret)
{
return ;
}
else if(ret == 2) //°´¼üÔòÏÔʾµÍµçͼ±êÈ»ºó¹Ø»ú£¬²åÈë»ðÅ£Ôò´ý»ú
{
start_condition = 1;
}
//Æô¶¯Ìõ¼þÅжϣ¬µÚ¶þ½×¶Î£¬¼ì²â¿ª»úÔ­Òò
ret = board_probe_poweron_cause(); //¸ºÊý£¬0£º½øÈëϵͳ£»ÕýÊý£º´ý»ú»òÕßÖ±½Ó¹Ø»ú
debug("stage2 resule %d\n", ret);
if(ret <= 0)
{
if(!start_condition)
{
return ;
}
else
{
tick_printf("battery low power with dc or ac, should charge longer\n");
sunxi_bmp_display("bat\\bempty.bmp");
__msdelay(3000);
do_shutdown(NULL, 0, 1, NULL);
}
}
else if(ret == AXP_VBUS_DCIN_NOT_EXIST) //µ±Ç°Ò»´ÎΪboot standby״̬£¬µ«ÊÇÆô¶¯Ê±¼ì²éÎÞÍⲿµçÔ´£¬Ö±½Ó¹Ø»ú
{
do_shutdown(NULL, 0, 1, NULL);
}
}
#ifdef FORCE_BOOT_STANDBY
bat_exist = 1;
#else
if(standby_mode)
{
bat_exist = 1;
}
else
{
bat_exist = board_probe_battery_exist();
if(bat_exist <= 0)
{
tick_printf("no battery exist\n");
return;
}
}
#endif
//Æô¶¯Ìõ¼þÅжϣ¬µÚÈý½×¶Î£¬¼ì²âµç³Ø´æÔÚ
//¸ºÊý£º¹Ø»ú£»0£º½øÈëϵͳ£»ÕýÊý£º´ý»ú
ret = board_probe_bat_status(standby_mode);
debug("stage3 resule %d\n", ret);
if(ret < 0)
{
do_shutdown(NULL, 0, 1, NULL);
}
else if(!ret)
{
return ;
}
#ifndef CONFIG_NO_BOOT_STANDBY
//Æô¶¯Ìõ¼þÅжϣ¬µÚËĽ׶Σ¬½øÈëboot´ý»ú
//¸ºÊý£º¹Ø»ú£¬ÆäËü£º½øÈëϵͳ
ret = board_standby_status(ret);
debug("stage4 resule %d\n", ret);
if(ret < 0)
{
do_shutdown(NULL, 0, 1, NULL);
}
#endif
return ;
}