1706 lines
42 KiB
C
Executable File
1706 lines
42 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 <spare_head.h>
|
||
#include <axp_power.h>
|
||
#include <android_misc.h>
|
||
#include <sunxi_mbr.h>
|
||
#include <boot_type.h>
|
||
#include <sys_partition.h>
|
||
#include <sys_config.h>
|
||
#include <fastboot.h>
|
||
#include <pmu.h>
|
||
#include <asm/arch/timer.h>
|
||
#include <asm/arch/key.h>
|
||
#include <asm/arch/dma.h>
|
||
#include <sunxi_board.h>
|
||
#include <serial.h>
|
||
#include <asm/arch/usb.h>
|
||
#if defined(CONFIG_SUNXI_I2C)
|
||
#include <i2c.h>
|
||
#elif defined(CONFIG_SUNXI_P2WI)
|
||
#include <p2wi.h>
|
||
#elif defined(CONFIG_SUNXI_RSB)
|
||
#include <rsb.h>
|
||
#endif
|
||
#if defined(CONFIG_SUNXI_RTC)
|
||
#include <rtc.h>
|
||
#endif
|
||
|
||
DECLARE_GLOBAL_DATA_PTR;
|
||
|
||
#define PARTITION_SETS_MAX_SIZE 1024
|
||
#define PARTITION_NAME_MAX_SIZE 16
|
||
#define ROOT_PART_NAME_MAX_SIZE (PARTITION_NAME_MAX_SIZE + 5)
|
||
|
||
int loglel_change_flag __attribute__((section(".data"))) = 0;
|
||
extern int update_user_data(void);
|
||
extern void jump_to(unsigned int entey_addr);
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
void sunxi_flush_allcaches(void)
|
||
{
|
||
icache_disable();
|
||
|
||
flush_dcache_all();
|
||
dcache_disable();
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int __mmc_exit(void)
|
||
{
|
||
return 0;
|
||
}
|
||
int mmc_exit(void)
|
||
__attribute__((weak, alias("__mmc_exit")));
|
||
|
||
void sunxi_board_close_source(void)
|
||
{
|
||
// axp_set_vbus_limit_dc();
|
||
mmc_exit();
|
||
timer_exit();
|
||
|
||
sunxi_key_exit();
|
||
#ifdef CONFIG_SUN6I
|
||
p2wi_exit();
|
||
#endif
|
||
sunxi_flash_exit(1); //ǿ<>ƹر<C6B9>FLASH
|
||
sunxi_sprite_exit(1);
|
||
#ifndef CONFIG_BOOT_TONE
|
||
sunxi_dma_exit();
|
||
#endif
|
||
disable_interrupts();
|
||
interrupt_exit();
|
||
|
||
return ;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_board_restart(int next_mode)
|
||
{
|
||
if(!next_mode)
|
||
{
|
||
next_mode = PMU_PRE_SYS_MODE;
|
||
}
|
||
printf("set next mode %d\n", next_mode);
|
||
axp_set_next_poweron_status(next_mode);
|
||
board_display_set_exit_mode(0);
|
||
#ifdef CONFIG_SUNXI_DISPLAY
|
||
drv_disp_exit();
|
||
#endif
|
||
sunxi_board_close_source();
|
||
reset_cpu(0);
|
||
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_board_shutdown(void)
|
||
{
|
||
#if defined(CONFIG_SUNXI_RTC)
|
||
printf("rtc disable\n");
|
||
rtc_disable();
|
||
#endif
|
||
printf("set next system normal\n");
|
||
axp_set_next_poweron_status(0x0);
|
||
|
||
board_display_set_exit_mode(0);
|
||
#ifdef CONFIG_SUNXI_DISPLAY
|
||
drv_disp_exit();
|
||
#endif
|
||
sunxi_flash_exit(1); //ǿ<>ƹر<C6B9>FLASH
|
||
sunxi_sprite_exit(1);
|
||
disable_interrupts();
|
||
interrupt_exit();
|
||
|
||
tick_printf("power off\n");
|
||
axp_set_hardware_poweroff_vol();
|
||
axp_set_power_off();
|
||
#if defined(CONFIG_ARCH_SUN8IW7P1)
|
||
power_off();
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_board_run_fel(void)
|
||
{
|
||
#if defined(CONFIG_SUN6I) || defined(CONFIG_ARCH_SUN8IW3P1)|| defined(CONFIG_ARCH_SUN8IW5P1) || defined(CONFIG_ARCH_SUN7I)|| defined(CONFIG_ARCH_SUN8IW8P1)
|
||
*((volatile unsigned int *)(SUNXI_RUN_EFEX_ADDR)) = SUNXI_RUN_EFEX_FLAG;
|
||
#elif defined(CONFIG_ARCH_SUN9IW1P1) || defined(CONFIG_ARCH_SUN8IW7P1) || defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW9P1)
|
||
sunxi_set_fel_flag();
|
||
#endif
|
||
printf("set next system status\n");
|
||
|
||
axp_set_next_poweron_status(PMU_PRE_SYS_MODE);
|
||
|
||
board_display_set_exit_mode(0);
|
||
#ifdef CONFIG_SUNXI_DISPLAY
|
||
drv_disp_exit();
|
||
#endif
|
||
printf("sunxi_board_close_source\n");
|
||
sunxi_board_close_source();
|
||
|
||
sunxi_flush_allcaches();
|
||
#if defined(CONFIG_ARCH_SUN5I)
|
||
printf("jump to fel_base\n");
|
||
jump_to(FEL_BASE);
|
||
#else
|
||
printf("reset cpu\n");
|
||
|
||
reset_cpu(0);
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_board_run_fel_eraly(void)
|
||
{
|
||
#if defined(CONFIG_SUN6I) || defined(CONFIG_ARCH_SUN8IW3P1) || defined(CONFIG_ARCH_SUN8IW5P1)|| defined(CONFIG_ARCH_SUN7I)||defined(CONFIG_ARCH_SUN8IW8P1)
|
||
*((volatile unsigned int *)(SUNXI_RUN_EFEX_ADDR)) = SUNXI_RUN_EFEX_FLAG;
|
||
#elif defined(CONFIG_ARCH_SUN9IW1P1) || defined(CONFIG_ARCH_SUN8IW7P1) || defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW9P1)
|
||
sunxi_set_fel_flag();
|
||
#endif
|
||
printf("set next system status\n");
|
||
axp_set_next_poweron_status(PMU_PRE_SYS_MODE);
|
||
timer_exit();
|
||
sunxi_key_exit();
|
||
#ifdef CONFIG_SUN6I
|
||
p2wi_exit();
|
||
#endif
|
||
sunxi_dma_exit();
|
||
#if defined(CONFIG_ARCH_SUN5I)
|
||
printf("jump to fel_base\n");
|
||
jump_to(FEL_BASE);
|
||
#else
|
||
printf("reset cpu\n");
|
||
//#if defined(CONFIG_ARCH_SUN9IW1P1)
|
||
// *( volatile unsigned int *)(0x008000e0) = 0x16aa0000;
|
||
//#endif
|
||
reset_cpu(0);
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
void sunxi_update_subsequent_processing(int next_work)
|
||
{
|
||
printf("next work %d\n", next_work);
|
||
switch(next_work)
|
||
{
|
||
case SUNXI_UPDATE_NEXT_ACTION_REBOOT: //<2F><><EFBFBD><EFBFBD>
|
||
case SUNXI_UPDATA_NEXT_ACTION_SPRITE_TEST:
|
||
printf("SUNXI_UPDATE_NEXT_ACTION_REBOOT\n");
|
||
//do_reset(NULL, 0, 0, NULL);
|
||
sunxi_board_restart(0);
|
||
|
||
break;
|
||
case SUNXI_UPDATE_NEXT_ACTION_SHUTDOWN: //<2F>ػ<EFBFBD>
|
||
printf("SUNXI_UPDATE_NEXT_ACTION_SHUTDOWN\n");
|
||
//do_shutdown(NULL, 0, 0, NULL);
|
||
sunxi_board_shutdown();
|
||
|
||
break;
|
||
case SUNXI_UPDATE_NEXT_ACTION_REUPDATE:
|
||
printf("SUNXI_UPDATE_NEXT_ACTION_REUPDATE\n");
|
||
sunxi_board_run_fel(); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
break;
|
||
case SUNXI_UPDATE_NEXT_ACTION_BOOT:
|
||
case SUNXI_UPDATE_NEXT_ACTION_NORMAL:
|
||
default:
|
||
printf("SUNXI_UPDATE_NEXT_ACTION_NULL\n");
|
||
break;
|
||
}
|
||
|
||
return ;
|
||
}
|
||
|
||
#define FIX_UDISK_SIZE
|
||
|
||
void fastboot_partition_init(void)
|
||
{
|
||
fastboot_ptentry fb_part;
|
||
int index, part_total;
|
||
char partition_sets[PARTITION_SETS_MAX_SIZE];
|
||
char part_name[PARTITION_NAME_MAX_SIZE];
|
||
char root_part_name[ROOT_PART_NAME_MAX_SIZE];
|
||
char *partition_index = partition_sets;
|
||
int offset = 0;
|
||
int temp_offset = 0;
|
||
int storage_type = get_boot_storage_type();
|
||
char* root_partition;
|
||
|
||
#ifdef FIX_UDISK_SIZE
|
||
int flash_sector;
|
||
flash_sector = sunxi_flash_size();
|
||
printf("the flash size is %d MB\n", flash_sector/2/1024);
|
||
#endif
|
||
|
||
root_partition = getenv("root_partition");
|
||
if(root_partition)
|
||
printf("root_partition is %s\n",root_partition);
|
||
|
||
printf("--------fastboot partitions--------\n");
|
||
part_total = sunxi_partition_get_total_num();
|
||
if((part_total <= 0) || (part_total > SUNXI_MBR_MAX_PART_COUNT))
|
||
{
|
||
printf("mbr not exist\n");
|
||
|
||
return ;
|
||
}
|
||
printf("-total partitions:%d-\n", part_total);
|
||
printf("%-12s %-12s %-12s\n", "-name-", "-start-", "-size-");
|
||
|
||
memset(partition_sets, 0, PARTITION_SETS_MAX_SIZE);
|
||
memset(root_part_name, 0, ROOT_PART_NAME_MAX_SIZE);
|
||
|
||
for(index = 0; index < part_total && index < SUNXI_MBR_MAX_PART_COUNT; index++)
|
||
{
|
||
sunxi_partition_get_name(index, &fb_part.name[0]);
|
||
fb_part.start = sunxi_partition_get_offset(index) * 512;
|
||
fb_part.length = sunxi_partition_get_size(index) * 512;
|
||
fb_part.flags = 0;
|
||
#ifdef FIX_UDISK_SIZE
|
||
if (strncmp(&fb_part.name[0], "UDISK" ,5) == 0) {
|
||
sunxi_partition_set_size_byname("UDISK", flash_sector - fb_part.start/512);
|
||
fb_part.length = sunxi_partition_get_size(index) * 512;
|
||
}
|
||
#endif
|
||
|
||
printf("%-12s: %-12x %-12x\n", fb_part.name, fb_part.start, fb_part.length);
|
||
|
||
memset(part_name, 0, PARTITION_NAME_MAX_SIZE);
|
||
if(storage_type == STORAGE_NAND)
|
||
{
|
||
sprintf(part_name, "nand%c", 'a' + index);
|
||
}
|
||
else if (storage_type == STORAGE_NOR)
|
||
{
|
||
sprintf(part_name, "mtdblock%d", index + 1);
|
||
}
|
||
else
|
||
{
|
||
if(index == 0)
|
||
{
|
||
strcpy(part_name, "mmcblk0p2");
|
||
}
|
||
else if( (index+1)==part_total)
|
||
{
|
||
strcpy(part_name, "mmcblk0p1");
|
||
}
|
||
else
|
||
{
|
||
sprintf(part_name, "mmcblk0p%d", index + 4);
|
||
}
|
||
}
|
||
|
||
if(root_partition != NULL && strcmp(root_partition, fb_part.name) == 0)
|
||
sprintf(root_part_name, "/dev/%s", part_name);
|
||
|
||
temp_offset = strlen(fb_part.name) + strlen(part_name) + 2;
|
||
if(temp_offset >= PARTITION_SETS_MAX_SIZE)
|
||
{
|
||
printf("partition_sets is too long, please reduces partition name\n");
|
||
break;
|
||
}
|
||
fastboot_flash_add_ptn(&fb_part);
|
||
sprintf(partition_index, "%s@%s:", fb_part.name, part_name);
|
||
offset += temp_offset;
|
||
partition_index = partition_sets + offset;
|
||
}
|
||
|
||
partition_sets[offset-1] = '\0';
|
||
partition_sets[PARTITION_SETS_MAX_SIZE - 1] = '\0';
|
||
printf("-----------------------------------\n");
|
||
|
||
if(*root_part_name != 0)
|
||
{
|
||
printf("set root to %s\n", root_part_name);
|
||
if(storage_type == STORAGE_NAND)
|
||
setenv("nand_root", root_part_name);
|
||
else if(storage_type == STORAGE_NOR)
|
||
setenv("nor_root", root_part_name);
|
||
else
|
||
setenv("mmc_root", root_part_name);
|
||
}
|
||
|
||
setenv("partitions", partition_sets);
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : <20><>Ŀ<EFBFBD><C4BF><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>dest_buf(<28><>ʽ<EFBFBD><CABD><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"AAA BBB C DD EEE"<22><><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD><EFBFBD><EFBFBD>tab
|
||
* <20>е<EFBFBD>goal<61><6C><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻<EFBFBD><E6BBBB>replace
|
||
* <20><>
|
||
* sunxi_str_replace("abc def gh", "def", "replace")
|
||
* ִ<>еĽ<D0B5><C4BD><EFBFBD><EFBFBD><EFBFBD> "abc def gh"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "abc replace gh"
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻
|
||
* <20><><EFBFBD>뱣֤<EBB1A3>ռ<EFBFBD><D5BC>㹻
|
||
************************************************************************************************************
|
||
*/
|
||
static int sunxi_str_replace(char *dest_buf, char *goal, char *replace)
|
||
{
|
||
char tmp[128];
|
||
char tmp_str[16];
|
||
int goal_len, rep_len, dest_len;
|
||
int i, j, k;
|
||
|
||
if( (goal == NULL) || (dest_buf == NULL))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
memset(tmp, 0, 128);
|
||
strcpy(tmp, dest_buf);
|
||
|
||
goal_len = strlen(goal);
|
||
dest_len = strlen(dest_buf);
|
||
|
||
if(replace != NULL)
|
||
{
|
||
rep_len = strlen(replace);
|
||
}
|
||
else
|
||
{
|
||
rep_len = 0;
|
||
}
|
||
j = 0;
|
||
for(i=0;tmp[i];)
|
||
{
|
||
//<2F>ҳ<EFBFBD><D2B3>ո<EFBFBD><D5B8>ַ<EFBFBD>
|
||
k = 0;
|
||
while(((tmp[i] != ' ') && (tmp[i] != 0) )|| (tmp[i+1] == ' '))
|
||
{
|
||
tmp_str[k++] = tmp[i];
|
||
i ++;
|
||
if(i >= dest_len)
|
||
break;
|
||
}
|
||
i ++;
|
||
//<2F><>ʼ<EFBFBD>ҳ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||
tmp_str[k] = 0;
|
||
if(!strcmp(tmp_str, goal))
|
||
{
|
||
if(rep_len)
|
||
{
|
||
strcpy(dest_buf + j, replace);
|
||
if(tmp[j + goal_len])
|
||
{
|
||
memcpy(dest_buf + j + rep_len, tmp + j + goal_len, dest_len - j - goal_len);
|
||
dest_buf[dest_len - goal_len + rep_len] = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(tmp[j + goal_len])
|
||
{
|
||
memcpy(dest_buf + j, tmp + j + goal_len, dest_len - j - goal_len);
|
||
dest_buf[dest_len - goal_len + rep_len] = 0;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
j = i;
|
||
}
|
||
|
||
return 0;
|
||
|
||
}
|
||
|
||
#ifndef CONFIG_SUNXI_SPINOR_PLATFORM
|
||
#define ANDROID_NULL_MODE 0
|
||
#define ANDROID_FASTBOOT_MODE 1
|
||
#define ANDROID_RECOVERY_MODE 2
|
||
#define USER_SELECT_MODE 3
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
static int detect_other_boot_mode(void)
|
||
{
|
||
int ret1, ret2;
|
||
int key_high, key_low;
|
||
int keyvalue;
|
||
int user_mode_used = 0;
|
||
keyvalue = gd->key_pressd_value;
|
||
printf("key %d\n", keyvalue);
|
||
script_parser_fetch("platform", "user_mode_used", &user_mode_used, 1);
|
||
if(user_mode_used)
|
||
{
|
||
if(keyvalue >0)
|
||
{
|
||
return USER_SELECT_MODE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret1 = script_parser_fetch("recovery_key", "key_max", &key_high, 1);
|
||
ret2 = script_parser_fetch("recovery_key", "key_min", &key_low, 1);
|
||
if((ret1) || (ret2))
|
||
{
|
||
printf("cant find rcvy value\n");
|
||
}
|
||
else
|
||
{
|
||
printf("recovery key high %d, low %d\n", key_high, key_low);
|
||
if((keyvalue >= key_low) && (keyvalue <= key_high))
|
||
{
|
||
printf("key found, android recovery\n");
|
||
|
||
return ANDROID_RECOVERY_MODE;
|
||
}
|
||
}
|
||
ret1 = script_parser_fetch("fastboot_key", "key_max", &key_high, 1);
|
||
ret2 = script_parser_fetch("fastboot_key", "key_min", &key_low, 1);
|
||
if((ret1) || (ret2))
|
||
{
|
||
printf("cant find fstbt value\n");
|
||
}
|
||
else
|
||
{
|
||
printf("fastboot key high %d, low %d\n", key_high, key_low);
|
||
if((keyvalue >= key_low) && (keyvalue <= key_high))
|
||
{
|
||
printf("key found, android fastboot\n");
|
||
return ANDROID_FASTBOOT_MODE;
|
||
}
|
||
}
|
||
}
|
||
return ANDROID_NULL_MODE;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : check_debug_mode
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : guoyingyang@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
|
||
static void check_debug_mode(void)
|
||
{
|
||
//if enter debug mode,set loglevel = 8
|
||
char change_env_data[32];
|
||
char *env_concole = "ttyS";
|
||
int baud = 115200;
|
||
int port_id = 0;
|
||
|
||
if(!loglel_change_flag)
|
||
return ;
|
||
memset(change_env_data,0,32);
|
||
sprintf(change_env_data, "%d",8);
|
||
setenv("loglevel",change_env_data);
|
||
if(script_parser_fetch("force_uart_para","force_uart_port",&port_id,sizeof(int)/4))
|
||
{
|
||
printf("card0_print_para port_id fetch error\n");
|
||
return ;
|
||
}
|
||
memset(change_env_data,0,32);
|
||
strcat(change_env_data,"ttyS");
|
||
sprintf(change_env_data,"%s%d%s%d",env_concole,port_id,",",baud);
|
||
setenv("console",change_env_data);
|
||
|
||
return ;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int check_android_misc(void)
|
||
{
|
||
int mode;
|
||
int pmu_value;
|
||
u32 misc_offset = 0;
|
||
char misc_args[2048];
|
||
char misc_fill[2048];
|
||
char boot_commond[128];
|
||
static struct bootloader_message *misc_message;
|
||
|
||
if(uboot_spare_head.boot_data.work_mode != WORK_MODE_BOOT)
|
||
{
|
||
return 0;
|
||
}
|
||
if(gd->force_shell)
|
||
{
|
||
char delaytime[8];
|
||
|
||
sprintf(delaytime, "%d", 3);
|
||
setenv("bootdelay", delaytime);
|
||
}
|
||
//if enter debug mode,set loglevel = 8
|
||
check_debug_mode();
|
||
|
||
memset(boot_commond, 0x0, 128);
|
||
strcpy(boot_commond, getenv("bootcmd"));
|
||
printf("base bootcmd=%s\n", boot_commond);
|
||
//<2F>жϴ洢<CFB4><E6B4A2><EFBFBD><EFBFBD>
|
||
if((uboot_spare_head.boot_data.storage_type == 1) || (uboot_spare_head.boot_data.storage_type == 2))
|
||
{
|
||
sunxi_str_replace(boot_commond, "setargs_nand", "setargs_mmc");
|
||
printf("bootcmd set setargs_mmc\n");
|
||
}
|
||
else
|
||
{
|
||
printf("bootcmd set setargs_nand\n");
|
||
}
|
||
misc_message = (struct bootloader_message *)misc_args;
|
||
memset(misc_args, 0x0, 2048);
|
||
memset(misc_fill, 0xff, 2048);
|
||
mode = detect_other_boot_mode();
|
||
if(mode == ANDROID_NULL_MODE)
|
||
{
|
||
pmu_value = axp_probe_pre_sys_mode();
|
||
if(pmu_value == PMU_PRE_FASTBOOT_MODE)
|
||
{
|
||
puts("PMU : ready to enter fastboot mode\n");
|
||
strcpy(misc_message->command, "bootloader");
|
||
}
|
||
else if(pmu_value == PMU_PRE_RECOVERY_MODE)
|
||
{
|
||
puts("PMU : ready to enter recovery mode\n");
|
||
strcpy(misc_message->command, "boot-recovery");
|
||
}
|
||
else
|
||
{
|
||
misc_offset = sunxi_partition_get_offset_byname("misc");
|
||
debug("misc_offset = %x\n",misc_offset);
|
||
if(!misc_offset)
|
||
{
|
||
printf("no misc partition is found\n");
|
||
}
|
||
else
|
||
{
|
||
printf("misc partition found\n");
|
||
sunxi_flash_read(misc_offset, 2048/512, misc_args); //read misc partition data
|
||
}
|
||
}
|
||
}
|
||
else if(mode == ANDROID_RECOVERY_MODE)
|
||
{
|
||
strcpy(misc_message->command, "boot-recovery");
|
||
}
|
||
else if( mode == ANDROID_FASTBOOT_MODE)
|
||
{
|
||
strcpy(misc_message->command, "bootloader");
|
||
}
|
||
//<2F><><EFBFBD><EFBFBD>ͳһ<CDB3>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
|
||
if(!loglel_change_flag) //add by young,if you want to enter debug_mode ,so do enter boot_normal
|
||
{
|
||
if(!strcmp(misc_message->command, "efex"))
|
||
{
|
||
/* there is a recovery command */
|
||
puts("find efex cmd\n");
|
||
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
|
||
sunxi_board_run_fel();
|
||
|
||
return 0;
|
||
}
|
||
|
||
if(!strcmp(misc_message->command, "boot-resignature"))
|
||
{
|
||
puts("find boot-resignature cmd\n");
|
||
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
|
||
sunxi_oem_op_lock(SUNXI_LOCKING, NULL, 1);
|
||
}
|
||
else if(!strcmp(misc_message->command, "boot-recovery"))
|
||
{
|
||
if(!strcmp(misc_message->recovery, "sysrecovery"))
|
||
{
|
||
puts("recovery detected, will sprite recovery\n");
|
||
strncpy(boot_commond, "sprite_recovery", sizeof("sprite_recovery"));
|
||
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
|
||
}
|
||
else
|
||
{
|
||
puts("Recovery detected, will boot recovery\n");
|
||
sunxi_str_replace(boot_commond, "boot_normal", "boot_recovery");
|
||
}
|
||
/* android recovery will clean the misc */
|
||
}
|
||
else if(!strcmp(misc_message->command, "bootloader"))
|
||
{
|
||
puts("Fastboot detected, will boot fastboot\n");
|
||
sunxi_str_replace(boot_commond, "boot_normal", "boot_fastboot");
|
||
if(misc_offset)
|
||
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
|
||
}
|
||
else if(!strcmp(misc_message->command, "usb-recovery"))
|
||
{
|
||
puts("Recovery detected, will usb recovery\n");
|
||
sunxi_str_replace(boot_commond, "boot_normal", "boot_recovery");
|
||
}
|
||
}
|
||
if(!strcmp(misc_message->command ,"debug_mode"))
|
||
{
|
||
puts("debug_mode detected ,will enter debug_mode");
|
||
if(!change_to_debug_mode())
|
||
{
|
||
check_debug_mode();
|
||
}
|
||
sunxi_flash_write(misc_offset,2048/512,misc_fill);
|
||
}
|
||
setenv("bootcmd", boot_commond);
|
||
|
||
printf("to be run cmd=%s\n", boot_commond);
|
||
return 0;
|
||
|
||
}
|
||
#else
|
||
int check_android_misc(void)
|
||
{
|
||
|
||
u32 misc_offset = 0;
|
||
char misc_args[2048];
|
||
static struct bootloader_message *misc_message;
|
||
|
||
char boot_commond[128];
|
||
|
||
misc_message = (struct bootloader_message *)misc_args;
|
||
memset(misc_args, 0x0, 2048);
|
||
|
||
memset(boot_commond, 0x0, 128);
|
||
strcpy(boot_commond, getenv("bootcmd"));
|
||
printf("base bootcmd=%s\n", boot_commond);
|
||
/* read misc partition */
|
||
misc_offset = sunxi_partition_get_offset_byname("misc");
|
||
debug("misc_offset = %x\n",misc_offset);
|
||
if(!misc_offset)
|
||
{
|
||
printf("no misc partition is found\n");
|
||
}
|
||
else
|
||
{
|
||
printf("misc partition found\n");
|
||
sunxi_flash_read(misc_offset, 2048/512, misc_args); //read misc partition data
|
||
}
|
||
/* check misc command */
|
||
if(!strcmp(misc_message->command, "boot-recovery"))
|
||
{
|
||
printf("Recovery detected, will boot recovery\n");
|
||
sunxi_str_replace(boot_commond, "boot_normal", "boot_recovery");
|
||
}
|
||
else if(!strcmp(misc_message->command, "efex"))
|
||
{
|
||
/* there is a recovery command */
|
||
printf("find efex cmd\n");
|
||
sunxi_board_run_fel();
|
||
|
||
return 0;
|
||
}
|
||
|
||
sunxi_str_replace(boot_commond, "setargs_nand", "setargs_nor");
|
||
printf("bootcmd set setargs_nor\n");
|
||
setenv("bootcmd", boot_commond);
|
||
|
||
printf("to be run cmd=%s\n", boot_commond);
|
||
return 0;
|
||
|
||
}
|
||
|
||
#endif
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int board_late_init(void)
|
||
{
|
||
fastboot_partition_init();
|
||
|
||
#ifdef CONFIG_ARCH_HOMELET
|
||
respond_physical_key_action();
|
||
#endif
|
||
check_android_misc();
|
||
#ifdef CONFIG_ARCH_HOMELET
|
||
update_user_data();
|
||
#endif
|
||
|
||
#ifdef CONFIG_USE_UBOOT_SERIALNO
|
||
extern int sunxi_set_serial_num(void);
|
||
sunxi_set_serial_num();
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
|
||
int check_uart_input(void)
|
||
{
|
||
int c = 0;
|
||
if(uboot_spare_head.boot_data.work_mode != WORK_MODE_BOOT)
|
||
{
|
||
return 0;
|
||
}
|
||
if(tstc())
|
||
{
|
||
c = getc();
|
||
printf("0x%x\n", c);
|
||
}
|
||
else
|
||
{
|
||
puts("no key input\n");
|
||
}
|
||
|
||
if(c == '2')
|
||
{
|
||
return -1;
|
||
}
|
||
else if(c == '3')
|
||
{
|
||
sunxi_key_init();
|
||
do_key_test(NULL, 0, 1, NULL);
|
||
}
|
||
else if(c == 's') //shell mode
|
||
{
|
||
gd->force_shell = 1;
|
||
gd->debug_mode = 1;
|
||
}
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
#define KEY_DELAY_MAX (8)
|
||
#define KEY_DELAY_EACH_TIME (40)
|
||
#define KEY_MAX_COUNT_GO_ON ((KEY_DELAY_MAX * 1000)/(KEY_DELAY_EACH_TIME))
|
||
int check_update_key(void)
|
||
{
|
||
int ret;
|
||
int fel_key_max;
|
||
int power_plug_count = 0;
|
||
int new_power_status = 0;
|
||
int old_power_status = 0;
|
||
int time_tick = 0 ;
|
||
int fel_key_mode = 0;
|
||
int user_mode_used = 0;
|
||
gd->key_pressd_value = 0;
|
||
if(uboot_spare_head.boot_data.work_mode != WORK_MODE_BOOT)
|
||
{
|
||
return 0;
|
||
}
|
||
old_power_status = axp_probe_power_source();
|
||
sunxi_key_init();
|
||
//detect user_mode exist
|
||
script_parser_fetch("platform", "user_mode_used", &user_mode_used, 1);
|
||
if(user_mode_used)
|
||
{
|
||
printf("user_mode found\n");
|
||
fel_key_mode = 2;
|
||
}
|
||
|
||
//detect fel_key exist
|
||
else
|
||
{
|
||
ret = script_parser_fetch("fel_key", "fel_key_max", &fel_key_max, 1);
|
||
if(ret)
|
||
{
|
||
printf("fel key old mode\n");
|
||
fel_key_mode = 1;
|
||
}
|
||
else
|
||
{
|
||
printf("fel key new mode\n");
|
||
}
|
||
}
|
||
printf("run key detect\n");
|
||
printf("fel_key_mode:%d\n",fel_key_mode);
|
||
|
||
sunxi_key_read();
|
||
__msdelay(10);
|
||
|
||
if(!fel_key_mode)
|
||
{
|
||
int key_value = -1;
|
||
int fel_key_max, fel_key_min;
|
||
time_tick = 0;
|
||
int i;
|
||
for(i=0; i<10; i++) {
|
||
key_value = sunxi_key_read();
|
||
if(key_value >= 0)
|
||
break;
|
||
__msdelay(10);
|
||
}
|
||
if(key_value < 0) //û<>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
{
|
||
printf("no key found\n");
|
||
return 0;
|
||
}
|
||
gd->key_pressd_value = key_value;
|
||
ret = script_parser_fetch("fel_key", "fel_key_max", &fel_key_max, 1);
|
||
if(ret)
|
||
{
|
||
printf("fel key max not found\n");
|
||
|
||
return 0;
|
||
}
|
||
|
||
ret = script_parser_fetch("fel_key", "fel_key_min", &fel_key_min, 1);
|
||
if(ret)
|
||
{
|
||
printf("fel key min not found\n");
|
||
|
||
return 0;
|
||
}
|
||
|
||
if((key_value <= fel_key_max) && (key_value >= fel_key_min))
|
||
{
|
||
printf("fel key detected\n");
|
||
|
||
return 1;
|
||
}
|
||
|
||
printf("fel key value %d is not in the range from %d to %d\n", key_value, fel_key_min, fel_key_max);
|
||
//old_usb_plug_status = usb_probe_vbus_type();
|
||
//add by guoyingyang
|
||
while(sunxi_key_read() > 0) //press key and not loosen
|
||
{
|
||
time_tick++;
|
||
new_power_status = axp_probe_power_source();
|
||
__msdelay(KEY_DELAY_EACH_TIME);
|
||
if(new_power_status != old_power_status)
|
||
{
|
||
power_plug_count++;
|
||
old_power_status = new_power_status;
|
||
}
|
||
if(power_plug_count == 3)
|
||
{
|
||
change_to_debug_mode();
|
||
break;
|
||
}
|
||
if(time_tick > KEY_MAX_COUNT_GO_ON)
|
||
{
|
||
printf("time out\n");
|
||
break;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
else if(fel_key_mode == 1)
|
||
{
|
||
int count;
|
||
int value_old, value_new, value_cnt;
|
||
int new_key, new_key_flag;
|
||
|
||
time_tick = 0;
|
||
count = 0;
|
||
value_cnt = 0;
|
||
new_key = 0;
|
||
new_key_flag = 0;
|
||
ret = sunxi_key_read(); //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
||
if(ret < 0) //û<>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
{
|
||
printf("no key found\n");
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
value_old = ret;
|
||
}
|
||
gd->key_pressd_value = ret;
|
||
while(1)
|
||
{
|
||
time_tick ++;
|
||
ret = axp_probe_key(); //<2F><>ȡpower<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
||
new_power_status = axp_probe_power_source(); //detect vbus status
|
||
printf("new_power_status = %d \n",new_power_status);
|
||
if(ret > 0) //<2F><><EFBFBD>POWER<45><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
{
|
||
count ++;
|
||
}
|
||
if(new_power_status != old_power_status)
|
||
{
|
||
debug("=======flag change========\n");
|
||
power_plug_count ++;
|
||
old_power_status = new_power_status;
|
||
}
|
||
__msdelay(KEY_DELAY_EACH_TIME);
|
||
ret = sunxi_key_read(); //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
||
if(ret < 0) //û<>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
{
|
||
printf("key not pressed anymore\n");
|
||
if(count == 1)
|
||
{
|
||
if(new_key >= 2)
|
||
{
|
||
printf("1\n");
|
||
printf("force to debug mode\n");
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
value_new = ret;
|
||
if(value_old == value_new)
|
||
{
|
||
value_cnt ++;
|
||
if(new_key_flag == 1)
|
||
{
|
||
new_key ++;
|
||
new_key_flag ++;
|
||
}
|
||
else if(!new_key_flag)
|
||
{
|
||
new_key_flag ++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
new_key_flag = 0;
|
||
value_old = value_new;
|
||
}
|
||
}
|
||
|
||
if(count == 3)
|
||
{
|
||
printf("you can unclench the key to update now\n");
|
||
return -1;
|
||
}
|
||
|
||
if((!count) && (power_plug_count == 3))
|
||
{
|
||
change_to_debug_mode();
|
||
return 0;
|
||
}
|
||
|
||
if((!count) && (time_tick >= KEY_MAX_COUNT_GO_ON))
|
||
{
|
||
printf("timeout, but no power key found\n");
|
||
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int user_key_value;
|
||
user_key_value = sunxi_key_read(); //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
||
if(user_key_value < 0) //û<>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
{
|
||
printf("no user_key found\n");
|
||
}
|
||
else
|
||
{
|
||
gd->key_pressd_value = user_key_value;
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
#ifndef CONFIG_SUNXI_SPINOR_PLATFORM
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : <20><><EFBFBD>ã<EFBFBD><C3A3><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>õ<EFBFBD>gpio
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int gpio_control(void)
|
||
{
|
||
int ret;
|
||
int used;
|
||
|
||
ret = script_parser_fetch("boot_init_gpio", "used", &used, sizeof(int) / 4);
|
||
if (!ret && used) {
|
||
puts("user_gpio config\n");
|
||
gpio_request_ex("boot_init_gpio", NULL);
|
||
puts("user_gpio ok\n");
|
||
return 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : usb-recovery д<><D0B4>misc<73><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : yanjianbo@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int write_usb_recovery_to_misc(void)
|
||
{
|
||
u32 misc_offset = 0;
|
||
char misc_args[2048];
|
||
static struct bootloader_message *misc_message;
|
||
int ret;
|
||
|
||
memset(misc_args, 0x0, 2048);
|
||
misc_message = (struct bootloader_message *)misc_args;
|
||
|
||
misc_offset = sunxi_partition_get_offset_byname("misc");
|
||
if(!misc_offset)
|
||
{
|
||
printf("no misc partition\n");
|
||
return 0;
|
||
}
|
||
ret = sunxi_flash_read(misc_offset, 2048/512, misc_args);
|
||
if (!ret)
|
||
{
|
||
printf("error: read misc partition\n");
|
||
return 0;
|
||
}
|
||
strcpy(misc_message->command, "usb-recovery");
|
||
sunxi_flash_write(misc_offset, 2048/512, misc_args);
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : һ<><D2BB><EFBFBD>ָ<EFBFBD><D6B8>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : yanjianbo@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
#define ONEKEY_USB_RECOVERY_MODE (0x01)
|
||
#define ONEKEY_SPRITE_RECOVERY_MODE (0x02)
|
||
#define USB_RECOVERY_KEY_VALUE (0x81)
|
||
#define SPRITE_RECOVERY_KEY_VALUE (0X82)
|
||
|
||
int check_physical_key_early(void)
|
||
{
|
||
user_gpio_set_t gpio_recovery;
|
||
__u32 gpio_hd;
|
||
int ret;
|
||
int gpio_value = 0;
|
||
int used = 0;
|
||
int mode = 0;
|
||
|
||
if(uboot_spare_head.boot_data.work_mode != WORK_MODE_BOOT)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
ret = script_parser_fetch("recovery_para", "used", (int *)&used, sizeof(int) / 4);
|
||
if (ret || !used)
|
||
{
|
||
printf("[recovery] no use\n");
|
||
return 0;
|
||
}
|
||
ret = script_parser_fetch("recovery_para", "recovery_key", (int *)&gpio_recovery, sizeof(user_gpio_set_t) / 4);
|
||
if (!ret)
|
||
{
|
||
gpio_recovery.mul_sel = 0; //ǿ<><C7BF><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD>
|
||
gpio_hd = gpio_request(&gpio_recovery, 1);
|
||
if (gpio_hd)
|
||
{
|
||
int time;
|
||
gpio_value = 0;
|
||
for(time = 0; time < 4; time++)
|
||
{
|
||
gpio_value += gpio_read_one_pin_value(gpio_hd, 0);
|
||
__msdelay(5);
|
||
}
|
||
if (!gpio_value)
|
||
{
|
||
printf("[box recovery] find the key\n");
|
||
script_parser_fetch("recovery_para", "mode", (int *)&mode, sizeof(int) / 4);
|
||
if (mode == ONEKEY_USB_RECOVERY_MODE)
|
||
{
|
||
gd->key_pressd_value = USB_RECOVERY_KEY_VALUE;
|
||
}
|
||
else if (mode == ONEKEY_SPRITE_RECOVERY_MODE)
|
||
{
|
||
gd->key_pressd_value = SPRITE_RECOVERY_KEY_VALUE;
|
||
uboot_spare_head.boot_data.work_mode = WORK_MODE_SPRITE_RECOVERY;
|
||
}
|
||
else
|
||
{
|
||
printf("[recovery] no option for one key recovery's mode (%d)\n", mode);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : yanjianbo@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
void respond_physical_key_action(void)
|
||
{
|
||
int key_value;
|
||
key_value = gd->key_pressd_value;
|
||
|
||
if (key_value == USB_RECOVERY_KEY_VALUE)
|
||
{
|
||
printf("[box recovery] set to one key usb recovery\n");
|
||
write_usb_recovery_to_misc();
|
||
}
|
||
else if (key_value == SPRITE_RECOVERY_KEY_VALUE)
|
||
{
|
||
printf("[box recovery] set to one key sprite recovery\n");
|
||
//setenv("bootcmd", "sprite_recovery");
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_ARCH_SUN9IW1P1
|
||
#define UART_GATE_CTRL (0x06000400 + 0x194)
|
||
#else
|
||
#define UART_GATE_CTRL (0x01c20000 + 0x6c)
|
||
#endif
|
||
|
||
#if !defined(CONFIG_ARCH_SUN7I) || !defined(CONFIG_ARCH_SUN5I)
|
||
#ifdef CONFIG_ARCH_SUN9IW1P1
|
||
#define UART_RST_CTRL (0x06000400 + 0x1B4)
|
||
#else
|
||
#define UART_RST_CTRL (0x01c20000 + 0x02D8)
|
||
#endif
|
||
#endif
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : modify_uboot_uart
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : guoyingyang@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int modify_uboot_uart(void)
|
||
{
|
||
script_gpio_set_t fetch_cfg_gpio[2];
|
||
u32 reg = 0;
|
||
int uart_port_id = 0;
|
||
//disable uart0
|
||
if(script_parser_fetch("uart_para","uart_debug_rx",(int *)(&fetch_cfg_gpio[0]),sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_rx \n");
|
||
return -1;
|
||
}
|
||
fetch_cfg_gpio[0].mul_sel = 0;
|
||
if(script_parser_patch("uart_para","uart_debug_rx",(void*)&fetch_cfg_gpio[0],sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error : can't patch uart_debug_rx\n");
|
||
return -1;
|
||
}
|
||
//config uart_tx
|
||
if(script_parser_fetch("uart_para","uart_debug_tx",(int *)(&fetch_cfg_gpio[1]),sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_tx \n");
|
||
return -1;
|
||
}
|
||
fetch_cfg_gpio[1].mul_sel = 0;
|
||
if(script_parser_patch("uart_para","uart_debug_tx",(void*)&fetch_cfg_gpio[1],sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error : can't patch uart_debug_tx\n");
|
||
return -1;
|
||
}
|
||
//disable uart0
|
||
gpio_request_simple("uart_para",NULL);
|
||
//port_id
|
||
if(script_parser_fetch("force_uart_para","force_uart_port",(int *)(&uart_port_id),sizeof(int)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_tx \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_patch("uart_para","uart_debug_port",(int *)(&uart_port_id),sizeof(int)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_tx \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_fetch("force_uart_para","force_uart_tx",(int *)(&fetch_cfg_gpio[0]),sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_tx \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_patch("uart_para","uart_debug_tx",(void*)&fetch_cfg_gpio[0],sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error : can't patch uart_debug_tx\n");
|
||
return -1;
|
||
}
|
||
if(script_parser_fetch("force_uart_para","force_uart_rx",(int *)(&fetch_cfg_gpio[1]),sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_tx \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_patch("uart_para","uart_debug_rx",(void*)&fetch_cfg_gpio[1],sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error : can't patch uart_debug_tx\n");
|
||
return -1;
|
||
}
|
||
|
||
printf("uart_port_id = %d\n",uart_port_id);
|
||
uboot_spare_head.boot_data.uart_port = uart_port_id;
|
||
//reset
|
||
#ifdef UART_RST_CTRL
|
||
reg = readl(UART_RST_CTRL);
|
||
reg &= ~(1 << (16 + uart_port_id));
|
||
reg |= (1 << (16 + uart_port_id));
|
||
writel(reg,UART_RST_CTRL);
|
||
#endif
|
||
//gate
|
||
reg = readl(UART_GATE_CTRL);
|
||
reg &= ~(1 << (16 + uart_port_id));
|
||
reg |= (1 << (16 + uart_port_id));
|
||
writel(reg,UART_GATE_CTRL);
|
||
//enable card0
|
||
gpio_request_simple("uart_para",NULL);
|
||
serial_init();
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : modify_system_uart
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return : -1 :fail 0:success
|
||
*
|
||
* note : guoyingyang@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
|
||
int modify_system_uart(void)
|
||
{
|
||
script_gpio_set_t fetch_cfg_gpio[2];
|
||
int uart_port_id = 0;
|
||
char uartname[16] ;
|
||
char uart_data[8] ;
|
||
int sdc0_used = 0,uart_used = 1;
|
||
|
||
if(script_parser_fetch("force_uart_para","force_uart_rx",(int *)(&fetch_cfg_gpio[0]),sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error: can't find force_uart_rx \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_fetch("force_uart_para","force_uart_tx",(int *)(&fetch_cfg_gpio[1]),sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error: can't find force_uart_tx \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_fetch("force_uart_para","force_uart_port",(int *)(&uart_port_id),sizeof(int)/4))
|
||
{
|
||
printf("debug_mode_error: can't find card0_tx \n");
|
||
return -1;
|
||
}
|
||
memset(uartname,0,16);
|
||
memset(uart_data,0,8);
|
||
#if defined (CONFIG_ARCH_SUN7I) ||defined(CONFIG_ARCH_SUN8IW1P1)
|
||
strcat(uartname,"uart_para");
|
||
#else
|
||
strcat(uartname,"uart");
|
||
#endif
|
||
sprintf(uart_data,"%d",uart_port_id);
|
||
strcat(uartname,uart_data);
|
||
printf("the uartname is %s \n",uartname);
|
||
if(script_parser_patch(uartname,"uart_used",(int *)(&uart_used),sizeof(int)/4))
|
||
{
|
||
printf("debug_mode_error : can't find patch uart_used\n");
|
||
return -1;
|
||
}
|
||
if(script_parser_patch(uartname,"uart_port",(int *)(&uart_port_id),sizeof(int)/4))
|
||
{
|
||
printf("debug_mode_error : can't find uart_debug_port \n");
|
||
return -1;
|
||
}
|
||
if(script_parser_patch(uartname,"uart_rx",(void*)&fetch_cfg_gpio[0],sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error : can't patch uart_debug_rx\n");
|
||
return -1;
|
||
}
|
||
if(script_parser_patch(uartname,"uart_tx",(void*)&fetch_cfg_gpio[1],sizeof(script_gpio_set_t)/4))
|
||
{
|
||
printf("debug_mode_error : can't patch uart_debug_rx\n");
|
||
return -1;
|
||
}
|
||
//disable card0 init in linux
|
||
if(script_parser_patch("mmc0_para","sdc_used",(int *)(&sdc0_used),sizeof(int)/4))
|
||
{
|
||
printf("debug_mode_error :can not patch sdc_used \n");
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : change_to_debug_mode
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return : -1 :fail 0:success
|
||
*
|
||
* note : guoyingyang@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int change_to_debug_mode(void)
|
||
{
|
||
printf("enter debug mode\n");
|
||
if(modify_uboot_uart())
|
||
{
|
||
printf("debug_mode_error : fail to modify uboot uart\n");
|
||
return -1;
|
||
}
|
||
if(modify_system_uart())
|
||
{
|
||
printf("debug_mode_error: fail to modify system uart\n");
|
||
return -1;
|
||
}
|
||
//if enter debug mode ,set system can print message
|
||
loglel_change_flag = 1;
|
||
return 0;
|
||
}
|
||
|
||
#ifdef CONFIG_READ_LOGO_FOR_KERNEL
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : sunxi_read_bootlogo
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return : -1 :fail 0:success
|
||
*
|
||
* note : guoyingyang@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
void sunxi_read_bootlogo(char *part_name)
|
||
{
|
||
int ret = 0;
|
||
u32 rblock = 0;
|
||
u32 start_block = 0;
|
||
uint addr;
|
||
#if defined(CONFIG_SUNXI_LOGBUFFER)
|
||
addr = (uint)(CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
|
||
#else
|
||
addr = (uint)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR);
|
||
#endif
|
||
printf("addr = %x \n",addr);
|
||
start_block = sunxi_partition_get_offset_byname((const char *)part_name);
|
||
if(start_block == 0 )
|
||
return ;
|
||
rblock = sunxi_partition_get_size_byname((const char *)part_name);
|
||
ret = sunxi_flash_read(start_block, rblock, (void *)addr);
|
||
if(ret != 0)
|
||
{
|
||
gd->fb_base = addr ;
|
||
printf("sunxi_read_bootlogo: read bootlogo partition successful \n");
|
||
}
|
||
else
|
||
{
|
||
gd->fb_base = 0;
|
||
printf("sunxi_read_bootlogo: read bootlogo partition fail \n");
|
||
}
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
int get_boot_storage_type_ext(void)
|
||
{
|
||
/* get real storage type that from BROM at boot mode*/
|
||
return uboot_spare_head.boot_data.storage_type;
|
||
}
|
||
|
||
int get_boot_storage_type(void)
|
||
{
|
||
/* we think that nand and spi-nand are the same storage medium */
|
||
/* so we can use the same process to deal with them */
|
||
if(uboot_spare_head.boot_data.storage_type == STORAGE_NAND
|
||
|| uboot_spare_head.boot_data.storage_type == STORAGE_SPI_NAND)
|
||
{
|
||
return STORAGE_NAND;
|
||
}
|
||
return uboot_spare_head.boot_data.storage_type;
|
||
}
|
||
|
||
void set_boot_storage_type(int storage_type)
|
||
{
|
||
uboot_spare_head.boot_data.storage_type = storage_type;
|
||
}
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name : get_debugmode_flag
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note : guoyingyang@allwinnertech.com
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int get_debugmode_flag(void)
|
||
{
|
||
int debug_mode = 0;
|
||
if(uboot_spare_head.boot_data.work_mode != WORK_MODE_BOOT)
|
||
{
|
||
gd->debug_mode = 1;
|
||
return 0;
|
||
}
|
||
if(!script_parser_fetch("platform", "debug_mode",&debug_mode, 1))
|
||
gd->debug_mode = debug_mode;
|
||
else
|
||
gd->debug_mode = 1;
|
||
return 0;
|
||
}
|