504 lines
12 KiB
C
Executable File
504 lines
12 KiB
C
Executable File
/*
|
||
* (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 ;
|
||
}
|
||
|
||
|