734 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			734 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2009, Google Inc.
 | |
|  * All rights reserved.
 | |
|  * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  *  * Redistributions of source code must retain the above copyright
 | |
|  *	notice, this list of conditions and the following disclaimer.
 | |
|  *  * Redistributions in binary form must reproduce the above copyright
 | |
|  *	notice, this list of conditions and the following disclaimer in
 | |
|  *	the documentation and/or other materials provided with the
 | |
|  *	distribution.
 | |
|  *  * Neither the name of Google, Inc. nor the names of its contributors
 | |
|  *	may be used to endorse or promote products derived from this
 | |
|  *	software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | |
|  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | |
|  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | |
|  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | |
|  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | |
|  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | |
|  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | |
|  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | |
|  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | |
|  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <reg.h>
 | |
| #include <debug.h>
 | |
| #include <dev/keys.h>
 | |
| #include <dev/ssbi.h>
 | |
| #include <lib/ptable.h>
 | |
| #include <dev/flash.h>
 | |
| #include <smem.h>
 | |
| #include <mmc.h>
 | |
| #include <platform/iomap.h>
 | |
| #include <target/board.h>
 | |
| #include <platform.h>
 | |
| #include <crypto_hash.h>
 | |
| 
 | |
| #define VARIABLE_LENGTH		0x10101010
 | |
| #define DIFF_START_ADDR		0xF0F0F0F0
 | |
| #define NUM_PAGES_PER_BLOCK	0x40
 | |
| #define RECOVERY_MODE		0x77665502
 | |
| #define FOTA_COOKIE		0x64645343
 | |
| 
 | |
| unsigned int fota_cookie[1];
 | |
| 
 | |
| static struct ptable flash_ptable;
 | |
| unsigned hw_platform = 0;
 | |
| unsigned target_msm_id = 0;
 | |
| unsigned msm_version = 0;
 | |
| 
 | |
| /* Setting this variable to different values defines the
 | |
|  * behavior of CE engine:
 | |
|  * platform_ce_type = CRYPTO_ENGINE_TYPE_NONE : No CE engine
 | |
|  * platform_ce_type = CRYPTO_ENGINE_TYPE_SW : Software CE engine
 | |
|  * platform_ce_type = CRYPTO_ENGINE_TYPE_HW : Hardware CE engine
 | |
|  * Behavior is determined in the target code.
 | |
|  */
 | |
| static crypto_engine_type platform_ce_type = CRYPTO_ENGINE_TYPE_SW;
 | |
| 
 | |
| int machine_is_evb();
 | |
| 
 | |
| /* for these partitions, start will be offset by either what we get from
 | |
|  * smem, or from the above offset if smem is not useful. Also, we should
 | |
|  * probably have smem_ptable code populate our flash_ptable.
 | |
|  *
 | |
|  * When smem provides us with a full partition table, we can get rid of
 | |
|  * this altogether.
 | |
|  *
 | |
|  */
 | |
| static struct ptentry board_part_list_default[] = {
 | |
| 	{
 | |
| 	 .start = 0,
 | |
| 	 .length = 10 /* In MB */ ,
 | |
| 	 .name = "boot",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 253 /* In MB */ ,
 | |
| 	 .name = "system",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 80 /* In MB */ ,
 | |
| 	 .name = "cache",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 4 /* In MB */ ,
 | |
| 	 .name = "misc",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = VARIABLE_LENGTH,
 | |
| 	 .name = "userdata",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 4 /* In MB */ ,
 | |
| 	 .name = "persist",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 10 /* In MB */ ,
 | |
| 	 .name = "recovery",
 | |
| 	 },
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * SKU3 & SKU PVT devices use the same micron NAND device with different density,
 | |
|  * due to this SKU3 partition creation fails as the number of blocks calculated
 | |
|  * from flash density is wrong, To avoid this use a different partition table &
 | |
|  * move the variable length partition to the end, this way kernel will truncate
 | |
|  * the variable length partition & we need not add target checks in the shared
 | |
|  * nand driver code.
 | |
|  */
 | |
| 
 | |
| static struct ptentry board_part_list_sku3[] = {
 | |
| 	{
 | |
| 	 .start = 0,
 | |
| 	 .length = 10 /* In MB */ ,
 | |
| 	 .name = "boot",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 253 /* In MB */ ,
 | |
| 	 .name = "system",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 80 /* In MB */ ,
 | |
| 	 .name = "cache",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 4 /* In MB */ ,
 | |
| 	 .name = "misc",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 4 /* In MB */ ,
 | |
| 	 .name = "persist",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = 10 /* In MB */ ,
 | |
| 	 .name = "recovery",
 | |
| 	 },
 | |
| 	{
 | |
| 	 .start = DIFF_START_ADDR,
 | |
| 	 .length = VARIABLE_LENGTH,
 | |
| 	 .name = "userdata",
 | |
| 	 },
 | |
| };
 | |
| 
 | |
| static int num_parts = sizeof(board_part_list_default) / sizeof(struct ptentry);
 | |
| 
 | |
| void smem_ptable_init(void);
 | |
| unsigned smem_get_apps_flash_start(void);
 | |
| 
 | |
| void keypad_init(void);
 | |
| 
 | |
| int target_is_emmc_boot(void);
 | |
| 
 | |
| void target_init(void)
 | |
| {
 | |
| 	unsigned offset;
 | |
| 	struct flash_info *flash_info;
 | |
| 	struct ptentry *board_part_list;
 | |
| 	unsigned total_num_of_blocks;
 | |
| 	unsigned next_ptr_start_adr = 0;
 | |
| 	unsigned blocks_per_1MB = 8;	/* Default value of 2k page size on 256MB flash drive */
 | |
| 	int i;
 | |
| 
 | |
| 	dprintf(INFO, "target_init()\n");
 | |
| 
 | |
| #if (!ENABLE_NANDWRITE)
 | |
| 	keys_init();
 | |
| 	keypad_init();
 | |
| #endif
 | |
| 
 | |
| 	/* Display splash screen if enabled */
 | |
| #if DISPLAY_SPLASH_SCREEN
 | |
| 	display_init();
 | |
| 	dprintf(SPEW, "Diplay initialized\n");
 | |
| #endif
 | |
| 
 | |
| 	if (target_is_emmc_boot()) {
 | |
| 		/* Must wait for modem-up before we can intialize MMC.
 | |
| 		 */
 | |
| 		while (readl(MSM_SHARED_BASE + 0x14) != 1) ;
 | |
| 
 | |
| 		if (mmc_boot_main(MMC_SLOT, MSM_SDC3_BASE)) {
 | |
| 			dprintf(CRITICAL, "mmc init failed!");
 | |
| 			ASSERT(0);
 | |
| 		}
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	ptable_init(&flash_ptable);
 | |
| 	smem_ptable_init();
 | |
| 
 | |
| 	flash_init();
 | |
| 	flash_info = flash_get_info();
 | |
| 	ASSERT(flash_info);
 | |
| 
 | |
| 	offset = smem_get_apps_flash_start();
 | |
| 	if (offset == 0xffffffff)
 | |
| 		while (1) ;
 | |
| 
 | |
| 	total_num_of_blocks = flash_info->num_blocks;
 | |
| 	blocks_per_1MB = (1 << 20) / (flash_info->block_size);
 | |
| 
 | |
| 	if (target_is_sku3())
 | |
| 		board_part_list = board_part_list_sku3;
 | |
| 	else
 | |
| 		board_part_list = board_part_list_default;
 | |
| 
 | |
| 	for (i = 0; i < num_parts; i++) {
 | |
| 		struct ptentry *ptn = &board_part_list[i];
 | |
| 		unsigned len = ((ptn->length) * blocks_per_1MB);
 | |
| 
 | |
| 		if (ptn->start != 0)
 | |
| 			ASSERT(ptn->start == DIFF_START_ADDR);
 | |
| 
 | |
| 		ptn->start = next_ptr_start_adr;
 | |
| 
 | |
| 		if (ptn->length == VARIABLE_LENGTH) {
 | |
| 			unsigned length_for_prt = 0;
 | |
| 			unsigned j;
 | |
| 			for (j = i + 1; j < num_parts; j++) {
 | |
| 				struct ptentry *temp_ptn = &board_part_list[j];
 | |
| 				ASSERT(temp_ptn->length != VARIABLE_LENGTH);
 | |
| 				length_for_prt +=
 | |
| 				    ((temp_ptn->length) * blocks_per_1MB);
 | |
| 			}
 | |
| 			len =
 | |
| 			    (total_num_of_blocks - 1) - (offset + ptn->start +
 | |
| 							 length_for_prt);
 | |
| 			ASSERT(len >= 0);
 | |
| 		}
 | |
| 		next_ptr_start_adr = ptn->start + len;
 | |
| 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
 | |
| 			   len, ptn->flags, TYPE_APPS_PARTITION,
 | |
| 			   PERM_WRITEABLE);
 | |
| 	}
 | |
| 
 | |
| 	smem_add_modem_partitions(&flash_ptable);
 | |
| 
 | |
| 	ptable_dump(&flash_ptable);
 | |
| 	flash_set_ptable(&flash_ptable);
 | |
| }
 | |
| void board_info(void)
 | |
| {
 | |
| 	struct smem_board_info_v4 board_info_v4;
 | |
| 	unsigned int board_info_len = 0;
 | |
| 	unsigned smem_status;
 | |
| 	unsigned format = 0;
 | |
| 	unsigned id = 0;
 | |
| 
 | |
| 	if (hw_platform && target_msm_id)
 | |
| 		return;
 | |
| 
 | |
| 	hw_platform = MSM7X27A_SURF;
 | |
| 	target_msm_id = MSM7225A;
 | |
| 
 | |
| 	smem_status = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
 | |
| 						   &format, sizeof(format), 0);
 | |
| 	if (!smem_status) {
 | |
| 		if (format == 4) {
 | |
| 			board_info_len = sizeof(board_info_v4);
 | |
| 			smem_status =
 | |
| 			    smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
 | |
| 						  &board_info_v4,
 | |
| 						  board_info_len);
 | |
| 			if (!smem_status) {
 | |
| 				id = board_info_v4.board_info_v3.hw_platform;
 | |
| 				target_msm_id =
 | |
| 				    board_info_v4.board_info_v3.msm_id;
 | |
| 				msm_version =
 | |
| 				    board_info_v4.board_info_v3.msm_version;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/* Detect SURF v/s FFA v/s QRD */
 | |
| 		if (target_msm_id >= MSM8225 && target_msm_id <= MSM8625
 | |
| 						|| (target_msm_id == MSM8125A)
 | |
| 						|| (target_msm_id == MSM8125)) {
 | |
| 			switch (id) {
 | |
| 			case 0x1:
 | |
| 				hw_platform = MSM8X25_SURF;
 | |
| 				break;
 | |
| 			case 0x2:
 | |
| 				hw_platform = MSM8X25_FFA;
 | |
| 				break;
 | |
| 			case 0x10:
 | |
| 				hw_platform = MSM8X25_EVT;
 | |
| 				break;
 | |
| 			case 0x11:
 | |
| 				hw_platform = MSM8X25Q_SKUD;
 | |
| 				break;
 | |
| 			case 0xC:
 | |
| 				hw_platform = MSM8X25_EVB;
 | |
| 				break;
 | |
| 			case 0xF:
 | |
| 				hw_platform = MSM8X25_QRD7;
 | |
| 				break;
 | |
| 			default:
 | |
| 				hw_platform = MSM8X25_SURF;
 | |
| 			}
 | |
| 		} else {
 | |
| 			switch (id) {
 | |
| 			case 0x1:
 | |
| 				/* Set the machine type based on msm ID */
 | |
| 				if (msm_is_7x25a(target_msm_id))
 | |
| 					hw_platform = MSM7X25A_SURF;
 | |
| 				else
 | |
| 					hw_platform = MSM7X27A_SURF;
 | |
| 				break;
 | |
| 			case 0x2:
 | |
| 				if (msm_is_7x25a(target_msm_id))
 | |
| 					hw_platform = MSM7X25A_FFA;
 | |
| 				else
 | |
| 					hw_platform = MSM7X27A_FFA;
 | |
| 				break;
 | |
| 			case 0xB:
 | |
| 				if(target_is_emmc_boot())
 | |
| 					hw_platform = MSM7X27A_QRD1;
 | |
| 				else
 | |
| 					hw_platform = MSM7X27A_QRD3;
 | |
| 				break;
 | |
| 			case 0xC:
 | |
| 				hw_platform = MSM7X27A_EVB;
 | |
| 				break;
 | |
| 			case 0xF:
 | |
| 				hw_platform = MSM7X27A_QRD3;
 | |
| 				break;
 | |
| 			default:
 | |
| 				if (msm_is_7x25a(target_msm_id))
 | |
| 					hw_platform = MSM7X25A_SURF;
 | |
| 				else
 | |
| 					hw_platform = MSM7X27A_SURF;
 | |
| 			};
 | |
| 		}
 | |
| 		/* Set msm ID for target variants based on values read from smem */
 | |
| 		switch (target_msm_id) {
 | |
| 		case MSM7225A:
 | |
| 		case MSM7625A:
 | |
| 		case ESM7225A:
 | |
| 		case MSM7225AA:
 | |
| 		case MSM7625AA:
 | |
| 		case ESM7225AA:
 | |
| 		case MSM7225AB:
 | |
| 		case MSM7625AB:
 | |
| 		case ESM7225AB:
 | |
| 		case MSM7125A:
 | |
| 			target_msm_id = MSM7625A;
 | |
| 			break;
 | |
| 		case MSM8225:
 | |
| 		case MSM8625:
 | |
| 		case MSM8125A:
 | |
| 		case MSM8125:
 | |
| 			target_msm_id = MSM8625;
 | |
| 			break;
 | |
| 		default:
 | |
| 			target_msm_id = MSM7627A;
 | |
| 		}
 | |
| 	}
 | |
| 	return;
 | |
| }
 | |
| 
 | |
| unsigned board_machtype(void)
 | |
| {
 | |
| 	board_info();
 | |
| 	return hw_platform;
 | |
| }
 | |
| 
 | |
| unsigned board_msm_id(void)
 | |
| {
 | |
| 	board_info();
 | |
| 	return target_msm_id;
 | |
| }
 | |
| 
 | |
| unsigned board_msm_version(void)
 | |
| {
 | |
| 	board_info();
 | |
| 	msm_version = (msm_version & 0xffff0000) >> 16;
 | |
| 	return msm_version;
 | |
| }
 | |
| 
 | |
| crypto_engine_type board_ce_type(void)
 | |
| {
 | |
| 	return platform_ce_type;
 | |
| }
 | |
| 
 | |
| void reboot_device(unsigned reboot_reason)
 | |
| {
 | |
| 	reboot(reboot_reason);
 | |
| }
 | |
| 
 | |
| static int read_from_flash(struct ptentry* ptn, int offset, int size, void *dest)
 | |
| {
 | |
| 	void *buffer = NULL;
 | |
| 	unsigned page_size = flash_page_size();
 | |
| 	unsigned page_mask = page_size - 1;
 | |
| 	int read_size = (size + page_mask) & (~page_mask);
 | |
| 
 | |
| 	buffer = malloc(read_size);
 | |
| 	if(!buffer){
 | |
| 		dprintf(CRITICAL, "ERROR : Malloc failed for read_from_flash \n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	if(flash_read(ptn, offset, buffer, read_size)){
 | |
| 		dprintf(CRITICAL, "ERROR : Flash read failed \n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 	memcpy(dest, buffer, size);
 | |
| 	free(buffer);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static unsigned int get_fota_cookie_mtd(void)
 | |
| {
 | |
| 	struct ptentry *ptn;
 | |
| 	struct ptable *ptable;
 | |
| 	unsigned int cookie = 0;
 | |
| 
 | |
| 	ptable = flash_get_ptable();
 | |
| 	if (ptable == NULL) {
 | |
| 		dprintf(CRITICAL, "ERROR: Partition table not found\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	ptn = ptable_find(ptable, "FOTA");
 | |
| 	if (ptn == NULL) {
 | |
| 		dprintf(CRITICAL, "ERROR: No FOTA partition found\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	if (read_from_flash(ptn, 0, sizeof(unsigned int), &cookie) == -1) {
 | |
| 		dprintf(CRITICAL, "ERROR: failed to read fota cookie from flash\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return cookie;
 | |
| }
 | |
| 
 | |
| static int read_from_mmc(struct ptentry* ptn, int size, void *dest)
 | |
| {
 | |
| 	void *buffer = NULL;
 | |
| 	unsigned sector_mask = 511;
 | |
| 	int read_size =  (size + sector_mask) & (~sector_mask);
 | |
| 
 | |
| 	buffer = malloc(read_size);
 | |
| 	if(!buffer){
 | |
| 		dprintf(CRITICAL, "ERROR : Malloc failed for read_from_flash \n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	if(mmc_read(ptn, buffer, read_size)) {
 | |
| 		dprintf(CRITICAL, "ERROR : Flash read failed \n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 	memcpy(dest, buffer, size);
 | |
| 	free(buffer);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int get_fota_cookie_mmc(void)
 | |
| {
 | |
| 	unsigned long long ptn = 0;
 | |
| 	int index = -1;
 | |
| 	unsigned int cookie = 0;
 | |
| 
 | |
| 	index = partition_get_index("FOTA");
 | |
| 	ptn = partition_get_offset(index);
 | |
| 
 | |
| 	if(ptn == 0) {
 | |
| 		dprintf(CRITICAL,"ERROR: FOTA partition not found\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 	if(read_from_mmc(ptn, sizeof(unsigned int), &cookie)) {
 | |
| 		dprintf(CRITICAL, "ERROR: Cannot read cookie info\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return cookie;
 | |
| }
 | |
| 
 | |
| unsigned check_reboot_mode(void)
 | |
| {
 | |
| 	unsigned mode[2] = { 0, 0 };
 | |
| 	unsigned int mode_len = sizeof(mode);
 | |
| 	unsigned smem_status;
 | |
| 	unsigned int cookie = 0;
 | |
| 
 | |
| 	smem_status = smem_read_alloc_entry(SMEM_APPS_BOOT_MODE,
 | |
| 					    &mode, mode_len);
 | |
| 
 | |
| 	/*
 | |
| 	 * SMEM value is relied upon on power shutdown. Check either of SMEM
 | |
| 	 * or FOTA update cookie is set
 | |
| 	 */
 | |
| 	if (target_is_emmc_boot())
 | |
| 		cookie = get_fota_cookie_mmc();
 | |
| 	else
 | |
| 		cookie = get_fota_cookie_mtd();
 | |
| 
 | |
| 	if ((mode[0] == RECOVERY_MODE) || (cookie == FOTA_COOKIE))
 | |
| 		return RECOVERY_MODE;
 | |
| 
 | |
| 	if (smem_status) {
 | |
| 		dprintf(CRITICAL,
 | |
| 			"ERROR: unable to read shared memory for reboot mode\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return mode[0];
 | |
| }
 | |
| 
 | |
| static unsigned target_check_power_on_reason(void)
 | |
| {
 | |
| 	unsigned power_on_status = 0;
 | |
| 	unsigned int status_len = sizeof(power_on_status);
 | |
| 	unsigned smem_status;
 | |
| 
 | |
| 	smem_status = smem_read_alloc_entry(SMEM_POWER_ON_STATUS_INFO,
 | |
| 					    &power_on_status, status_len);
 | |
| 	if (smem_status) {
 | |
| 		dprintf(CRITICAL,
 | |
| 			"ERROR: unable to read shared memory for power on reason\n");
 | |
| 	}
 | |
| 
 | |
| 	return power_on_status;
 | |
| }
 | |
| 
 | |
| unsigned target_pause_for_battery_charge(void)
 | |
| {
 | |
| 	if (target_check_power_on_reason() == PWR_ON_EVENT_WALL_CHG)
 | |
| 		return 1;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void target_battery_charging_enable(unsigned enable, unsigned disconnect)
 | |
| {
 | |
| }
 | |
| 
 | |
| #if _EMMC_BOOT
 | |
| void target_serialno(unsigned char *buf)
 | |
| {
 | |
| 	unsigned int serialno;
 | |
| 	serialno = mmc_get_psn();
 | |
| 	sprintf(buf, "%x", serialno);
 | |
| }
 | |
| 
 | |
| int emmc_recovery_init(void)
 | |
| {
 | |
| 	int rc;
 | |
| 	rc = _emmc_recovery_init();
 | |
| 	return rc;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int machine_is_evb()
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	unsigned mach_type = board_machtype();
 | |
| 
 | |
| 	switch(mach_type) {
 | |
| 		case MSM7X27A_EVB:
 | |
| 		case MSM8X25_EVB:
 | |
| 		case MSM8X25_EVT:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	}
 | |
| 	return ret;
 | |
| }
 | |
| int machine_is_qrd()
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	unsigned mach_type = board_machtype();
 | |
| 
 | |
| 	switch(mach_type) {
 | |
| 		case MSM7X27A_QRD1:
 | |
| 		case MSM7X27A_QRD3:
 | |
| 		case MSM8X25_QRD7:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	}
 | |
| 	return ret;
 | |
| }
 | |
| int machine_is_skud()
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	unsigned mach_type = board_machtype();
 | |
| 
 | |
| 	switch(mach_type) {
 | |
| 		case MSM8X25Q_SKUD:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	}
 | |
| 	return ret;
 | |
| }
 | |
| int machine_is_8x25()
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	unsigned mach_type = board_machtype();
 | |
| 
 | |
| 	switch(mach_type) {
 | |
| 		case MSM8X25_SURF:
 | |
| 		case MSM8X25_FFA:
 | |
| 		case MSM8X25_EVB:
 | |
| 		case MSM8X25_EVT:
 | |
| 		case MSM8X25_QRD7:
 | |
| 		case MSM8X25Q_SKUD:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	}
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| int msm_is_7x25a(int msm_id)
 | |
| {
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	switch (msm_id) {
 | |
| 		case MSM7225A:
 | |
| 		case MSM7625A:
 | |
| 		case ESM7225A:
 | |
| 		case MSM7225AA:
 | |
| 		case MSM7625AA:
 | |
| 		case ESM7225AA:
 | |
| 		case MSM7225AB:
 | |
| 		case MSM7625AB:
 | |
| 		case ESM7225AB:
 | |
| 		case MSM7125A:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	};
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static void target_ulpi_init(void)
 | |
| {
 | |
| 	unsigned int reg;
 | |
| 
 | |
| 	ulpi_read(0x31);
 | |
| 	dprintf(INFO, " Value of ulpi read 0x31 is %08x\n", reg);
 | |
| 	/* todo : the write back value should be calculated according to
 | |
| 	 * reg &= 0xF3 but sometimes the value that is read initially
 | |
| 	 * doesnt look right
 | |
| 	 */
 | |
| 	ulpi_write(0x4A, 0x31);
 | |
| 	reg = ulpi_read(0x31);
 | |
| 	dprintf(INFO, " Value of ulpi read 0x31 after write is %08x\n", reg);
 | |
| 
 | |
| 	reg = ulpi_read(0x32);
 | |
| 	dprintf(INFO, " Value of ulpi read 0x32 is %08x\n", reg);
 | |
| 	ulpi_write(0x30, 0x32);
 | |
| 	reg = ulpi_read(0x32);
 | |
| 	dprintf(INFO, " Value of ulpi read 0x32 after write is %08x\n", reg);
 | |
| 
 | |
| 	reg = ulpi_read(0x36);
 | |
| 	dprintf(INFO, " Value of ulpi read 0x36 is %08x\n", reg);
 | |
| 	ulpi_write(reg | 0x2, 0x36);
 | |
| 	reg = ulpi_read(0x36);
 | |
| 	dprintf(INFO, " Value of ulpi read 0x36 after write is %08x\n", reg);
 | |
| }
 | |
| 
 | |
| void target_usb_init(void)
 | |
| {
 | |
| 	target_ulpi_init();
 | |
| }
 | |
| 
 | |
| int target_cont_splash_screen()
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	unsigned mach_type = 0;
 | |
| 
 | |
| 	mach_type = board_machtype();
 | |
| 
 | |
| 	switch(mach_type) {
 | |
| 		case MSM8X25_EVB:
 | |
| 		case MSM8X25_EVT:
 | |
| 		case MSM8X25_QRD7:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	};
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| int target_is_sku3()
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	unsigned mach_type = 0;
 | |
| 
 | |
| 	mach_type = board_machtype();
 | |
| 
 | |
| 	switch(mach_type) {
 | |
| 		case MSM7X27A_QRD3:
 | |
| 			ret = 1;
 | |
| 			break;
 | |
| 		default:
 | |
| 			ret = 0;
 | |
| 	};
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| /* Function to set the capabilities for the host */
 | |
| void target_mmc_caps(struct mmc_host *host)
 | |
| {
 | |
| 	host->caps.ddr_mode = 0;
 | |
| 	host->caps.hs200_mode = 0;
 | |
| 	host->caps.bus_width = MMC_BOOT_BUS_WIDTH_4_BIT;
 | |
| 	host->caps.hs_clk_rate = MMC_CLK_50MHZ;
 | |
| }
 | 
