SBL
最近踩的坑,记录一下,QFILE无法烧录程序,卡在烧录,后来发现是硬件的boot config配置问题
串口打印:
Format: Log Type - Time(microsec) - message - optional Info
Log Type: B - Since Boot(Power On Reset), D - Delta, S - Statistic
S - QC_IMAGE_VERSION_STRING=BOOT.BF.3.1.2.C2-00052
S - IMAGE_VARIANT_STRING=DAADANAZA
S - OEM_IMAGE_VERSION_STRING=titus-Gen9
S - Boot Config, 0x000000e1
B - 1567 - PBL, Start
B - 4546 - bootable_media_detect_entry, Start
B - 34490768 - bootable_media_detect_success, Start
B - 34490772 - elf_loader_entry, Start
B - 41428806 - auth_hash_seg_entry, Start
B - 41429054 - auth_hash_seg_exit, Start
B - 44022147 - elf_segs_hash_verify_entry, Start
B - 44090943 - PBL, End
B - 34835300 - SBL1, Start
B - 34881264 - boot_flash_init, Start
D - 0 - boot_flash_init, Delta
B - 34886540 - boot_config_data_table_init, Start
D - 30 - boot_config_data_table_init, Delta - (0 Bytes)
B - 34894592 - CDT version:3,Platform ID:8,Major ID:1,Minor ID:0,Subtype:0
B - 34900082 - zyk->
B - 34901394 - enter sbl1_hw_init---zyk
B - 34904291 - build_type:2
B - 34906304 - sbl1_ddr_set_params, Start
B - 34909415 - cpr_init, Start
D - 0 - cpr_init, Delta
B - 34913868 - Pre_DDR_clock_init, Start
D - 183 - Pre_DDR_clock_init, Delta
D - 0 - sbl1_ddr_set_params, Delta
sbl1与lk共同够成高通平台的bootloader功能,现在主要记录一下高通平台sbl1启动的流程与相关烧录部分
sbl1_main_ctl
boot_config_process_bl-》boot_config_process_entry
从flash中下载代码到ram
/*------------------------------------------------------------------
186 Image Loading and Authentication
187 ------------------------------------------------------------------*/
188 /* Reset boot statistics flash byte counter. */
189 boot_statistics_reset_flash_byte_counter();
190
191 if (boot_config_entry->load == TRUE)
sbl1_config_table
load_qsee_pre_procs
boot_hand_control_to_deviceprogrammer_ddr_main
boot_deviceprogrammer_ddr_main
deviceprogrammer_entry
deviceprogrammer_init_hw
initFirehoseStorage
sdcc_handle_open
sdcc_handle_find_card
sdcc_find_mmc_device
sdcc_command
开始部分为sbl1.s
sbl1_entry
;Change to supervisor Mode
msr CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
; Save the passing parameter from PBL 将PBL中的数据传给sbl1,这里暂时存储在r7中
mov r7, r0
; Set VBAR (vector Base Address Register) to SBL vector table
ldr r0, =SCL_SBL1_VECTOR_BASE
MCR p15, 0, r0, c12, c0, 0
; Setup the supervisor mode stack
ldr r0, =|Image$$SBL1_SVC_STACK$$ZI$$limit|
mov r13, r0
; Switch to IRQ
msr CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
mov r13, r0
; Switch to FIQ
msr CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
mov r13, r0
; Switch to undefined mode and setup the undefined mode stack
msr CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
ldr r0, =|Image$$SBL1_UND_STACK$$ZI$$Limit|
mov r13, r0
; Switch to abort mode and setup the abort mode stack
msr CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
ldr r0, =|Image$$SBL1_ABT_STACK$$ZI$$Limit|
mov r13, r0
; Return to supervisor mode
msr CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
; Restore the passing parameter 将pbl的数据传给r0一起作为函数参数给sbl1
mov r0, r7
; ------------------------------------------------------------------
; Call functions external to perform SBL1 function.
; It should never return.
; ------------------------------------------------------------------
ldr r5, =sbl1_main_ctl c语言的主要入口
blx r5
; For safety
bl loophere ; never returns, keep lr in r14 for debug
/*===========================================================================
** Function : sbl1_main_ctl
** ==========================================================================
*/
/*!
*
* @brief
* The Main controller performs the following functions:
* - Initializes ram
* - And so on...
*
* @param[in] pbl_shared Pointer to shared data
*
* @par Dependencies
* None
*
* @retval
* None
*
* @par Side Effects
* This function never returns.
*
*/
void sbl1_main_ctl(boot_pbl_shared_data_type *pbl_shared)
{
bl_ERROR_type status = BL_ERR_OTHERS;
/* Calculate the SBL start time for use during boot logger initialization. */
sbl_start_time = CALCULATE_TIMESTAMP(HWIO_IN(TIMETICK_CLK));
#ifdef SBL1_disable_D_cache
mmu_flush_cache_and_disable();
mmu_enable_instruction_cache();
#endif
/* Enabling external abort */
sbl1_external_abort_enable(CPSR_EA_BIT);
/*configure Domain access control register */
mmu_set_dacr(DACR_ALL_DOMAIN_CLIENTS);
/* Enable qdss workaround*/
boot_clock_debug_init();
/* Enter debug mode if debug cookie is set */
sbl1_debug_mode_enter();
/* Initialize the stack protection canary */
boot_init_stack_chk_canary();
/* Initialize boot shared imem */
boot_shared_imem_init(&bl_shared_data);
/* Initialize busywait module
Note: This is required to be done before logger init due to uart driver
dependency on busywait */
BL_VERIFY(boot_busywait_init() == DAL_SUCCESS,BL_ERR_SBL);
/* Initialize boot logger and start the log timer */
sbl1_boot_logger_init(&boot_log_data,
pbl_shared);
boot_log_set_meta_info(boot_log_data.meta_info_start);
/* Retrieve info passed from PBL*/
sbl1_retrieve_shared_info_from_pbl(pbl_shared);
/* Initialize the QSEE interface */
sbl1_init_sbl_qsee_interface(&bl_shared_data,
&sbl_verified_info);
/* Initialize SBL memory map.
Initializing early because drivers could be located in RPM Code RAM. */
sbl1_populate_initial_mem_map(&bl_shared_data);
/* Initialize the secboot functions */
BL_VERIFY(boot_secboot_ftbl_init(&bl_shared_data) == BL_ERR_NONE,
BL_ERR_IMG_SECURITY_FAIL);
/* set hash algorithm */
BL_VERIFY((status = boot_set_hash_algo(SBL_HASH_SHA256)) == BL_ERR_NONE,
status);
/* Initialize dal heap using internal memory */
boot_DALSYS_HeapInit(boot_internal_heap,
BOOT_INTERNAL_HEAP_SIZE,
FALSE);
/*Initialize DAL, needs to be called before modules that uses DAL */
boot_DALSYS_InitMod(NULL);
/* Store the sbl1 hash to shared imem */
boot_store_tpm_hash_block(&bl_shared_data,
&sbl_verified_info);
/* Initialize roll back protection image table */
boot_rollback_init_img_set_table(&bl_shared_data,
&boot_rollback_version_img_set_table[0],
boot_rollback_version_img_set_num);
#if (!defined(FEATURE_RUMI_BOOT))
/* calling here to ensure eeprom init goes fine for CDT read */
boot_pre_i2c_clock_init();
#endif
/* Check L2 error flag, if it has been set then set dload cookie and reboot */
if(L2_parity_error_in_sbl)
{
boot_dload_set_cookie();
boot_hw_reset(BOOT_WARM_RESET_TYPE);
}
/*-----------------------------------------------------------------------
Add the SBL1, System Debug, SMEM, and OCIMEM address ranges
to the memory protection.
-----------------------------------------------------------------------*/
boot_clobber_add_global_protection_region((void *)SBL1_CODE_BASE,
SBL1_MAX_IMAGE_SIZE );
boot_clobber_add_global_protection_region((void *)SCL_SBL1_DDR_DATA_BASE,
SCL_SBL1_DDR_DATA_SIZE);
boot_clobber_add_global_protection_region((void *)SCL_SYSTEM_DEBUG_BASE,
SCL_SYSTEM_DEBUG_SIZE);
boot_clobber_add_global_protection_region((void *)SCL_SHARED_RAM_BASE,
SCL_SHARED_RAM_SIZE);
boot_clobber_add_global_protection_region((void *)SCL_IMEM_BASE,
SCL_IMEM_SIZE);
/*----------------------------------------------------------------------
In SBL builds the function below is stubbed out (does nothing).
When building Deviceprogrammer the function below never returns.
The function below becomes active by defining the feature
FEATURE_BOOT_EXTERN_DEVICEPROGRAMMER_LITE_COMPLETED.
----------------------------------------------------------------------*/
boot_hand_control_to_deviceprogrammer_lite_main (pbl_shared);
/*-----------------------------------------------------------------------
Process the target-dependent SBL1 procedures
-----------------------------------------------------------------------*/
boot_config_process_bl(&bl_shared_data,
SBL1_IMG,
sbl1_config_table);
} /* sbl1_main_ctl() */
559 /*==========================================================================
560 DEFINE TARGET BOOT CONFIG TABLE
561 ===========================================================================*/
562 boot_configuration_table_entry sbl1_config_table[] =
563 {
564
565 /* SBL1 -> QSEE */
566 {
567 SBL1_IMG, /* host_img_id */
568 CONFIG_IMG_QC, /* host_img_type */
569 GEN_IMG, /* target_img_id */
570 CONFIG_IMG_ELF, /* target_img_type */
571 SECBOOT_QSEE_SW_TYPE, /* target_img_sec_type */
572 TRUE, /* load */
573 TRUE, /* auth */
574 FALSE, /* exec */
575 FALSE, /* jump */
576 NULL, /* exec_func */
577 NULL, /* jump_func */
578 load_qsee_pre_procs, /* pre_procs */
579 load_qsee_post_procs, /* post_procs */
580 NULL, /* load_cancel */
581 qsee_partition_name, /* target_img_partition_id */
582 QSEE_BOOT_LOG_STR, /* target_img_str */
583 sbl1_table, /* whitelist table */
584 FALSE, /* boot_ssa_enabled */
585 TRUE, /* enable_rollback_protection*/
586 FALSE, /* enable_xpu */
587 0x0 /* xpu_proc_id*/
588 },
589
590 /* SBL1 -> RPM */
591 {
592 SBL1_IMG, /* host_img_id */
593 CONFIG_IMG_QC, /* host_img_type */
594 GEN_IMG, /* target_img_id */
595 CONFIG_IMG_ELF, /* target_img_type */
596 SECBOOT_RPM_FW_SW_TYPE, /* target_img_sec_type */
597 TRUE, /* load */
598 TRUE, /* auth */
599 FALSE, /* exec */
245 /*==========================================================================
246 FUNCTIONS TO EXECUTE BEFORE TZ LOADING
247 ===========================================================================*/
248 boot_procedure_func_type load_qsee_pre_procs[] =
249 {
250 /* Save reset register logs */
251 boot_save_reset_register_log,
252
253 /*----------------------------------------------------------------------
254 Update the partition IDs to be used for GUID based boot targets
255 ----------------------------------------------------------------------*/
256 sbl1_update_partition_ids,
257
258 #ifdef FEATURE_BOOT_SDCC_BOOT
259 /* Initialize the flash device */
260 boot_flash_init,
261 #endif
262 /* Copy the configure data table from eeprom */
263 boot_config_data_table_init,
264
265 /* Store platform id */
266 sbl1_hw_platform_pre_ddr,
267
268 (boot_procedure_func_type)sbl1_hw_init,
269
270 /* Configure ddr parameters based on eeprom CDT table data. */
271 sbl1_ddr_set_params,
272
273 /* Initialize DDR */
274 (boot_procedure_func_type)sbl1_ddr_init,
275
276 /*----------------------------------------------------------------------
277 In SBL builds the function below is stubbed out (does nothing).
278 When building Deviceprogrammer the function below never returns.
279 The function below becomes active by defining the feature
280 FEATURE_BOOT_EXTERN_DEVICEPROGRAMMER_DDR_COMPLETED.
281 ----------------------------------------------------------------------*/
282 boot_hand_control_to_deviceprogrammer_ddr_main,
283
284 /*Set ddr parameters in CDB2&CDB3, enhance set*/
285 sbl1_ddr_set_params_enhance,
286
287 /* Initialize SBL1 DDR ZI region, relocate boot log to DDR */
288 sbl1_post_ddr_init,
289
290 sbl1_hw_init_secondary,
291
292 /* DDR training */
293 (boot_procedure_func_type)sbl1_wait_for_ddr_training,
294
40 /*===========================================================================
41 FUNCTION DECLARATIONS
42 ===========================================================================*/
43
44 /*===========================================================================
45
46 ** Function : boot_deviceprogrammer_ddr_main
47
48 ** ==========================================================================
49 */
50 /*!
51 * Run deviceprogrammer after ddr has been initialized.
52 *
53 * @param bl_shared_data
54 * The shared bootloader information.
55 *
56 * @return
57 * This function never returns.
58 *
59 *****************************************************************************/
60 void boot_hand_control_to_deviceprogrammer_ddr_main
61 (
62 bl_shared_data_type *bl_shared_data
63 )
64 {
65 deviceprogrammer_entry(bl_shared_data->sbl_shared_data->pbl_shared_data);
66 for (;;);
67 }
128 // The entry point from SBL.
129 void deviceprogrammer_entry(boot_pbl_shared_data_type *pbl_shared)
130 {
131 pbl_shared_global = pbl_shared;
132
133 deviceprogrammer_zi_buffers ();
134 deviceprogrammer_init_hw();
135 main_firehose();
136 }
70 void deviceprogrammer_init_hw() {
71 char err_log[256] = {0};
72 printLog("%s %d----zyk",__FUNCTION__,__LINE__);
73 printLog("deviceprogrammer_init_hw");
74 initFirehoseProtocol(); // initializes default values for fh structure
75
76 #ifndef FEATURE_FIREHOSE_SKIP_CLOCK
77 #ifndef FEATURE_BOOT_EXTERN_DEVICEPROGRAMMER_DDR_COMPLETED
78 // This needs to be called before calling Clock_Init()
79 if (TRUE != Clock_PreDDRInitEx(DDR_TYPE_LPDDR2)) { strlcat(err_log, "clock pre ddr:fail ", sizeof(err_log)); }
80 #endif
81
82 // Lowering clock frequencies because otherwise eMMC card initialization sometimes fails
83 // if the clock '' is set too high
84 if (FALSE == Clock_Init(CLOCK_BOOT_PERF_MIN, CLOCK_BOOT_PERF_MIN)) { strlcat(err_log, "init clock:fail ", sizeof(err_log)); }
85 #endif
86
87 // Call setlocale to set the locale to the default values
88 // for string functions such as strncasecmp to work properly
89 setlocale(LC_ALL, "C");
90
91 if(PM_ERR_FLAG__SUCCESS != pm_pon_channel_config()) { strlcat(err_log, "init pmic:fail ", sizeof(err_log)); }
92 printLog("%s %d----zyk",__FUNCTION__,__LINE__);
93
94 // Initialize eMMC storage device, open up handles
95 if (FALSE == initFirehoseStorage()) { strlcat(err_log, "init storage:fail ", sizeof(err_log)); printLog("%s %d---initFirehoseStorage fail-zyk
",__FUNCTION__,__LINE__);}
96
97 #ifndef FEATURE_FIREHOSE_SKIP_CLOCK
98 // This calls the Clock API to bump up clocks.
99 // Before doing this, we need support for it in the Clock SCons
100 // env.AddLibsToImage(['CLOCK_BOOT_DRIVER', 'EMMCBLD_IMAGE'],
101 // ClockChipsetSBL_lib)
102 // in file core\systemdrivers\clock\hw\msm8974\build\clock_sbl.scons
103 if (FALSE == Clock_Init(CLOCK_BOOT_PERF_MAX, CLOCK_BOOT_PERF_MAX)) { strlcat(err_log, "init clock:fail ", sizeof(err_log)); }
104 #endif
105
106 #ifndef SKIP_SECBOOT_CHECK_NOT_recommended_BY_QUALCOMM
107 // This check below is to ensure that only VIP programmer is run on secure boot devices
108 // In otherwords, signing the non VIP programmer is highly not recommended
109 if (FALSE == isvalidationMode() && TRUE == isAuthenticationEnabled()) { strlcat(err_log, "Secure boot detected. VIP not enabled:fail ", sizeof(err_log)); }
110 #endif
111
112 // These PMIC calls were added to have long key power off to be
113 // working from flash programmer so that device can be powered off in
114 // factory for devices that do not have removable BATtery
115 pm_pon_reset_source_cfg(0,PM_PON_RESET_SOURCE_KPDPWR,904,500,
116 PM_PON_RESET_CFG_NORMAL_SHUTDOWN);
117 pm_pon_reset_source_ctl(0, PM_PON_RESET_SOURCE_KPDPWR,PM_ON);
118
119 initFirehoseTransport(); // Initialize USB transport
120 if (strlen(err_log) > 0) {
121 while (1) {
246 boolean initFirehoseStorage() {
247 printLog("%s %d----zyk",__FUNCTION__,__LINE__);
248 printLog("initFirehoseStorage");
249 return init_storage_device_hw(&(fh.emmc_storage));
250 }
73 boolean init_storage_device_hw(storage_device_t *storedev) {
74 SDCC_STATUS rc;
75 int i;
76 sdcc_mem_info_type mem_info;
77
78 for (i = PARTITION_EMMC_USER; i < PARTITION_EMMC_NONE; i++) {
79 if (i != PARTITION_EMMC_RPMB) {
80 //FREEZE_watchdog();
81 printLog("init_storage_device_hw 1");
82 printLog("%s %d----zyk",__FUNCTION__,__LINE__);
83
84 storedev->hsdev_partition_handles[i] = sdcc_handle_open (
85 storedev->drivenum,
86 i);
87 if (i == PARTITION_EMMC_USER) {
88 if (storedev->hsdev_partition_handles[i] == NULL) {
89 printLog("init_storage_device_hw 2");
90 printLog("%s %d----zyk",__FUNCTION__,__LINE__);
91 storedev->hsdev_partition_handles[i] = sdcc_handle_open (
92 storedev->drivenum,
93 i);
94 if (storedev->hsdev_partition_handles[i] == NULL)
95 return false;
96 }
97
98 rc = sdcc_handle_mem_get_device_info(storedev->hsdev_partition_handles[i], &mem_info);
99 if (rc != SDCC_NO_ERROR)
100 return FALSE;
101 if (mem_info.card_size_in_sectors > 0)
102 storedev->sector_size = mem_info.block_len;
103 }
104
105 }
106 }
107
108 //FREEZE_WATCHDOG();
109 // TODO: Can we ignore the return value of this call ?
110 rc = sdcc_handle_set_active_bootable_partition(
111 storedev->hsdev_partition_handles[PARTITION_EMMC_USER]);
112 if (rc != SDCC_NO_ERROR) {
113
114 }
115 return TRUE;
116 }
core/storage/sdcc/src/sdcc_Mini_api.c
/*lint -save -e641 Suppress 'Converting enum to int' warning */
/******************************************************************************
* Name: sdcc_handle_open
*
* Description:
* This function first initializes the SDCC controller such as turning on the
* clock, configuring the GPiOS, and turning on the power supply to the
* device. It returns NULL if there is no memory device attached. If there
* is a memory device, it will initialize the device and take it out of the
* identification state. It then sets up the device for data transfer.
* A non-null pointer to the SDCC device is returned.
*
* arguments:
* driveno [IN] : a valid drive number between 0 and the total
* number of card slots - 1
* phy_partition_num [IN] : physical partition number. Use
* \ref SDCC_HANDLE_PHY_PARTITION_ENTIRE_MEM_DEVICE
* to get a handle representing the entire memory
* device. For eMMC v4.3, the valid boot partition
* numbers are 1 and 2. User area partition number
* is 0.
*
* Returns:
* A pointer to the SDCC device if successful. NULL if failed.
*
* Note:
* sdcc_init() is called in sdcc_handle_open().
*
******************************************************************************/
struct sdcc_device *
sdcc_handle_open( int16 driveno, uint32 phy_partition_num )
{
SDCC_STATUS rc = SDCC_NO_ERROR;
sdcc_slot_type *sdcc_pdata = NULL;
sdcc_dev_type *sdcc_pdev = NULL;
boolean ret = TRUE;
struct sdcc_device *ret_handle = NULL;
boolean still_in_use = TRUE;
printLog("enter---k min api sdcc_handle_open");
if ( !SDCC_DRIVENO_IS_VALID(driveno) )
{
DPRINTF(("Invalid Drive Number: %d", driveno));
return NULL;
}
/* PBL uses legacy Qualcomm mode, so partial enumeration is supported in */
/* Qualcomm legacy mode only. However, if we switch to SDHCi mode now, */
/* we need to do a full re-init */
if ((FALSE == SDCCSdhciEnable) &&
(TRUE == sdcc_is_partial_enumeration (driveno)))
{
ret_handle = sdcc_handle_optimized_open (phy_partition_num);
return ret_handle;
}
/* This is the only place we get config flag from a UEFI variable
* to determine if the driver supports SDHCi or Qualcomm interface.
* After this, we'll use the p_device->sdhci_mode as flag */
if (TRUE == SDCCSdhciEnable)
{
ret = sdcc_init_sdhci_mode(driveno);
}
else
{
ret = sdcc_init_qc_mode(driveno);
}
if ( FALSE == ret )
{
DPRINTF(("Failed to initialize drive number %d", driveno));
return NULL;
}
sdcc_pdata = sdcc_get_slot_handle (driveno);
if (NULL == sdcc_pdata)
{
DPRINTF(("sdcc_handle_open: can't get slot handle\n"));
return NULL;
}
sdcc_pdev = &(sdcc_pdata->dev);
do
{
/* register the client handle first */
ret_handle = sdcc_register_client_handle( (uint32)driveno,
phy_partition_num );
if ( NULL == ret_handle )
{
/* check if memory device in driveno is still in use */
still_in_use = sdcc_is_device_still_in_use( sdcc_pdev );
if ( !still_in_use )
{
/* client handle list is full */
(void) sdcc_deinit( sdcc_pdev );
}
break;
}
/* return if this is a SDIO device */
if ( SDCC_CARD_SDIO == sdcc_pdev->card_type )
{
/* client handle registration will be initiated in SDIO API */
/* deregister the client handle */
sdcc_deregister_client_handle( &ret_handle );
break;
}
/* return if it has been initialized */
if (( SDCC_CARD_SD == sdcc_pdev->card_type ) ||
( SDCC_CARD_SDHC == sdcc_pdev->card_type ) ||
( SDCC_CARD_MMC == sdcc_pdev->card_type ) ||
( SDCC_CARD_MMCHC == sdcc_pdev->card_type ))
{
/* no need to select the partition region on the device as it is */
/* already in use */
/* will return a new handle to client */
break;
}
printLog("194 zyk min api sdcc_handle_open");
/* find the attached device */
sdcc_pdev->card_type = sdcc_handle_find_card( ret_handle );
/* update card_type field in sdcc_mem_info struct */
sdcc_pdev->mem.mem_info.card_type = sdcc_pdev->card_type;
/* return and close controller if none attached */
if ( SDCC_CARD_UNKNOWN == sdcc_pdev->card_type )
{
(void) sdcc_handle_close(ret_handle);
ret_handle = NULL;
break;
}
/* return if SDIO device attached */
if ( SDCC_CARD_SDIO == sdcc_pdev->card_type )
{
/* client handle registration will be initiated in SDIO API */
/* deregister the client handle */
sdcc_deregister_client_handle( &ret_handle );
DPRINTF(("Found SDIO device.\n"));
break;
}
/* proceed if this is SD/MMC device */
/* finish identification mode */
rc = sdcc_init_memory_device(sdcc_pdev);
if (SDCC_NO_ERROR != rc)
{
DPRINTF(("Failed to initialize the card.\n"));
sdcc_pdev->errno = rc;
(void) sdcc_handle_close(ret_handle);
ret_handle = NULL;
break;
}
if (FALSE == sdcc_pdev->sdhci_mode)
{
HAL_sdcc_flowcontrol (driveno, TRUE);
}
/* get memory device info */
rc = sdcc_get_memory_info(sdcc_pdev);
if (SDCC_NO_ERROR != rc)
{
DPRINTF(("Failed to get memory card info.\n"));
sdcc_pdev->errno = rc;
(void) sdcc_handle_close(ret_handle);
ret_handle = NULL;
break;
}
/* re-program the clock for data transfer */
sdcc_config_clk(sdcc_pdev, SDCC_DATA_TRANSFER_MODE);
/* config device for data transfer */
rc = sdcc_config_memory_device(sdcc_pdev);
if (SDCC_NO_ERROR == rc)
{
sdcc_pdev->host_state = SDCC_HOST_TRAN;
// set to true if card is removed / reinserted
sdcc_pdata->slot_state_changed = FALSE;
}
else
{
sdcc_pdev->errno = rc;
sdcc_pdev->card_type = SDCC_CARD_UNKNOWN;
(void) sdcc_handle_close(ret_handle);
ret_handle = NULL;
}
}
while (0);
return ret_handle;
}
/******************************************************************************
* Name: sdcc_handle_find_card
*
* Description:
* This function finds out the card type specified in handle parameter.
*
* Arguments:
* handle [IN] : a pointer to the SDCC device that was returned from
* sdcc_handle_open()
*
* Returns:
* card type that indicates if device is SD, MMC, SDIO, or unknown
*
******************************************************************************/
SDCC_CARD_TYPE sdcc_handle_find_card( struct sdcc_device *handle )
{
SDCC_CARD_TYPE card_type = SDCC_CARD_UNKNOWN;
uint32 driveno = 0;
printLog("sdcc_handle_find_card --zyk");
driveno = SDCC_HANDLE_GET_DRIVENO( handle );
if (!SDCC_DRIVENO_IS_VALID( driveno ))
{
DPRINTF(("Invalid Drive Number:%d", driveno));
return SDCC_CARD_UNKNOWN;
}
printLog("sdcc_handle_find_card --zyk 167");
/* set the power mode to 'power on' */
HAL_sdcc_SetPowerState( driveno, HAL_SDCC_POWER_ON );
if (FALSE == handle->hdev->sdhci_mode)
{
/* enable the clock */
HAL_sdcc_BusClockEnable( driveno, TRUE );
/* disable powersave on bus clock while supply voltage ramps up */
HAL_sdcc_PowerSave( driveno, FALSE );
sdcc_osal_sleep( SDCC_SUPPLY_RAMP_UP_TIME_MS );
HAL_sdcc_PowerSave( driveno, TRUE );
/* Enable Feedback Clock */
sdcc_osal_sleep( SDCC_SUPPLY_RAMP_UP_TIME_MS );
HAL_sdcc_SetClockEdge( driveno, HAL_SDCC_CLOCK_EDGE_FEEDBACK );
}
else
{
HAL_sdhci_PowerSave( driveno, FALSE);
sdcc_osal_sleep( SDCC_SUPPLY_RAMP_UP_TIME_MS );
HAL_sdhci_PowerSave( driveno, TRUE);
}
/* lower the clock to < 400KHz for card identification */
sdcc_config_clk( handle->hdev, SDCC_IDENTIFICATION_MODE );
/* look for memory card */
printLog("sdcc_handle_find_card --zyk 194");
if (sdcc_bsp_get_slot_type(driveno) & SDCC_BSP_EMBEDDED_MEM_SLOT)
{
/* look for MMC device */
card_type = sdcc_find_mmc_device( handle );
}
else
{
/* look for SD device */
card_type = sdcc_find_sd_device( handle );
}
printLog("sdcc_handle_find_card --zyk %d",card_type);
return card_type;
}
/******************************************************************************
* Name: sdcc_find_mmc_device
*
* Description:
* This function looks for the MMC device of the specified driveno.
*
* Parameters:
* handle [IN] : a pointer to the SDCC device
*
* Returns:
* card type that indicates if device is MMC or unknown
*
******************************************************************************/
SDCC_CARD_TYPE
sdcc_find_mmc_device ( struct sdcc_device *handle )
{
SDCC_CARD_TYPE card_type = SDCC_CARD_UNKNOWN;
sdcc_dev_type *sdcc_pdev = handle->hdev;
SDCC_STATUS rc = SDCC_ERR_UNKNOWN;
sdcc_cmd_type sdcc_cmd;
uint32 i;
printLog("sdcc_find_mmc_device --zyk");
/* CMD0: reset card first */
sdcc_cmd.cmd = SD_CMD0_GO_IDLE_STATE;
sdcc_cmd.cmd_arg = SDCC_CMD_ARGU_NULL;
sdcc_cmd.resp_type = SDCC_RESP_NONE;
sdcc_cmd.prog_scan = 0;
sdcc_cmd.flags = SDCC_TRANSFER_FLAG_IS_CMD_ONLY;
(void) sdcc_command (sdcc_pdev, &sdcc_cmd);
/* continue on to look for MMC card */
for ( i = 0; i < SDCC_MMC_DETECT_MAX_RETRIES; i++ )
{
/* CMD1: sent voltage to be used */
sdcc_cmd.cmd = SD_CMD1_SEND_OP_COND;
sdcc_cmd.cmd_arg = SDCC_MMC_HCS_NEGOTIATE_OCR;
sdcc_cmd.resp_type = SDCC_RESP_SHORT;
sdcc_cmd.prog_scan = 0;
sdcc_cmd.flags = SDCC_TRANSFER_FLAG_IS_CMD_ONLY;
rc = sdcc_command( sdcc_pdev, &sdcc_cmd );
if ( SDCC_NO_ERROR != rc )
{
/* exit the for-loop for MMC card detection if there is issue in */
/* sending the command to the card */
break;
}
else if ( sdcc_cmd.resp[0] & SDCC_DEVICE_RDY )
{
/* access mode validation: */
/* byte access mode represents <= 2GB card size */
/* sector access mode represents > 2GB card size, however */
/* this needs to be reconfirmed by reading SEC_COUNT */
/* in EXT_CSD */
/* >2GB: [30:29] = 1,0 */
if ( ((sdcc_cmd.resp[0] >> 30) & 1) &&
!((sdcc_cmd.resp[0] >> 29) & 1) )
{
card_type = SDCC_CARD_MMCHC;
DPRINTF(("Found MMCHC card after %dth retry\n", i));
}
else
{
card_type = SDCC_CARD_MMC;
DPRINTF(("Found MMC card after %dth retry\n", i));
}
return card_type;
}
sdcc_osal_sleep( SDCC_MMC_DETECT_BUSY_RETRY_Interval );
}
return card_type;
}
/******************************************************************************
* Name: sdcc_command
*
* Description:
* This is a wrAPPer function for sending the command and poll
* the status. It decides whether to use the Qualcomm or standard
* Host Controller interface to communicate with the memory device.
*
* Arguments:
* sdcc_pdev [IN] : pointer to device type
* sdcc_cmd [IN] : pointer to command data structure
*
* Returns:
* Returns error code
*
******************************************************************************/
SDCC_STATUS
sdcc_command(sdcc_dev_type *sdcc_pdev, sdcc_cmd_type *sdcc_cmd)
{
printLog("sdcc_command _entry cmd:%d",(uint32)sdcc_cmd->cmd);
if ((NULL == sdcc_pdev) || (NULL == sdcc_cmd))
{
//printLog("SDCC_ERR_INVALID_PARAM return");
return SDCC_ERR_INVALID_PARAM;
}
if (TRUE == sdcc_pdev->sdhci_mode)
{
printLog("eMMC cmd sdhci_mode");
return sdcc_command_sdhci_mode(sdcc_pdev, sdcc_cmd);
}
else
{
printLog("eMMC cmd qc_mode");
return sdcc_command_qc_mode(sdcc_pdev, sdcc_cmd);
}
}
相关阅读
现在我们要知道我们的店铺参加活动不容易,所以我们在参加一个活动之前一定要做好万全的准备,其中包括对活动流程的安排,一起来看一下
iOS开发者众多,但并不是所有的开发者都对账号申请,证书配置这些问题都清楚,毕竟不是所有开发者都能够经历这个环节,多数情况下是进公
笔者之前讲了很多金融知识以及金融软件产品的设计要点,今天接着来聊一聊“银行授信”,笔者将通过银行授信流程的剖析、额度申请、审
流程图的制作可以套用模板,这样对框架结构的搭建就节约了很多时间,那在今天小编要给大家分享最新绘制的流程图模板,希望大家喜欢。
潮电街,可能有不少商家对此都是比较不熟悉的。其简单来说,就是一个主要销售智能类商品的网上商城,现阶段的淘宝的新的核心市场。那么