new file mode 100644
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: autotimerfunc.c
+ *
+ * Abstract: This source file used to implemnt auto timer functions
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 8/25/2014 Creation Peter.Guo
+ */
+
+#include "../include/basic.h"
+#include "../include/cardapi.h"
+#include "../include/host.h"
+#include "../include/hostapi.h"
+#include "../include/debug.h"
+#include "../include/util.h"
+
+/*
+ * Function Name: autotimer_clear
+ * Abstract: This Function is used to clear timer tick
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ *
+ */
+static void autotimer_clear(bht_dev_ext_t *pdx)
+{
+ pdx->auto_timer.auto_dmt_tick = 0;
+ pdx->auto_timer.auto_poweroff_tick = 0;
+ pdx->auto_timer.auto_cmd12_tick = 0;
+ pdx->auto_timer.last_tick = 0;
+ pdx->auto_timer.auto_led_off_tick = 0;
+}
+
+/*
+ * Function Name: func_timer_callback
+ * Abstract: This Function is used to calculate timer tick
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ *
+ *
+ * Notes:
+ *
+ * so giving the routine another name requires you to modify the build tools.
+ */
+
+void func_timer_callback(bht_dev_ext_t *pdx)
+{
+ u32 cur_time, interval;
+ bool event = FALSE;
+
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "Enter %s\n",
+ __func__);
+ if (pdx->auto_timer.enable == FALSE || pdx->auto_timer.cancel)
+ goto exit;
+
+ if (pdx->auto_timer.stop) {
+ autotimer_clear(pdx);
+ goto exit;
+ }
+
+ /* If card not workable don't use timer */
+ if (pdx->card.card_present == FALSE)
+ goto exit;
+ if (pdx->card.card_type == CARD_NONE
+ || pdx->card.card_type == CARD_ERROR)
+ goto exit;
+ if (pdx->card.state == CARD_STATE_POWEROFF)
+ goto exit;
+ /* If rtd3 entered not do below steps */
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0,
+ "auto timer really work\n");
+
+ /* calculate the real interval */
+ cur_time = os_get_cur_tick();
+ if (pdx->auto_timer.last_tick == 0) {
+ pdx->auto_timer.last_tick = cur_time;
+ interval = AUTO_TIMER_TICK;
+ } else {
+ interval = cur_time - pdx->auto_timer.last_tick;
+ pdx->auto_timer.last_tick = cur_time;
+ }
+
+ /* update and check timeout for each tick */
+ if (pdx->auto_timer.auto_cmd12_enable && pdx->card.has_built_inf) {
+ pdx->auto_timer.auto_cmd12_tick += interval;
+ if (pdx->auto_timer.auto_cmd12_tick >=
+ pdx->auto_timer.auto_cmd12_time)
+ event = TRUE;
+ }
+
+ if (pdx->auto_timer.auto_dmt_enable && pdx->card.card_type == CARD_UHS2
+ && pdx->card.state == CARD_STATE_WORKING) {
+ pdx->auto_timer.auto_dmt_tick += interval;
+ if (pdx->auto_timer.auto_dmt_tick >=
+ pdx->auto_timer.auto_dmt_time)
+ event = TRUE;
+ }
+
+ if (pdx->auto_timer.auto_led_off_enable && (pdx->host.led_on)) {
+ pdx->auto_timer.auto_led_off_tick += interval;
+ if (pdx->auto_timer.auto_led_off_tick >=
+ pdx->auto_timer.auto_led_off_time)
+ event = TRUE;
+ }
+
+ if (pdx->auto_timer.auto_poweroff_enable) {
+ pdx->auto_timer.auto_poweroff_tick += interval;
+ if (pdx->auto_timer.auto_poweroff_tick >=
+ pdx->auto_timer.auto_poweroff_time)
+ event = TRUE;
+ }
+
+ if (pdx->auto_timer.cancel || pdx->auto_timer.stop)
+ goto exit;
+
+ if (event) {
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0,
+ "auto timer set event\n");
+
+#if CFG_OS_LINUX
+ os_set_event(&pdx->os, EVENT_AUTO_TIMER);
+#else
+ os_set_event(pdx, &pdx->os, EVENT_TASK_OCCUR, EVENT_AUTO_TIMER);
+#endif
+
+ }
+ os_start_timer(pdx, &pdx->os, TIMER_AUTO, AUTO_TIMER_TICK);
+
+exit:
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "Exit %s\n",
+ __func__);
+}
+
+/*
+ * Function Name: func_autotimer_init
+ * Abstract: This Function is used to init timer function variables
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ *
+ *
+ * Notes:
+ *
+ * so giving the routine another name requires you to modify the build tools.
+ */
+
+void func_autotimer_init(bht_dev_ext_t *pdx)
+{
+ cfg_item_t *cfg = pdx->cfg;
+
+ os_memset(&pdx->auto_timer, 0, sizeof(pdx->auto_timer));
+
+ pdx->auto_timer.auto_dmt_time =
+ cfg->timer_item.auto_dormant_timer.time_ms;
+ pdx->auto_timer.auto_dmt_enable =
+ (bool)cfg->timer_item.auto_dormant_timer.enable_dmt_func;
+ pdx->auto_timer.enable_hibernate =
+ (bool)cfg->timer_item.auto_dormant_timer.enable_hbr;
+
+ pdx->auto_timer.auto_poweroff_enable = FALSE;
+ pdx->auto_timer.auto_poweroff_time = 10 * 1000;
+
+ pdx->auto_timer.auto_led_off_enable = pdx->host.feature.hw_led_fix;
+ /* led off set to 1s */
+ pdx->auto_timer.auto_led_off_time = 1000;
+
+ pdx->auto_timer.enable = pdx->auto_timer.auto_cmd12_enable |
+ pdx->auto_timer.auto_poweroff_enable |
+ pdx->auto_timer.auto_dmt_enable |
+ pdx->auto_timer.auto_led_off_enable;
+
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "Autopower off enable=%d time=%dms\n",
+ pdx->auto_timer.auto_poweroff_enable,
+ pdx->auto_timer.auto_poweroff_time);
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "Autodmt=%d time=%dms bhrb=%d\n",
+ pdx->auto_timer.auto_dmt_enable, pdx->auto_timer.auto_dmt_time,
+ pdx->auto_timer.enable_hibernate);
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "AutoStopInf enable=%d time=%dms\n",
+ pdx->auto_timer.auto_cmd12_enable,
+ pdx->auto_timer.auto_cmd12_time);
+}
+
+/*
+ * Function Name: func_timer_thread
+ * Abstract: This Function is used to calculate timer tick
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ *
+ *
+ * Notes:
+ *
+ * This function is called by thread to do real job
+ */
+void func_timer_thread(bht_dev_ext_t *pdx)
+{
+ int busy = 0;
+
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "Enter %s\n",
+ __func__);
+
+ if (pdx->auto_timer.enable == FALSE || pdx->auto_timer.cancel
+ || pdx->auto_timer.stop)
+ goto clear;
+
+ /* If card not workable don't use timer */
+ if (pdx->card.card_present == FALSE)
+ goto clear;
+ if (pdx->card.card_type == CARD_NONE
+ || pdx->card.card_type == CARD_ERROR)
+ goto clear;
+ if (pdx->card.state == CARD_STATE_POWEROFF)
+ goto clear;
+
+ /* If rtd3 entered not call below function */
+
+ if (pdx->auto_timer.auto_poweroff_enable) {
+ if (pdx->auto_timer.auto_poweroff_tick >=
+ pdx->auto_timer.auto_poweroff_time) {
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_CARD_OPS, 0,
+ "auto poweroff\n");
+ if (busy == 0) {
+ os_set_dev_busy(pdx);
+ busy = 1;
+ }
+ card_power_off(&pdx->card, FALSE);
+ autotimer_clear(pdx);
+ goto next;
+ }
+ }
+
+ if (pdx->auto_timer.auto_cmd12_enable && pdx->card.has_built_inf) {
+ if (pdx->auto_timer.auto_cmd12_tick >=
+ pdx->auto_timer.auto_cmd12_time) {
+ if (busy == 0) {
+ os_set_dev_busy(pdx);
+ busy = 1;
+ }
+ pdx->auto_timer.auto_cmd12_tick = 0;
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_CARD_OPS, 0,
+ "auto stop infinite\n");
+ card_stop_infinite(&pdx->card, TRUE, NULL);
+ }
+ }
+
+ if (pdx->auto_timer.auto_dmt_enable && pdx->card.card_type == CARD_UHS2
+ && pdx->card.state == CARD_STATE_WORKING) {
+ if (pdx->auto_timer.auto_dmt_tick >=
+ pdx->auto_timer.auto_dmt_time) {
+ if (busy == 0) {
+ os_set_dev_busy(pdx);
+ busy = 1;
+ }
+ pdx->auto_timer.auto_dmt_tick = 0;
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_CARD_OPS, 0,
+ "auto enter sleep\n");
+ card_enter_sleep(&pdx->card, TRUE,
+ pdx->auto_timer.enable_hibernate);
+ }
+ }
+
+ if (pdx->auto_timer.auto_led_off_enable && (pdx->host.led_on)) {
+ if (pdx->auto_timer.auto_led_off_tick >=
+ pdx->auto_timer.auto_led_off_time) {
+ if (busy == 0) {
+ os_set_dev_busy(pdx);
+ busy = 1;
+ }
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_CARD_OPS, 0,
+ "auto led off\n");
+ pdx->auto_timer.auto_led_off_tick = 0;
+ host_led_ctl(&pdx->host, FALSE);
+ }
+ }
+
+next:
+ if (busy)
+ os_set_dev_idle(pdx);
+ goto exit;
+
+clear:
+ autotimer_clear(pdx);
+
+exit:
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "Exit %s\n",
+ __func__);
+}
+
+void func_autotimer_stop(bht_dev_ext_t *pdx)
+{
+ if (pdx->auto_timer.enable == FALSE)
+ return;
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "stop autotimer\n",
+ __func__);
+ pdx->auto_timer.stop = 1;
+ os_stop_timer(pdx, &pdx->os, TIMER_AUTO);
+ autotimer_clear(pdx);
+
+}
+
+void func_autotimer_start(bht_dev_ext_t *pdx)
+{
+ if (pdx->auto_timer.enable == FALSE || pdx->auto_timer.cancel)
+ return;
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "start autotimer\n",
+ __func__);
+ autotimer_clear(pdx);
+ pdx->auto_timer.stop = 0;
+ os_start_timer(pdx, &pdx->os, TIMER_AUTO, AUTO_TIMER_TICK);
+}
+
+void func_autotimer_cancel(bht_dev_ext_t *pdx)
+{
+ if (pdx->auto_timer.enable == FALSE || pdx->auto_timer.cancel)
+ return;
+ DbgInfo(MODULE_AUTOTIMER, FEATURE_TIMER_TRACE, 0, "cancel autotimer\n",
+ __func__);
+ pdx->auto_timer.cancel = 1;
+ os_cancel_timer(pdx, &pdx->os, TIMER_AUTO);
+ autotimer_clear(pdx);
+}
new file mode 100644
@@ -0,0 +1,1132 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: cfgmng.c
+ *
+ * Abstract: This source file used to mangage dynamic configuration
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 8/25/2014 Creation Peter.Guo
+ */
+
+#include "../include/basic.h"
+#include "../include/debug.h"
+#include "../include/util.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define DMDN_TYPE_CNT 4
+
+/*
+ * 0 1 2 3
+ * UHS2 UHS2M1 UHS2M2 UHS2M3
+ *
+ * 4 5 6 7
+ * SD200 SD200M1 SD200M2 SD200M3
+ *
+ * 8 9 10 11
+ * SD100M SD100M1 SD100M2 SD100M3
+ *
+ * 12 13 14 15 16
+ * SD75M DDR50 50MZ 25MZ 400K
+ *
+ * 17
+ * DDR50InputTuning
+ *
+ */
+
+/* global definition about configuration structure */
+cfg_item_t g_cfg[SUPPORT_CHIP_COUNT][2];
+
+u32 g_dmdn_divider_tbl[DMDN_TYPE_CNT][MAX_FREQ_SUPP] = {
+ /* SDS, Fujin2 */
+ {
+ /* UHSII */
+ 0x1f340002, 0x18230002, 0x181f0002, 0x181b0002,
+ /* SDR104=208M */
+ 0x1f340000, 0x18230000, 0x181f0000, 0x181b0000,
+ /* 100M */
+ 0x18270001, 0x18230001, 0x181F0001, 0x181B0001,
+ 0x181d0001, 0x18270002, 0x18270002, 0x18270004, 0x182700FA,
+ 0xFFFF0001,
+ /* 200M ~ 140M */
+ 0x18270000, 0x18230000, 0x181f0000, 0x181b0000,
+ /* 50M 25M 400K */
+ 0x18270002, 0x18270002, 0x18270004, 0x182700fa },
+
+ /* Seabird, SeaEagle */
+ {
+ /* UHSII */
+ 0x2c280002, 0x27140002, 0x2B1C0002, 0x2C1A0002,
+ /* SDR104=200M */
+ 0x2c280000, 0x27140000, 0x2B1C0000, 0x2c1A0000,
+ /* 100M */
+ 0x25100001, 0x27140001, 0x2B1C0001, 0x2C1A0001,
+ 0x250C0001, 0x25100002, 0x25100002, 0x25100004, 0x251000FA,
+ 0x35100001,
+ /* 200M ~ 140M */
+ 0x25100000, 0x27140000, 0x2b1c0000, 0x2c1a0000,
+ /* 50M 25M 400K */
+ 0x25100002, 0x25100002, 0x25100004, 0x251000fa },
+
+ /* SeaEagle2 */
+ {
+ /* UHSII */
+ 0x2c280002, 0x27140002, 0x2B1C0002, 0x2c1a0002,
+ /* SDR104=208M */
+ 0x2c280000, 0x27140000, 0x2B1C0000, 0x2c1a0000,
+ /* 100M */
+ 0x25100001, 0x27140001, 0x2b1c0001, 0x2c1a0001,
+ 0x250c0001, 0x25100002, 0x25100002, 0x25100004, 0x251000fa,
+ 0x35100001,
+ /* 200M ~ 140M */
+ 0x25100000, 0x27140000, 0x2b1c0000, 0x2c1a0000,
+ /* 50M 25M 400K */
+ 0x25100002, 0x25100002, 0x25100004, 0x251000fa },
+ /* GG8 */
+ {
+ /* UHSII */
+ 0x2c500002, 0x251D0002, 0x251A0002, 0x25160002,
+ /* SDR104=208M */
+ 0x2c500000, 0x251D0000, 0x251A0000, 0x25160000,
+ /* 100M */
+ 0x25200001, 0x251D0001, 0x251A0001, 0x25160001,
+ 0x25160001, 0x25200002, 0x25200002, 0x25200004, 0x252000fa,
+ 0x25200002,
+ /* 200M ~ 140M */
+ 0x25200000, 0x251D0000, 0x251A0001, 0x25160000,
+ /* 50M 25M 400K */
+ 0x25200002, 0x25200002, 0x25200004, 0x252000fa,
+ /* DDR200 */
+ 0x25200000, 0x251D0000, 0x251A0000, 0x25160000,
+ /* DDR225, 225MHz, 200MHz */
+ 0x25240000, 0x25200000, 0x251D0000, 0x251A0000 }
+};
+
+#if (0)
+/*
+ * UHS2 UHS2M1 UHS2M2 UHS2M3
+ * SD200 SD200M1 SD200M2 SD200M3
+ * SD100M SD100M1 SD100M2 SD100M3
+ * SD75M DDR50 50MZ 25MZ 400K
+ */
+u32 g_dmdn_divider_tbl_fpga[MAX_FREQ_SUPP] = {
+ /* 208/4 187.5/4 166.7/4 145.8/4 UHSII */
+ 0x05030002, 0x06040002, 0x08060002, 0x07060002,
+ /* 200/2 180/2 160.7/2 140.6/2 SDR104 */
+ 0x08050001, 0x0A070001, 0x09070001, 0x09080001,
+ /* 100 90 80.4 70.3 100M */
+ 0x08050001, 0x0A070001, 0x09070001, 0x09080001,
+ /* 75 50 50 25 400K */
+ 0x06050001, 0x08050002, 0x08050002, 0x08050004, 0x080500FA
+};
+#endif
+
+/*
+ * UHS2 UHS2M1 UHS2M2 UHS2M3
+ * SD200 SD200M1 SD200M2 SD200M3
+ * SD100M SD100M1 SD100M2 SD100M3
+ * SD75M DDR50 50MZ 25MZ 400K
+ */
+u32 g_dmdn_divider_tbl_fpga[MAX_FREQ_SUPP] = {
+ /* 208/4 187.5/4 166.7/4 145.8/4 UHSII */
+ 0x05030002, 0x05030002, 0x05030002, 0x05030002,
+ /* 200/2 180/2 160.7/2 140.6/2 SDR104 */
+ 0x08050001, 0x08050002, 0x08050003, 0x08050001,
+ /* 100 90 80.4 70.3 100M */
+ 0x08050001, 0x08050001, 0x08050001, 0x08050001,
+ /* 75 50 50 25 400K */
+ 0x08050002, 0x08050002, 0x08050002, 0x08050004, 0x080500FA,
+ /* DDR50 Inputtuning */
+ 0x080a0001,
+ /* use for eMMC */
+ 0x08050001, 0x08050001, 0x08050001, 0x08050001, 0x08050002, 0x08050002,
+ 0x08050004, 0x080500FA,
+ /* 200/2 180/2 160.7/2 140.6/2 DDR200 */
+ 0x08050001, 0x08050001, 0x08050001, 0x08050001
+};
+
+static void cfg_parse(cfg_item_t *cfg, e_chip_type chip_type);
+static void cfg_set_default_val(cfg_item_t *cfg, e_chip_type type);
+
+void cfgmng_init_chipcfg(e_chip_type chip_type, cfg_item_t *cfg, bool reinit)
+{
+ cfg_driver_item_t driver_item;
+ cfg_psd_mode_t psd_mode;
+ u32 bit64 = 0;
+
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, NOT_TO_RAM,
+ "========================================\n");
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, NOT_TO_RAM,
+ "ChipType=%d, boot_flag = %d\n", chip_type, cfg->boot_flag);
+
+ if (reinit) {
+ driver_item = cfg->driver_item;
+ psd_mode = cfg->feature_item.psd_mode;
+ bit64 =
+ cfg->host_item.test_dma_mode_setting.enable_dma_64bit_address;
+ }
+ cfg_set_default_val(cfg, chip_type);
+ os_cfg_load(cfg, chip_type);
+ cfg_parse(cfg, chip_type);
+ if (reinit) {
+ cfg->driver_item = driver_item;
+ cfg->feature_item.psd_mode = psd_mode;
+ cfg->host_item.test_dma_mode_setting.enable_dma_64bit_address =
+ bit64 ? 1 : 0;
+ }
+}
+
+/*
+ *
+ * Function Name: cfgmng_init
+ *
+ * Abstract:
+ * 1. Read different chip type registry information
+ * 2. parse reigstry information
+ *
+ * Input:
+ * None
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: DriverEntry
+ */
+void cfgmng_init(void)
+{
+ u8 i = 0;
+ e_chip_type chip_type;
+
+ for (i = 0; i < SUPPORT_CHIP_COUNT; i++) {
+ /* for non-boot cfg */
+
+ cfg_item_t *cfg = &g_cfg[i][0];
+
+ chip_type = (e_chip_type) i;
+ cfg->boot_flag = FALSE;
+ cfgmng_init_chipcfg(chip_type, cfg, FALSE);
+
+ /* for boot config */
+ cfg = &g_cfg[i][1];
+ chip_type = (e_chip_type) i;
+ cfg->boot_flag = TRUE;
+
+ cfgmng_init_chipcfg(chip_type, cfg, FALSE);
+
+ }
+}
+
+/*
+ *
+ * Function Name: cfgmng_get
+ *
+ * Abstract:
+ * 1. transfer the (cfg_item_t *) structure
+ *
+ * Input:
+ * e_chip_type chip_type;
+ *
+ * Output:
+ * pointer to cfg_item_t
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller:
+ */
+cfg_item_t *cfgmng_get(void *pdx, e_chip_type chip_type, bool boot)
+{
+ int i = boot ? 1 : 0;
+ cfg_item_t *cfg = &g_cfg[(u32) chip_type][i];
+ u32 *tbl = NULL;
+
+ switch ((u32) chip_type) {
+ case CHIP_SDS0:
+ case CHIP_SDS1:
+ case CHIP_FUJIN2:
+ tbl = &g_dmdn_divider_tbl[0][0];
+ break;
+
+ case CHIP_SEABIRD:
+ case CHIP_SEAEAGLE:
+ tbl = &g_dmdn_divider_tbl[1][0];
+ break;
+ case CHIP_SEAEAGLE2:
+ tbl = &g_dmdn_divider_tbl[2][0];
+ break;
+ case CHIP_GG8:
+ case CHIP_ALBATROSS:
+ tbl = &g_dmdn_divider_tbl[3][0];
+ break;
+ }
+
+ if (cfg->fpga_item.fpga_ctrl.is_fpga_chip) {
+ tbl = g_dmdn_divider_tbl_fpga;
+ DbgInfo(MODULE_CFG_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "Use Dmdn table For FPGA\n");
+ }
+
+ if (tbl != NULL)
+ os_memcpy(cfg->dmdn_tbl, tbl, sizeof(g_dmdn_divider_tbl_fpga));
+
+ DbgInfo(MODULE_CFG_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "chip type =%d DMDN basetbl = %p realtbl=%p\n", chip_type,
+ &g_dmdn_divider_tbl[0][0], cfg->dmdn_tbl);
+ cfg_print_debug(cfg);
+ cfg->pcr_item.cnt = 0;
+
+ /* clear pcr cfg */
+ os_memset(&cfg->pcr_item, 0, sizeof(cfg_pcr_item_t));
+
+ os_enum_reg_cfg(cfg, chip_type, (byte *) "\\pcr", os_load_pcr_cb);
+ os_enum_reg_cfg(cfg, chip_type, (byte *) "\\dmdn", os_load_dmdn_cb);
+
+ return cfg;
+}
+
+/*
+ *
+ * Function Name: print_registry_value
+ *
+ * Abstract:
+ * 1. print the registry name and it's value
+ *
+ * Input:
+ * PVOID cfg_item: Pointer to the registry configuration structure
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: registry_load
+ */
+void cfg_print_debug(PVOID cfg_item)
+{
+#if DBG || _DEBUG
+ cfg_item_t *cfg = (cfg_item_t *) cfg_item;
+
+ cfg_card_item_t card_item = cfg->card_item;
+ cfg_host_item_t host_item = cfg->host_item;
+
+ cfg_feature_item_t feature_item = cfg->feature_item;
+ cfg_timer_item_t timer_item = cfg->timer_item;
+ cfg_timeout_item_t timeout_item = cfg->timeout_item;
+
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "-------------Registry item Check Start--------------------\n");
+
+ /* -------------------- card item name as below------------------ */
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "sd_card_mode_dis: 0x%08x\n",
+ card_item.sd_card_mode_dis);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_max_access_mode: 0x%08x\n",
+ card_item.test_max_access_mode);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_driver_strength_sel: 0x%08x\n",
+ card_item.test_driver_strength_sel);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_max_power_limit: 0x%08x\n",
+ card_item.test_max_power_limit);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "mmc_mode_dis: 0x%08x\n",
+ card_item.mmc_mode_dis);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "emmc_mode: 0x%08x\n",
+ card_item.emmc_mode);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "sd7_sdmode_switch_control: 0x%08x\n",
+ card_item.sd7_sdmode_switch_control);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_uhs2_setting: 0x%08x\n",
+ card_item.uhs2_setting);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_uhs2_setting2: 0x%08x\n",
+ card_item.test_uhs2_setting2);
+
+ /* -------------------- host item name as below ------------------ */
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_dma_mode_setting: 0x%08x\n",
+ host_item.test_dma_mode_setting);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_infinite_transfer_mode: 0x%08x\n",
+ host_item.test_infinite_transfer_mode);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_sdma_boun_setting: 0x%08x\n",
+ host_item.test_sdma_boundary);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_tag_queue_capability: 0x%08x\n",
+ host_item.test_tag_queue_capability);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_ocb_ctrl: 0x%08x\n",
+ host_item.test_ocb_ctrl);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "bios_l1_substate: 0x%08x\n",
+ host_item.bios_l1_substate);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "vdd_power_source_item: 0x%08x\n",
+ host_item.vdd_power_source_item);
+
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "host_drive_strength: 0x%08x\n",
+ host_item.host_drive_strength);
+
+ /* -------------------- issue fix item name as below------------------ */
+
+ /* -------------------- feature item name as below-------------------- */
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "psd_mode: 0x%08x\n",
+ feature_item.psd_mode);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "pcie_wake_setting: 0x%08x\n",
+ feature_item.pcie_wake_setting);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_main_ldo_setting: 0x%08x\n",
+ feature_item.test_main_ldo_setting);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "output_tuning_item: 0x%08x\n",
+ feature_item.output_tuning_item);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "hsmux_vcme_enable: 0x%08x\n",
+ feature_item.hsmux_vcme_enable);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "refclk_stable_detection_counter1: 0x%08x\n",
+ feature_item.refclk_stable_detection_counter1);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "refclk_stable_detection_counter2: 0x%08x\n",
+ feature_item.refclk_stable_detection_counter2);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "refclk_stable_detection_counter3: 0x%08x\n",
+ feature_item.refclk_stable_detection_counter3);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "auto_detect_refclk_counter_range_ctl:0x%08x\n",
+ feature_item.auto_detect_refclk_counter_range_ctl);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "l1_enter_exit_logic_ctl: 0x%08x\n",
+ feature_item.l1_enter_exit_logic_ctl);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "pcie_phy_amplitude_adjust: 0x%08x\n",
+ feature_item.pcie_phy_amplitude_adjust);
+
+ /* -------------------- timer item name as below------------------ */
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "auto_sleep_control: 0x%08x\n",
+ timer_item.auto_sleep_control);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "auto_dormant_timer: 0x%08x\n",
+ timer_item.auto_dormant_timer);
+
+ /* -------------------- timeout item name as below------------------ */
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "power_wait_time: 0x%08x\n",
+ timeout_item.power_wait_time);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_write_data_timeout: 0x%08x\n",
+ timeout_item.test_write_data_timeout);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_read_data_timeout: 0x%08x\n",
+ timeout_item.test_read_data_timeout);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_non_data_timeout: 0x%08x\n",
+ timeout_item.test_non_data_timeout);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_r1b_data_timeout: 0x%08x\n",
+ timeout_item.test_r1b_data_timeout);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "test_card_init_timeout: 0x%08x\n",
+ timeout_item.test_card_init_timeout);
+
+ /* -------------------- fpga item name as below------------------ */
+
+ /* -------------------- driver item name as below------------------ */
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "driver item: 0x%08x\n",
+ cfg->driver_item);
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, 0,
+ "-------------Registry item Check End--------------------\n");
+#endif
+}
+
+/*
+ *
+ * Function Name: fill_registry_struct
+ *
+ * Abstract:
+ * 1. call memcpy function to fill the registry structure
+ *
+ * Input:
+ * PVOID cfg_item: Pointer to single registry key address
+ * u32 cfg_def_val: the value of the single registry key structure
+ * u32 data_len: memcpy data length
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_set_default_val
+ */
+static void fill_registry_struct(PVOID cfg_item, u32 cfg_def_val, u32 data_len)
+{
+ u32 fill_registry_val = cfg_def_val;
+
+ os_memcpy(cfg_item, &fill_registry_val, data_len);
+}
+
+/*
+ *
+ * Function Name: cfg_set_default_val
+ *
+ * Abstract:
+ * 1. set the default value for every registry key
+ *
+ * Input:
+ * PVOID cfg_item: Pointer to the registry configuration structure
+ * e_chip_type type:
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfgmng_init
+ */
+static void cfg_set_default_val(cfg_item_t *cfg, e_chip_type type)
+{
+ u32 dma_mode, uhs2_setting, tag_queue_capability;
+
+ if (type == CHIP_SEAEAGLE2 || type == CHIP_GG8
+ || type == CHIP_ALBATROSS) {
+ dma_mode = 0x80000071;
+ tag_queue_capability = 0x80010010;
+ } else {
+#if GLOBAL_ENABLE_BOOT
+ tag_queue_capability = 0x80010020;
+#else
+ tag_queue_capability = 0x80010010;
+#endif
+#ifdef CFG_OS_LINUX
+ dma_mode = 0x80000071;
+#else
+ dma_mode = 0x80000006;
+#endif
+ }
+
+ if (type == CHIP_SEAEAGLE)
+ uhs2_setting = 0x97080112;
+ else if (type == CHIP_SEAEAGLE2)
+ uhs2_setting = 0x97400012;
+ else if (type == CHIP_GG8 || type == CHIP_ALBATROSS)
+ uhs2_setting = 0x97400012;
+ else
+ uhs2_setting = 0x97100112;
+
+ /* -------------------- card item name ------------------ * */
+ fill_registry_struct(&(cfg->card_item.sd_card_mode_dis), 0, 4);
+ fill_registry_struct(&cfg->card_item.test_max_access_mode, 0x80000003,
+ 4);
+ fill_registry_struct(&cfg->card_item.test_driver_strength_sel, 0, 4);
+ fill_registry_struct(&cfg->card_item.test_max_power_limit, 0x80000003,
+ 4);
+ fill_registry_struct(&cfg->card_item.mmc_mode_dis, 0, 4);
+#if GLOBAL_ENABLE_BOOT
+ fill_registry_struct(&cfg->card_item.emmc_mode, GLOBAL_EMMC_BOOT_CFG,
+ 4);
+#else
+ fill_registry_struct(&cfg->card_item.emmc_mode, 0, 4);
+#endif
+
+ fill_registry_struct(&cfg->card_item.sd7_sdmode_switch_control,
+ 0x00000030, 4);
+
+ fill_registry_struct(&cfg->card_item.uhs2_setting, uhs2_setting, 4);
+
+ fill_registry_struct(&cfg->card_item.test_uhs2_setting2, 0x80000006, 4);
+ /* ------------------- card item name end --------------------- */
+
+ /* -------------------- host item name ------------------ * */
+ fill_registry_struct(&cfg->host_item.test_dma_mode_setting, dma_mode,
+ 4);
+ if (type == CHIP_SDS0 || type == CHIP_SDS1)
+ fill_registry_struct(&cfg->host_item.test_infinite_transfer_mode,
+ 0x00000000, 4);
+ else
+ fill_registry_struct(&cfg->host_item.test_infinite_transfer_mode,
+ 0x8000000F, 4);
+ fill_registry_struct(&cfg->host_item.test_sdma_boundary, 0x20, 4);
+ fill_registry_struct(&cfg->host_item.test_tag_queue_capability,
+ tag_queue_capability, 4);
+ fill_registry_struct(&cfg->host_item.test_ocb_ctrl, 0x0, 4);
+ fill_registry_struct(&cfg->host_item.bios_l1_substate, 0x8000000f, 4);
+
+ fill_registry_struct(&cfg->host_item.vdd_power_source_item, 0x00091B05,
+ 4);
+ fill_registry_struct(&cfg->host_item.host_drive_strength, 0x00000000,
+ 4);
+ /* -------------------- host item name end-------------------- */
+
+#ifdef CFG_OS_LINUX
+ fill_registry_struct(&cfg->feature_item.psd_mode, 0x80000000, 4);
+#else
+ fill_registry_struct(&cfg->feature_item.psd_mode, 0x0a0a, 4);
+#endif
+
+ fill_registry_struct(&cfg->feature_item.psd_mode, 0x0, 4);
+
+ fill_registry_struct(&cfg->feature_item.test_main_ldo_setting, 0, 4);
+
+ fill_registry_struct(&cfg->feature_item.output_tuning_item, 0xC01F17DC,
+ 4);
+
+ /* -------------------- feature item name end------------------ */
+ fill_registry_struct(&cfg->feature_item.hsmux_vcme_enable, 0x00000000,
+ 4);
+
+ fill_registry_struct(&cfg->feature_item.refclk_stable_detection_counter1,
+ 0x00000003, 4);
+ fill_registry_struct(&cfg->feature_item.refclk_stable_detection_counter2,
+ 0x001e044c, 4);
+ fill_registry_struct(&cfg->feature_item.refclk_stable_detection_counter3,
+ 0x04b024b0, 4);
+ fill_registry_struct(&cfg->feature_item.auto_detect_refclk_counter_range_ctl,
+ 0x00000000, 4);
+ fill_registry_struct(&cfg->feature_item.l1_enter_exit_logic_ctl,
+ 0x00000000, 4);
+ fill_registry_struct(&cfg->feature_item.pcie_phy_amplitude_adjust,
+ 0x0000006a, 4);
+
+ fill_registry_struct(&cfg->timer_item.auto_sleep_control, 0, 4);
+ fill_registry_struct(&cfg->timer_item.auto_dormant_timer, 0x80000025,
+ 4);
+ /* -------------------- timer item name end------------------ * 44 */
+
+ /* -------------------- timeout item name------------------ */
+ fill_registry_struct(&cfg->timeout_item.power_wait_time, 0x0024000a, 4);
+
+ fill_registry_struct(&cfg->timeout_item.test_write_data_timeout,
+ 0x80001770, 4);
+ fill_registry_struct(&cfg->timeout_item.test_read_data_timeout,
+ 0x80001770, 4);
+ fill_registry_struct(&cfg->timeout_item.test_non_data_timeout,
+ 0x800003e8, 4);
+ fill_registry_struct(&cfg->timeout_item.test_r1b_data_timeout,
+ 0x80001194, 4);
+ fill_registry_struct(&cfg->timeout_item.test_card_init_timeout,
+ 0x800005dc, 4);
+ /* -------------------- timeout item name end------------------ * 58 */
+
+ /* -------------------- fpga item name----------------------- */
+ fill_registry_struct(&cfg->fpga_item.fpga_ctrl, 0x00000000, 4);
+ /* -------------------- fpga item name end ------------------ */
+
+ /* -------------------- driver item name------------------ * */
+ fill_registry_struct(&(cfg->driver_item), 0x8080000a, 4);
+
+ os_memset(&cfg->test_item, 0, sizeof(cfg->test_item));
+}
+
+/*
+ *
+ * Function Name: cfg_parse_card_item
+ *
+ * Abstract:
+ * 1. parse the card related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ * e_chip_type chip_type: chip type index
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_card_item(cfg_item_t *cfg, e_chip_type chip_type)
+{
+ cfg_card_item_t *card_item = &cfg->card_item;
+
+ /* sd_card_mode_dis */
+ if (card_item->sd_card_mode_dis.sd_mode_dis_enable == 0) {
+ card_item->sd_card_mode_dis.dis_sd30_card = 0;
+ card_item->sd_card_mode_dis.dis_sd40_card = 0;
+ }
+
+ /* max_access_mode */
+ if (card_item->test_max_access_mode.reserve == 0)
+ card_item->test_max_access_mode.value = 3;
+
+ /* max_power_limit */
+ if (card_item->test_max_power_limit.reserve == 0)
+ card_item->test_max_power_limit.value = 3;
+
+ /* emmc_mode */
+ if (card_item->emmc_mode.emmc_enable) {
+ if ((chip_type != CHIP_SEAEAGLE2) && (chip_type != CHIP_GG8)
+ && (chip_type != CHIP_ALBATROSS)) {
+ card_item->emmc_mode.enable_12_vccq = 0;
+ card_item->emmc_mode.enable_18_vcc = 0;
+ card_item->emmc_mode.enable_force_hs400 = 0;
+ }
+
+ if ((card_item->emmc_mode.dis_4bit_bus_width == 1) &&
+ (card_item->emmc_mode.dis_8bit_bus_width == 1)
+ ) {
+ card_item->emmc_mode.enable_ddr_mode = 0;
+ }
+
+ } else {
+ card_item->emmc_mode.dis_hs = 0;
+ card_item->emmc_mode.dis_4bit_bus_width = 0;
+ card_item->emmc_mode.dis_8bit_bus_width = 0;
+ card_item->emmc_mode.enable_ddr_mode = 0;
+ card_item->emmc_mode.enable_18_vccq = 0;
+ card_item->emmc_mode.enable_force_hs200 = 0;
+ card_item->emmc_mode.enable_12_vccq = 0;
+ card_item->emmc_mode.enable_18_vcc = 0;
+ card_item->emmc_mode.enable_force_hs400 = 0;
+ }
+
+ /* uhs2_setting */
+ if (card_item->uhs2_setting.reserve == 0) {
+ if (card_item->uhs2_setting.reserve_syn_dir_gap == 0) {
+ card_item->uhs2_setting.min_lss_syn = 2;
+ card_item->uhs2_setting.min_lss_dir = 1;
+ if (chip_type == CHIP_SEAEAGLE2 || chip_type == CHIP_GG8
+ || chip_type == CHIP_ALBATROSS)
+ card_item->uhs2_setting.min_data_gap_sel = 0;
+ else
+ card_item->uhs2_setting.min_data_gap_sel = 1;
+ }
+
+ if (card_item->uhs2_setting.reserve_nfcu == 0) {
+ if (chip_type == CHIP_SEAEAGLE)
+ card_item->uhs2_setting.max_nfcn_sel = 0x8;
+ else if (chip_type == CHIP_SEAEAGLE2
+ || chip_type == CHIP_GG8
+ || chip_type == CHIP_ALBATROSS)
+ card_item->uhs2_setting.max_nfcn_sel = 0x40;
+ else
+ card_item->uhs2_setting.max_nfcn_sel = 0x10;
+ }
+
+ /* half */
+ card_item->uhs2_setting.half_full_sel = 1;
+ /* fast mode */
+ card_item->uhs2_setting.fast_low_pwr_sel = 0;
+ /* range-B */
+ card_item->uhs2_setting.max_speed_range_sel = 1;
+ }
+
+ /* test_uhs2_setting2 */
+ if (card_item->test_uhs2_setting2.reserve == 0) {
+ card_item->test_uhs2_setting2.enable_power_off_vdd1 = 0;
+ card_item->test_uhs2_setting2.enable_full_reset_reinit = 1;
+ card_item->test_uhs2_setting2.enable_internal_clk_dormant = 1;
+ card_item->test_uhs2_setting2.disable_scramb_mode = 0;
+ }
+}
+
+/*
+ *
+ * Function Name: cfg_parse_host_item
+ *
+ * Abstract:
+ * 1. set the host cfg pointer
+ * 2. parse the host related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ * e_chip_type chip_type: chip type index
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_host_item(cfg_item_t *cfg, e_chip_type chip_type)
+{
+ cfg_host_item_t *host_item = &cfg->host_item;
+
+ /* dma_mode_setting */
+ if (host_item->test_dma_mode_setting.reserve == 0) {
+ /* adma2 */
+ host_item->test_dma_mode_setting.dma_mode = 1;
+ host_item->test_dma_mode_setting.enable_dma_26bit_len = 0;
+ host_item->test_dma_mode_setting.enable_dma_64bit_address = 0;
+ host_item->test_dma_mode_setting.enable_dma_32bit_blkcount = 0;
+ }
+
+ if ((chip_type != CHIP_SEAEAGLE2) && (chip_type != CHIP_GG8)
+ && (chip_type != CHIP_ALBATROSS)) {
+ /* only SE2 support merge */
+ host_item->test_tag_queue_capability.enable_srb_merge = 0;
+ }
+
+ /* infinite_transfer_mode */
+ if (host_item->test_infinite_transfer_mode.enable_inf == 0) {
+ host_item->test_infinite_transfer_mode.enable_legacy_inf = 0;
+ host_item->test_infinite_transfer_mode.enable_sd40_inf = 0;
+ host_item->test_infinite_transfer_mode.enable_mmc_inf = 0;
+ host_item->test_infinite_transfer_mode.enable_emmc_inf = 0;
+ }
+
+ /* sdma_boundary_len_setting */
+ if (host_item->test_sdma_boundary.reserve) {
+ /* SDMA */
+ if (host_item->test_dma_mode_setting.dma_mode == 0) {
+ if (host_item->test_sdma_boundary.value < 4)
+ host_item->test_sdma_boundary.value = 4;
+ }
+ } else {
+ host_item->test_sdma_boundary.value = 32;
+ }
+
+ /* tag_queue_capability */
+ if (host_item->test_tag_queue_capability.reserve == 0) {
+ /* 16 SRBs */
+ host_item->test_tag_queue_capability.max_srb = 0x10;
+ host_item->test_tag_queue_capability.enable_srb_merge = 0;
+ } else {
+ if (host_item->test_tag_queue_capability.max_srb == 0)
+ host_item->test_tag_queue_capability.max_srb = 0x10;
+ }
+
+ if (host_item->test_ocb_ctrl.sw_pwroff_en)
+ host_item->test_ocb_ctrl.int_check_en = 1;
+}
+
+/*
+ *
+ * Function Name: cfg_parse_issue_fix_item
+ *
+ * Abstract:
+ * 1. set the issue ifx item cfg pointer
+ * 2. parse the issue fix item related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_issue_fix_item(cfg_item_t *cfg)
+{
+
+}
+
+/*
+ *
+ * Function Name: cfg_parse_feature_item
+ *
+ * Abstract:
+ * 1. set the feature item cfg pointer
+ * 2. parse the feature item related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_feature_item(cfg_item_t *cfg, e_chip_type chip_type)
+{
+ if (chip_type != CHIP_SEAEAGLE && chip_type != CHIP_SEAEAGLE2
+ && chip_type != CHIP_GG8 && chip_type != CHIP_ALBATROSS) {
+ cfg->feature_item.output_tuning_item.enable_dll_divider = 0;
+ }
+}
+
+/*
+ *
+ * Function Name: cfg_parse_timeout_item
+ *
+ * Abstract:
+ * 1. set the timeout item cfg pointer
+ * 2. parse the timeout item related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_timeout_item(cfg_item_t *cfg)
+{
+ cfg_timeout_item_t *timeout_item = &cfg->timeout_item;
+
+ if (timeout_item->test_write_data_timeout.reserve == 0)
+ /* default:6s */
+ timeout_item->test_write_data_timeout.value = 6000;
+
+ if (timeout_item->test_read_data_timeout.reserve == 0)
+ /* default:6s */
+ timeout_item->test_read_data_timeout.value = 6000;
+
+ if (timeout_item->test_non_data_timeout.reserve == 0)
+ timeout_item->test_non_data_timeout.value = 1000;
+
+ if (timeout_item->test_r1b_data_timeout.reserve == 0)
+ timeout_item->test_r1b_data_timeout.value = 4500;
+
+ if (timeout_item->test_card_init_timeout.reserve == 0)
+ /* delay ACMD41/CMD1 return ready 1.5s (max) */
+ timeout_item->test_card_init_timeout.value = 1500;
+}
+
+/*
+ *
+ * Function Name: cfg_parse_fpga_item
+ *
+ * Abstract:
+ * 1. set the fpga item cfg pointer
+ * 2. parse the fpga item related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_fpga_item(cfg_item_t *cfg)
+{
+
+}
+
+/*
+ *
+ * Function Name: cfg_parse_driver_item
+ *
+ * Abstract:
+ * 1. set the driver item cfg pointer
+ * 2. parse the driver item related registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the config structure
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfg_parse
+ */
+static void cfg_parse_driver_item(cfg_item_t *cfg, e_chip_type chip_type)
+{
+ cfg_driver_item_t *driver_item = &cfg->driver_item;
+ /* driver item */
+ if (driver_item->reserve == 0) {
+
+ driver_item->dis_patch_ntfs_verify_rtd3 = FALSE;
+ driver_item->dis_patch_rtd3_idle_ref_cnt = FALSE;
+ driver_item->delay_for_failsafe_s3resume = 3;
+ driver_item->failsafe_en = 0;
+
+ }
+#if GLOBAL_ENABLE_BOOT
+ driver_item->removable = FALSE;
+ driver_item->removable_pnp = FALSE;
+#endif
+
+}
+
+/*
+ *
+ * Function Name: cfg_parse
+ *
+ * Abstract:
+ * 1. parse the registry information
+ * - If the registry valid bit is invalid state, then set the default configuration
+ *
+ * Input:
+ * cfg_item_t *cfg: Pointer to the cfg_item structure
+ * e_chip_type chip_type: chip type index
+ *
+ * Output:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Notes:
+ * Caller: cfgmng_init
+ */
+static void cfg_parse(cfg_item_t *cfg, e_chip_type chip_type)
+{
+ cfg_parse_card_item(cfg, chip_type);
+ cfg_parse_host_item(cfg, chip_type);
+ cfg_parse_issue_fix_item(cfg);
+ cfg_parse_feature_item(cfg, chip_type);
+ cfg_parse_timeout_item(cfg);
+ cfg_parse_fpga_item(cfg);
+ cfg_parse_driver_item(cfg, chip_type);
+
+}
+
+void cfg_dma_mode_dec(cfg_item_t *cfg, u32 dec_dma_mode)
+{
+ cfg->host_item.test_dma_mode_setting.dma_mode = dec_dma_mode;
+ DbgInfo(MODULE_CFG_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "Change DMA mode to 0x%08x\n", dec_dma_mode);
+}
+
+void cfg_dma_addr_range_dec(cfg_item_t *cfg, u32 dma_range)
+{
+ cfg->host_item.test_dma_mode_setting.enable_dma_64bit_address =
+ dma_range;
+ DbgInfo(MODULE_CFG_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "Change DMA addr(64bit Address) to %d\n", dma_range);
+}
+
+void cfgmng_update_dumpmode(cfg_item_t *cfg, e_chip_type chip_type)
+{
+ /* Use Non-Infinite adma2 mode for dump_mode */
+ cfg->host_item.test_dma_mode_setting.dma_mode = CFG_TRANS_MODE_ADMA2;
+
+ cfg->timer_item.auto_dormant_timer.enable_dmt_func = 0;
+
+ /* disable rtd3 */
+ cfg->feature_item.psd_mode.enable_rtd3 = FALSE;
+
+ /* disable output tuning */
+ cfg->feature_item.output_tuning_item.enable_dll = 0;
+ cfg->host_item.test_tag_queue_capability.max_srb = 1;
+
+ cfg->boot_flag = TRUE;
+
+ DbgInfo(MODULE_CFG_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "update cfg for dump_mode setting\n");
+}
+
+/* bus_width 0: 1bit 1: 4bit 2: 8bit */
+void cfg_emmc_busw_supp(cfg_emmc_mode_t *emmc_mode, u8 bus_width)
+{
+ emmc_mode->dis_8bit_bus_width = 1;
+ emmc_mode->dis_4bit_bus_width = 1;
+
+ if (bus_width == 1) {
+ emmc_mode->dis_8bit_bus_width = 1;
+ emmc_mode->dis_4bit_bus_width = 0;
+ } else if (bus_width == 2) {
+ emmc_mode->dis_8bit_bus_width = 0;
+ emmc_mode->dis_4bit_bus_width = 0;
+ }
+
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CARD_INIT, NOT_TO_RAM,
+ "Change MMC bus width to %d\n", bus_width);
+}
+
+void os_load_pcr_cb(void *cfgp, u32 type, u32 idx, u32 addr, u32 value)
+{
+ cfg_item_t *cfg = cfgp;
+
+ if (idx >= MAX_PCR_SETTING_SIZE) {
+ DbgErr("%s idx(%d) ovf(%d)\n", __func__, idx,
+ MAX_PCR_SETTING_SIZE);
+ goto exit;
+ }
+ if (cfg->pcr_item.cnt < MAX_PCR_SETTING_SIZE) {
+ cfg_pcr_t *pcr = &cfg->pcr_item.pcr_tb[idx];
+
+ pcr->valid_flg = 1;
+ pcr->type = type;
+ pcr->addr = (u16) addr;
+ pcr->mask = (u16) (value >> 16);
+ pcr->val = (u16) (value & 0xffff);
+ cfg->pcr_item.cnt++;
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, NOT_TO_RAM,
+ "[%d] PCR Addr: 0x%04X vlaue=0x%8X\n", idx, addr,
+ value);
+ DbgErr("[%d] PCR Addr: 0x%04X vlaue=0x%8X\n", idx, addr, value);
+ } else {
+ DbgErr("%s cnt(%d) ovf(%d)\n", __func__, cfg->pcr_item.cnt,
+ MAX_PCR_SETTING_SIZE);
+ goto exit;
+ }
+exit:
+ ;
+}
+
+void os_load_dmdn_cb(void *cfgp, u32 type, u32 idx, u32 addr, u32 value)
+{
+ cfg_item_t *cfg = cfgp;
+
+ if (addr < MAX_FREQ_SUPP) {
+ cfg->dmdn_tbl[addr] = value;
+ DbgInfo(MODULE_CFG_MNG, FEATURE_CFG_TRACE, NOT_TO_RAM,
+ "DMDN Table idx: 0x%x, Value: 0x%08x\n", addr, value);
+ }
+}
+
+bool cfg_dma_need_sdma_like_buffer(u32 dma_mode)
+{
+ if ((dma_mode == CFG_TRANS_MODE_ADMA2_SDMA_LIKE) ||
+ (dma_mode == CFG_TRANS_MODE_ADMA3_SDMA_LIKE) ||
+ (dma_mode == CFG_TRANS_MODE_SDMA) ||
+ (dma_mode == CFG_TRANS_MODE_ADMA_MIX_SDMA_LIKE))
+ return TRUE;
+ else
+ return FALSE;
+
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: funcapi.h
+ *
+ * Abstract: This include file define interface for each function
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 8/25/2014 Creation Peter.Guo
+ */
+
+void func_autotimer_init(bht_dev_ext_t *pdx);
+
+void pm_init(bht_dev_ext_t *pdx);
+
+void func_timer_thread(bht_dev_ext_t *pdx);
+
+/*
+ * This function is called by thread
+ * (1) If auotpowered off wake up card
+ * (2) Thermal contorl if tagqueue is not running
+ */
+void tagio_event_handler(bht_dev_ext_t *pdx);
+void genio_event_hanlder(bht_dev_ext_t *pdx);
+void rtd3_event_hanlder(bht_dev_ext_t *pdx);
+
+void testcase_main(bht_dev_ext_t *pdx, byte type);
+void testcase_init(bht_dev_ext_t *pdx);
new file mode 100644
@@ -0,0 +1,618 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: geniofunc.c
+ *
+ * Abstract: This source file used to implement IOctrl request
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 8/25/2014 Creation Peter.Guo
+ */
+
+#include "../include/basic.h"
+#include "../include/cardapi.h"
+#include "../include/reqapi.h"
+#include "../include/tqapi.h"
+#include "../include/hostapi.h"
+#include "../include/cmdhandler.h"
+#include "../include/funcapi.h"
+#include "funcapi.h"
+#include "../include/debug.h"
+
+bool func_cprm(sd_card_t *card, request_t *req)
+{
+ bool result = FALSE;
+ bool ret = FALSE;
+ sd_host_t *host = card->host;
+ card_info_t *card_info = &(card->info);
+ byte cmd_index;
+ u32 argument = 0;
+ u32 cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ sd_command_t sd_cmd;
+ u32 *pSrbData32;
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Enter %s\n", __func__);
+
+ if ((card->card_type != CARD_SD) && (card->card_type != CARD_UHS2))
+ goto exit;
+
+ result = card_stop_infinite(card, TRUE, NULL);
+ if (result == FALSE) {
+ DbgErr("Stop Infinite failed1\n");
+ goto exit;
+ }
+
+ /* If use read write, Save Current DMA mode */
+ host_transfer_init(host, FALSE, TRUE);
+ result = FALSE;
+ switch (req->gen_req_t.arg1) {
+ case CPRM_IO_GETCSD:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETCSD\n");
+ os_memcpy(req->srb_buff, &(card_info->raw_csd[0]), 16);
+ result = TRUE;
+ break;
+ case CPRM_IO_GETMID:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETMID\n");
+ cmd_index = SD_CMD44 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_IN, req->srb_buff, 8);
+ if (!ret) {
+ DbgErr("Issue ACMD44 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_GETWP:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETWP\n");
+ pSrbData32 = (u32 *) req->srb_buff;
+ if ((sdhci_readw(host, 0x26) & 0x08) != 0)
+ *pSrbData32 = 0;
+ else
+ *pSrbData32 = 1;
+ result = TRUE;
+ break;
+ case CPRM_IO_GETMKB:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETMKB\n");
+ cmd_index = SD_CMD43 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ argument = *((u32 *) req->srb_buff);
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, argument,
+ cmd_flag, DATA_DIR_IN, req->srb_buff, 512);
+ if (!ret) {
+ DbgErr("Issue ACMD43 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_SETCERRN:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_SETCERRN\n");
+ cmd_index = SD_CMD45 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_OUT, req->srb_buff, 8);
+ if (!ret) {
+ DbgErr("Issue ACMD45 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_GETCERRN:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETCERRN\n");
+ cmd_index = SD_CMD46 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_IN, req->srb_buff, 8);
+ if (!ret) {
+ DbgErr("Issue ACMD46 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_SETCERRES:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_SETCERRES\n");
+ cmd_index = SD_CMD47 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_OUT, req->srb_buff, 8);
+ if (!ret) {
+ DbgErr("Issue ACMD47 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_GETCERRES:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETCERRES\n");
+ cmd_index = SD_CMD48 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_IN, req->srb_buff, 8);
+ if (!ret) {
+ DbgErr("Issue ACMD48 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_CHANGE_SA:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_CHANGE_SA\n");
+ cmd_index = SD_CMD49 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_NONE, NULL, 0);
+ if (!ret) {
+ DbgErr("Issue ACMD49 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_READ:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_READ\n");
+ if (req->gen_req_t.data_len == 512) {
+ cmd_index = SD_CMD17;
+ cmd_flag =
+ CMD_FLG_ADMA_SDMA | CMD_FLG_R1 | CMD_FLG_RESCHK;
+ } else {
+ cmd_index = SD_CMD18;
+ cmd_flag =
+ CMD_FLG_MULDATA | CMD_FLG_ADMA_SDMA | CMD_FLG_R1 |
+ CMD_FLG_RESCHK;
+ cmd_set_auto_cmd_flag(card, &cmd_flag);
+ }
+
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_IN,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("Issue CMD18 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_WRITE:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_WRITE\n");
+ if (req->gen_req_t.data_len == 512) {
+ cmd_index = SD_CMD24;
+ cmd_flag =
+ CMD_FLG_ADMA_SDMA | CMD_FLG_R1 | CMD_FLG_RESCHK;
+ } else {
+ cmd_index = SD_CMD25;
+ cmd_flag =
+ CMD_FLG_MULDATA | CMD_FLG_ADMA_SDMA | CMD_FLG_R1 |
+ CMD_FLG_RESCHK;
+ cmd_set_auto_cmd_flag(card, &cmd_flag);
+ }
+
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_OUT,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("Issue CMD25 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_SECURE_READ:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_SECURE_READ\n");
+ cmd_index = SD_CMD18 | SD_APPCMD;
+ cmd_flag = CMD_FLG_ADMA_SDMA | CMD_FLG_R1 | CMD_FLG_RESCHK;
+ if (card->card_type == CARD_SD)
+ cmd_flag |= CMD_FLG_MULDATA;
+ argument = req->gen_req_t.data_len >> 9;
+ argument = ((argument << 24) | req->gen_req_t.arg2);
+
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, argument,
+ cmd_flag, DATA_DIR_IN, req->srb_buff,
+ req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("Issue ACMD18 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_SECURE_WRITE:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_SECURE_WRITE\n");
+ cmd_index = SD_CMD25 | SD_APPCMD;
+ cmd_flag = CMD_FLG_ADMA_SDMA | CMD_FLG_R1 | CMD_FLG_RESCHK;
+ if (card->card_type == CARD_SD)
+ cmd_flag |= CMD_FLG_MULDATA;
+ argument = req->gen_req_t.data_len >> 9;
+ argument = ((argument << 24) | req->gen_req_t.arg2);
+
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, argument,
+ cmd_flag, DATA_DIR_OUT, req->srb_buff,
+ req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("Issue CMD25 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case CPRM_IO_GETSDHC:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "CPRM_IO_GETSDHC\n");
+ pSrbData32 = (u32 *) req->srb_buff;
+ *pSrbData32 = card_info->card_ccs;
+ result = TRUE;
+ break;
+ default:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IOCTL Unknown\n");
+ break;
+
+ }
+ /* Resorte current DMA mode */
+ host_transfer_init(host, card->inf_trans_enable, FALSE);
+exit:
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+ return result;
+}
+
+bool func_io_reg(sd_card_t *card, request_t *req)
+{
+ bool result = FALSE;
+ sd_host_t *host = card->host;
+ u32 *pSrbData32;
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Enter %s\n", __func__);
+
+ switch (req->gen_req_t.arg1) {
+ case IO_READ_PCI_REG:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_READ_PCI_REG\n");
+ pSrbData32 = (u32 *) req->srb_buff;
+ *pSrbData32 = pci_readl(host, (u16) req->gen_req_t.arg2);
+ result = TRUE;
+ break;
+ case IO_WRITE_PCI_REG:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_WRITE_PCI_REG\n");
+ pSrbData32 = (u32 *) req->srb_buff;
+ pci_writel(host, (u16) req->gen_req_t.arg2, *(pSrbData32 + 1));
+ result = TRUE;
+ break;
+ case IO_READ_MEM_REG:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_READ_MEM_REG\n");
+ pSrbData32 = (u32 *) req->srb_buff;
+ *pSrbData32 = sdhci_readl(host, (u16) req->gen_req_t.arg2);
+ result = TRUE;
+ break;
+ case IO_WRITE_MEM_REG:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_WRITE_MEM_REG\n");
+ pSrbData32 = (u32 *) req->srb_buff;
+ sdhci_writel(host, (u16) req->gen_req_t.arg2,
+ *(pSrbData32 + 1));
+ result = TRUE;
+ break;
+ default:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IOCTL Unknown\n");
+ break;
+
+ }
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+ return result;
+}
+
+bool erase_rw_blk_end_set(sd_card_t *card, sd_command_t *sd_cmd, u32 sec_addr)
+{
+ u32 cmdflag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ e_data_dir dir = DATA_DIR_NONE;
+ byte *data = NULL;
+ u32 datalen = 0;
+
+ bool ret = FALSE;
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Enter %s\n", __func__);
+
+ ret =
+ card_send_sdcmd(card, sd_cmd, SD_CMD33, sec_addr, cmdflag, dir,
+ data, datalen);
+ if (!ret)
+ DbgErr("erase rw blk end set error\n");
+
+ return ret;
+}
+
+bool erase_rw_blk_start_set(sd_card_t *card, sd_command_t *sd_cmd,
+ u32 sec_addr)
+{
+ u32 cmdflag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ e_data_dir dir = DATA_DIR_NONE;
+ byte *data = NULL;
+ u32 datalen = 0;
+
+ bool ret = FALSE;
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Enter %s\n", __func__);
+
+ ret =
+ card_send_sdcmd(card, sd_cmd, SD_CMD32, sec_addr, cmdflag, dir,
+ data, datalen);
+ if (!ret)
+ DbgErr("erase rw blk start set error\n");
+
+ return ret;
+}
+
+bool func_erase(sd_card_t *card, sd_command_t *sd_cmd)
+{
+ u32 cmdflag = CMD_FLG_R1B | CMD_FLG_RESCHK;
+ e_data_dir dir = DATA_DIR_NONE;
+ byte *data = NULL;
+ u32 datalen = 0;
+ byte cmd_index = SD_CMD38;
+ bool ret = FALSE;
+ u32 argument = 0x0;
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Enter %s\n", __func__);
+
+ ret =
+ card_send_sdcmd(card, sd_cmd, cmd_index, argument, cmdflag, dir,
+ data, datalen);
+ if (!ret)
+ DbgErr("erase error\n");
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+ return ret;
+}
+
+bool func_nsm(sd_card_t *card, request_t *req, bht_dev_ext_t *pdx)
+{
+ bool result = FALSE;
+ bool ret = FALSE;
+ sd_host_t *host = card->host;
+ card_info_t *card_info = &(card->info);
+ byte cmd_index;
+ u32 cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ sd_command_t sd_cmd;
+ u8 *p8;
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Enter %s\n", __func__);
+
+ if ((card->card_type != CARD_SD) && (card->card_type != CARD_UHS2))
+ goto exit;
+
+ result = card_stop_infinite(card, TRUE, NULL);
+ if (result == FALSE) {
+ DbgErr("Stop Infinite failed1\n");
+ goto exit;
+ }
+
+ /* If use read write, Save Current DMA mode */
+ host_transfer_init(host, FALSE, TRUE);
+ result = FALSE;
+ switch (req->gen_req_t.arg1) {
+
+ case IO_NSM_CMD48:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD48\n");
+ cmd_index = SD_CMD48;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_IN,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD48 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case IO_NSM_CMD49:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD49\n");
+ cmd_index = SD_CMD49;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_OUT,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD49 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case IO_NSM_CMD58:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD58\n");
+ cmd_index = SD_CMD58;
+ cmd_flag =
+ CMD_FLG_AUTO12 | CMD_FLG_MULDATA | CMD_FLG_R1 |
+ CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_IN,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD58 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case IO_NSM_CMD59:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD59\n");
+ cmd_index = SD_CMD59;
+ cmd_flag =
+ CMD_FLG_AUTO12 | CMD_FLG_MULDATA | CMD_FLG_R1 |
+ CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_OUT,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD59 Fail.\n");
+ goto exit;
+ }
+ result = TRUE;
+ break;
+ case IO_NSM_CMD42:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD42\n");
+
+ result = TRUE;
+ cmd_index = SD_CMD42;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ req->gen_req_t.arg2, cmd_flag, DATA_DIR_OUT,
+ req->srb_buff, req->gen_req_t.data_len);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD42 Fail.\n");
+ goto exit;
+ }
+ p8 = (u8 *) (req->srb_buff);
+ /* If Unlock command */
+ if (((*p8) & 0x4) == 0) {
+ card->locked = FALSE;
+ result = card_init_stage2(card);
+
+ if (result == TRUE && pdx->scsi.last_present == 0) {
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE,
+ NOT_TO_RAM,
+ "Exec Bus Change for Unlock ok\n");
+ /* callback execute successfully */
+ if (thread_exec_high_prio_job
+ (pdx, os_bus_change, pdx))
+ pdx->scsi.last_present = 1;
+ }
+ }
+ break;
+ case IO_NSM_CMD9:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD9\n");
+ os_memcpy(req->srb_buff, &(card_info->raw_csd[0]), 16);
+ result = TRUE;
+#if (0)
+ result = TRUE;
+ cmd_index = SD_CMD9;
+ cmd_flag = CMD_FLG_R2 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ card_info->rca << 16, cmd_flag,
+ DATA_DIR_NONE, NULL, 0);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD9 Fail.\n");
+ goto exit;
+ } else {
+ /* Set the card CSD info */
+ os_memcpy(req->srb_buff, &(sd_cmd->response[0]), 16);
+ }
+#endif
+ break;
+ case IO_NSM_CMD10:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_CMD10\n");
+ os_memcpy(req->srb_buff, &(card_info->raw_cid[0]), 16);
+
+ result = TRUE;
+#if (0)
+ cmd_index = SD_CMD10;
+ cmd_flag = CMD_FLG_R2 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ card_info->rca << 16, cmd_flag,
+ DATA_DIR_NONE, NULL, 0);
+ if (!ret) {
+ DbgErr("IO_NSM_CMD10 Fail.\n");
+ goto exit;
+ } else {
+ /* Set the card CID info */
+ os_memcpy(req->srb_buff, &(sd_cmd->response[0]), 16);
+ }
+#endif
+ break;
+
+ case IO_NSM_ACMD51:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_ACMD51\n");
+
+ result = TRUE;
+ cmd_index = SD_CMD51 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index,
+ card_info->rca << 16, cmd_flag, DATA_DIR_IN,
+ req->srb_buff, 8);
+ if (!ret) {
+ DbgErr("IO_NSM_ACMD51 Fail.\n");
+ goto exit;
+ }
+ break;
+
+ case IO_NSM_ACMD13:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IO_NSM_ACMD13\n");
+
+ result = TRUE;
+ cmd_index = SD_CMD13 | SD_APPCMD;
+ cmd_flag = CMD_FLG_R1 | CMD_FLG_RESCHK;
+ ret =
+ card_send_sdcmd(card, &sd_cmd, cmd_index, 0, cmd_flag,
+ DATA_DIR_IN, req->srb_buff, 64);
+ if (!ret) {
+ DbgErr("IO_NSM_ACMD13 Fail.\n");
+ goto exit;
+ }
+ break;
+
+ default:
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "IOCTL Unknown\n");
+ break;
+
+ }
+ /* Resorte current DMA mode */
+ host_transfer_init(host, card->inf_trans_enable, FALSE);
+exit:
+
+ DbgInfo(MODULE_MAIN_GENIO, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+ return result;
+}
new file mode 100644
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: pmfunc.c
+ *
+ * Abstract: This source file used to implement power management functions
+ *
+ * Version: 1.00
+ *
+ * Author: Yuxiang
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 9/2/2014 Creation Yuxiang
+ */
+
+#include "../include/basic.h"
+#include "../include/debug.h"
+#include "../include/reqapi.h"
+#include "../include/funcapi.h"
+#include "../include/hostapi.h"
+#include "../include/hostvenapi.h"
+#include "../include/cardapi.h"
+#include "../include/cmdhandler.h"
+
+void pm_init(bht_dev_ext_t *pdx)
+{
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_DRIVER_INIT, 0, "Enter %s chip:%xh\n",
+ __func__, pdx->host.chip_type);
+
+ /* TODO: RTD3 enable From the registry */
+ pdx->pm_state.s3s4_entered = FALSE;
+ pdx->pm_state.rtd3_en = hostven_rtd3_check(&pdx->host);
+ pdx->pm_state.rtd3_entered = FALSE;
+ pdx->pm_state.s5_entered = FALSE;
+ pdx->pm_state.warm_boot_entered = FALSE;
+ hostven_pm_mode_cfg(&pdx->host, &(pdx->pm_state));
+ os_pm_init(pdx);
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Exit %s\n", __func__);
+}
+
+extern void host_internal_clk_setup(sd_host_t *host, bool on);
+
+static void req_enter_d0_internal(bht_dev_ext_t *pdx, bool reinit_async)
+{
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0,
+ "Enter %s rtd3=%d card_init status=%d\n", __func__,
+ pdx->pm_state.rtd3_en, pdx->card.thread_init_card_flag);
+
+#ifdef MultiThread
+ os->thread_auto_timer_runing = FALSE;
+ os->thread_card_init_runing = FALSE;
+ os->thread_card_remove_runing = FALSE;
+ os->thread_pending_runing = FALSE;
+ os->thread_gen_io_runing = FALSE;
+ os->thread_tag_io_runing = FALSE;
+ os->thread_rtd3_runing = FALSE;
+ os->thread_terminate_runing = FALSE;
+#else
+
+#endif
+
+ host_vendor_feature_init(&(pdx->host));
+ host_init(&(pdx->host));
+
+ if (hostven_chk_card_present(&pdx->host)) {
+ pdx->card.card_present = TRUE;
+ /* clean card_init flag status to wait for initialization */
+ pdx->card.thread_init_card_flag = 0;
+
+ } else {
+ pdx->scsi.scsi_eject = FALSE;
+
+ pdx->card.card_present = FALSE;
+ card_stuct_uinit(&pdx->card);
+ }
+ thermal_uninit(pdx);
+ if (reinit_async) {
+ if (pdx->scsi.scsi_eject == 0) {
+
+#if CFG_OS_LINUX
+ os_set_event(&pdx->os, EVENT_CARD_CHG);
+#else
+ os_set_event(pdx, &pdx->os, EVENT_TASK_OCCUR,
+ TASK_CARD_CHG);
+#endif
+ } else {
+ host_internal_clk_setup(&(pdx->host), TRUE);
+ }
+ }
+
+ pdx->pm_state.s3s4_entered = FALSE;
+ pdx->pm_state.s5_entered = FALSE;
+ pdx->pm_state.warm_boot_entered = FALSE;
+ if (pdx->pm_state.rtd3_en)
+ pdx->pm_state.rtd3_entered = FALSE;
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0,
+ "Exit %s card_init status=%d\n", __func__,
+ pdx->card.thread_init_card_flag);
+}
+
+void req_enter_d0(bht_dev_ext_t *pdx)
+{
+ req_enter_d0_internal(pdx, TRUE);
+}
+
+void req_enter_d0_sync(bht_dev_ext_t *pdx)
+{
+ req_enter_d0_internal(pdx, FALSE);
+}
+
+void req_pre_enter_d3(bht_dev_ext_t *pdx)
+{
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Enter %s\n",
+ __func__);
+
+ /* for thread sync : such as autotimer stop infinite */
+ if (os_pending_thread(pdx, TRUE) == FALSE)
+ DbgErr("%s pending thread failed\n", __func__);
+
+ if (card_stop_infinite(&pdx->card, FALSE, NULL) == FALSE)
+ card_power_off(&(pdx->card), TRUE);
+
+ os_pending_thread(pdx, FALSE);
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Exit %s\n", __func__);
+}
+
+#if (0)
+void pcr_part_a_backup(bht_dev_ext_t *pdx)
+{
+ if (pdx->cfg->driver_item.backup_part_a) {
+ /* enable or disable LED output or not. */
+ pdx->pm_state.reg_0xdc = pci_readl(&pdx->host, 0xdc);
+
+ /* disable or enable RTD3 */
+ pdx->pm_state.reg_0x3e0 = pci_readl(&pdx->host, 0x3e0);
+
+ pdx->pm_state.reg_0x3e8 = pci_readl(&pdx->host, 0x3e8);
+
+ pdx->pm_state.reg_0x3ec = pci_readl(&pdx->host, 0x3ec);
+
+ /* Change the ASPM L0s Exit Latency */
+ pdx->pm_state.reg_0xf4 = pci_readl(&pdx->host, 0xf4);
+
+ /* ep nfts value */
+ pdx->pm_state.reg_0x74 = pci_readl(&pdx->host, 0x74);
+
+ /* Power saving mode setting */
+ pdx->pm_state.reg_0xf0 = pci_readl(&pdx->host, 0xf0);
+
+ /* enable or disable ASPM L0s&L1 */
+ pdx->pm_state.reg_0x90 = pci_readl(&pdx->host, 0x90);
+
+ }
+
+}
+
+void pcr_part_b_backup(bht_dev_ext_t *pdx)
+{
+ if (pdx->cfg->driver_item.backup_part_b) {
+ pdx->pm_state.reg_0x64 = pci_readl(&pdx->host, 0x64);
+ /* skt power control output enable */
+ pdx->pm_state.reg_0xec = pci_readl(&pdx->host, 0xec);
+ /* ocb cntl timer */
+ /* ocb cntl enable */
+ pdx->pm_state.reg_0xd4 = pci_readl(&pdx->host, 0xd4);
+ pdx->pm_state.reg_0x3e4 = pci_readl(&pdx->host, 0x3e4);
+ /* PLL DM */
+ pdx->pm_state.reg_0x304 = pci_readl(&pdx->host, 0x304);
+
+ /* Set Base Clock Frequency */
+ pdx->pm_state.reg_0x328 = pci_readl(&pdx->host, 0x328);
+
+ /* Set DLL tuning window */
+ pdx->pm_state.reg_0x300 = pci_readl(&pdx->host, 0x300);
+
+ /* aux power LDO */
+ pdx->pm_state.reg_0x68 = pci_readl(&pdx->host, 0x68);
+
+ /* Adjust the output delay for SD2.0 high speed mode */
+ pdx->pm_state.reg_0x350 = pci_readl(&pdx->host, 0x350);
+ /* T_EIDL_ENTRY */
+ pdx->pm_state.reg_0x35c = pci_readl(&pdx->host, 0x35c);
+
+ /* disable bit for UHSII term_resistor_calibration */
+ pdx->pm_state.reg_0x3e0 = pci_readl(&pdx->host, 0x3e0);
+
+ /* Set the Max power supply capability of SD host */
+ pdx->pm_state.reg_0x334 = pci_readl(&pdx->host, 0x334);
+
+ /* external enable polarity control pin */
+ pdx->pm_state.reg_0xd8 = pci_readl(&pdx->host, 0xd8);
+
+ /* AOSC off support */
+ pdx->pm_state.reg_0x3f0 = pci_readl(&pdx->host, 0x3f0);
+
+ /* max read request size */
+ pdx->pm_state.reg_0x88 = pci_readl(&pdx->host, 0x88);
+
+ /* UHSII DLL watch dog */
+ pdx->pm_state.reg_0x33c = pci_readl(&pdx->host, 0x33c);
+
+ /* PCI-PM L1 entrance timer */
+ pdx->pm_state.reg_0xe0 = pci_readl(&pdx->host, 0xe0);
+
+ /* ASPM L1 entrance timer */
+ pdx->pm_state.reg_0xfc = pci_readl(&pdx->host, 0xfc);
+
+ }
+}
+
+void pcr_part_a_restore(bht_dev_ext_t *pdx)
+{
+ if (pdx->cfg->driver_item.backup_part_a) {
+ pci_writel(&pdx->host, 0xdc, pdx->pm_state.reg_0xdc);
+ pci_writel(&pdx->host, 0x3e0, pdx->pm_state.reg_0x3e0);
+ pci_writel(&pdx->host, 0x3e8, pdx->pm_state.reg_0x3e8);
+ pci_writel(&pdx->host, 0x3ec, pdx->pm_state.reg_0x3ec);
+ pci_writel(&pdx->host, 0xf4, pdx->pm_state.reg_0xf4);
+ pci_writel(&pdx->host, 0x74, pdx->pm_state.reg_0x74);
+ pci_writel(&pdx->host, 0xf0, pdx->pm_state.reg_0xf0);
+ pci_cfgio_writel(&pdx->host, 0x90, pdx->pm_state.reg_0x90);
+ }
+}
+
+void pcr_part_b_restore(bht_dev_ext_t *pdx)
+{
+ if (pdx->cfg->driver_item.backup_part_b) {
+ pci_writel(&pdx->host, 0x64, pdx->pm_state.reg_0x64);
+ pci_writel(&pdx->host, 0xec, pdx->pm_state.reg_0xec);
+ pci_writel(&pdx->host, 0xd4, pdx->pm_state.reg_0xd4);
+ pci_writel(&pdx->host, 0x304, pdx->pm_state.reg_0x304);
+ pci_writel(&pdx->host, 0x328, pdx->pm_state.reg_0x328);
+ pci_writel(&pdx->host, 0x300, pdx->pm_state.reg_0x300);
+ /* Don't need to restore as it is the stick register */
+ pci_writel(&pdx->host, 0x3e4, pdx->pm_state.reg_0x3e4);
+ pci_writel(&pdx->host, 0x68, pdx->pm_state.reg_0x68);
+
+ pci_writel(&pdx->host, 0x350, pdx->pm_state.reg_0x350);
+ pci_writel(&pdx->host, 0x35c, pdx->pm_state.reg_0x35c);
+ pci_writel(&pdx->host, 0x3e0, pdx->pm_state.reg_0x3e0);
+ pci_writel(&pdx->host, 0x334, pdx->pm_state.reg_0x334);
+ pci_writel(&pdx->host, 0xd8, pdx->pm_state.reg_0xd8);
+ pci_writel(&pdx->host, 0x3f0, pdx->pm_state.reg_0x3f0);
+ pci_cfgio_writel(&pdx->host, 0x88, pdx->pm_state.reg_0x88);
+ pci_writel(&pdx->host, 0x33c, pdx->pm_state.reg_0x33c);
+ pci_writel(&pdx->host, 0xe0, pdx->pm_state.reg_0xe0);
+ pci_writel(&pdx->host, 0xfc, pdx->pm_state.reg_0xfc);
+ }
+}
+#endif
+
+void failsafe_fct(bht_dev_ext_t *pdx)
+{
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0,
+ "Enter %s, fail-safe: %d, chip type: 0x%x\n", __func__,
+ pdx->cfg->driver_item.failsafe_en, pdx->host.chip_type);
+
+ /* add s5_entered here to fix GG8-MP FPGA PM issue#2 */
+ if ((pdx->pm_state.s3s4_entered) || (pdx->pm_state.s5_entered)) {
+ if (pdx->cfg->driver_item.failsafe_en == 1) {
+ if (pdx->host.chip_type == CHIP_SEAEAGLE) {
+ /* Failsafe enable */
+ pci_orl(&(pdx->host), 0x3E0, BIT6);
+ }
+
+ if (pdx->host.chip_type == CHIP_GG8
+ || pdx->host.chip_type == CHIP_ALBATROSS) {
+
+ pci_andl(&(pdx->host), 0x408, ~(0x84210842));
+ pci_andl(&(pdx->host), 0x410, ~(0x02108410));
+
+ }
+ }
+ }
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Exit %s\n", __func__);
+}
+
+void pcie_weakup(bht_dev_ext_t *pdx, u32 Sx_flag, bool enable)
+{
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Enter %s(%d) with S%d\n",
+ __func__, enable, Sx_flag);
+
+ if (pdx->host.chip_type != CHIP_GG8
+ && pdx->host.chip_type != CHIP_ALBATROSS) {
+ DbgErr("Error: pcie weakup function only support GG8\n");
+ return;
+ }
+
+ if (enable) {
+ /* Driver load, Driver re-enable Card insert/remove source bit(0x468[20] = 1). */
+ pci_orl(&(pdx->host), 0x468, (1 << 20));
+ } else {
+ switch (Sx_flag) {
+ case ENTRY_S3:
+ if (pdx->cfg->feature_item.pcie_wake_setting.s3_disable_wakeup)
+ pci_andl(&(pdx->host), 0x468, ~(1 << 20));
+ else
+ DbgErr
+ ("Warning:registry setting for s3 is not ready\n");
+
+ break;
+
+ case ENTRY_S4:
+ if (pdx->cfg->feature_item.pcie_wake_setting.s4_disable_wakeup)
+ pci_andl(&(pdx->host), 0x468, ~(1 << 20));
+ else
+ DbgErr
+ ("Warning:registry setting for s4 is not ready\n");
+
+ break;
+
+ case ENTRY_S5:
+ if (pdx->cfg->feature_item.pcie_wake_setting.s5_disable_wakeup)
+ pci_andl(&(pdx->host), 0x468, ~(1 << 20));
+ else
+ DbgErr
+ ("Warning:registry setting for s5 is not ready\n");
+
+ break;
+
+ default:
+ DbgErr
+ ("Error: only support 3/4/5!!! current value is %d\n",
+ Sx_flag);
+ break;
+
+ }
+ }
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Exit %s\n", __func__);
+}
+
+void req_enter_d3(bht_dev_ext_t *pdx)
+{
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Enter %s\n",
+ __func__);
+
+ func_autotimer_stop(pdx);
+ card_power_off(&(pdx->card), FALSE);
+ thermal_uninit(pdx);
+ host_int_sig_dis(&(pdx->host), 0xffffffff);
+
+ pdx->card.initialized_once = FALSE;
+ card_stuct_init(pdx);
+
+ DbgInfo(MODULE_MAIN_PM, FEATURE_PM_TRACE, 0, "Exit %s\n", __func__);
+
+}
new file mode 100644
@@ -0,0 +1,546 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: reqmng.c
+ *
+ * Abstract: This file is used to manage interface for OSEntry layer
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 8/25/2014 Creation Peter.Guo
+ */
+
+#include "../include/basic.h"
+#include "../include/reqapi.h"
+#include "../include/tqapi.h"
+#include "../include/transhapi.h"
+#include "../include/debug.h"
+#include "../include/hostapi.h"
+#include "../include/cardapi.h"
+#include "../include/funcapi.h"
+#include "funcapi.h"
+#include "../include/cmdhandler.h"
+#include "../include/hostvenapi.h"
+
+#ifdef MultiThread
+extern void thread_card_chg(void *pdx);
+extern void thread_card_init(void *pdx);
+extern void thread_event_pending(void *pdx);
+extern void thread_event_tag_io(void *pdx);
+extern void thread_event_gen_io(void *pdx);
+extern void thread_runtime_d3(void *pdx);
+extern void thread_auto_timer(void *pdx);
+extern void thread_event_terminate(void *pdx);
+extern void thread_camod_poll_card_chg(void *pdx);
+#endif
+
+/*
+ * Function Name: req_global_init
+ *
+ * Abstract:
+ *
+ * This routine init timer, tagqueue, host cap init,
+ * and vendor reg setting, host interrupt and init to workable status
+ * card and host software structure init (caller init pci_dev_t and global cfg).
+ *
+ * Input:
+ *
+ * pdx [in]: The device extension object.
+ *
+ * Output:
+ *
+ * None
+ *
+ * Return value:
+ *
+ * None
+ *
+ * Notes:
+ *
+ * IRQL <= APC_LEVEL
+ */
+s32 req_global_init(bht_dev_ext_t *pdx)
+{
+ DbgInfo(MODULE_REQ_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ /* Initialize the host pointer for the card structure */
+ pdx->card.host = &(pdx->host);
+ pdx->scsi_init_flag = 0;
+ /* Host vendor settings */
+ host_vendor_feature_init(&(pdx->host));
+
+ host_init_capbility(&(pdx->host));
+
+ /* 6 Initialize the OS layer */
+
+ /* DPC init has to be in HWinitpassive routine */
+ os_layer_init(pdx, &pdx->os);
+
+ /* card struct init */
+ card_stuct_init(pdx);
+
+ os_memset(&pdx->pre_card, 0, sizeof(pre_card_info_t));
+
+ pdx->pre_card.s3s4_resume_for_card_init = FALSE;
+
+ pdx->auto_timer.s3reusme_cardchg_issuefix_en = FALSE;
+ pdx->auto_timer.s3s4_start_timer = FALSE;
+ pdx->auto_timer.s3reusme_timer_expect_cnt = 0;
+ pdx->auto_timer.s3reusme_timer_actual_cnt = 0;
+
+ func_autotimer_init(pdx);
+
+ /* dma api init */
+ dma_api_io_init(pdx, &pdx->dma_buff);
+
+ /* Tag queue sturct init */
+
+ /* dump mode don't use tag queue */
+ if (pdx->dump_mode == FALSE)
+ tag_queue_init(pdx);
+
+ os_memset(&pdx->scsi, 0, sizeof(scsi_mng_t));
+
+ pdx->soft_irq.enable = 0;
+ pdx->p_srb_ext = NULL;
+
+ /* 7. Initialize the thread */
+
+ /* dump mode don't use thread */
+ if (pdx->dump_mode == FALSE)
+ os_create_thread(&pdx->os.thread, pdx, thread_main);
+
+ /* 8. Host controller initialize */
+ host_init(&(pdx->host));
+ thermal_init(pdx);
+ pdx->signature = BHT_PDX_SIGNATURE;
+
+ /* 9. PM init */
+ pm_init(pdx);
+
+ if (hostven_chk_card_present(&pdx->host)) {
+ hostven_main_power_ctrl(&pdx->host, TRUE);
+ pdx->card.card_present = TRUE;
+ } else {
+ hostven_main_power_ctrl(&pdx->host, FALSE);
+ }
+
+ /* Test Case Init */
+ testcase_init(pdx);
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+
+ return 0;
+}
+
+/*
+ * This function is used context:
+ * (1) In Thread
+ * (2) (Card and Tagqueue is not working)
+ * (3) No other SRB will coming down
+ */
+void req_global_reinit(bht_dev_ext_t *pdx)
+{
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ /* Host vendor settings */
+ host_vendor_feature_init(&(pdx->host));
+
+ host_init_capbility(&(pdx->host));
+
+ card_stuct_uinit(&pdx->card);
+
+ func_autotimer_init(pdx);
+
+ tag_queue_init(pdx);
+
+ thermal_init(pdx);
+
+ if (hostven_chk_card_present(&pdx->host)) {
+ hostven_main_power_ctrl(&pdx->host, TRUE);
+ pdx->card.card_present = TRUE;
+ }
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+
+}
+
+/*
+ * Function Name: req_cancel_all_io
+ * Abstract: This Function is used to cancel all not handled io
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ *
+ * Output:
+ *
+ */
+void req_cancel_all_io(bht_dev_ext_t *pdx)
+{
+ DbgInfo(MODULE_REQ_MNG, FEATURE_RW_TRACE, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ if (pdx->dump_mode)
+ goto exit;
+ /* try to cancel gen io */
+ if (pdx->p_srb_ext != NULL) {
+ if (pdx->p_srb_ext->req.srb_done_cb)
+ pdx->p_srb_ext->req.srb_done_cb(pdx, pdx->p_srb_ext);
+ } else {
+ /* try to cancel tag io */
+ tag_queue_abort(pdx, REQ_RESULT_ABORT);
+ }
+exit:
+ DbgInfo(MODULE_REQ_MNG, FEATURE_RW_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+
+}
+
+/*
+ *
+ * Function Name: req_global_uninit
+ *
+ * Abstract:
+ *
+ * This routine uninit os related variable, reset host, finish pending Srb
+ * reset host
+ *
+ * Input:
+ *
+ * pdx [in]: The device extension object.
+ *
+ * Output:
+ *
+ * None
+ *
+ * Return value:
+ *
+ * None
+ *
+ * Notes:
+ *
+ *
+ *
+ *
+ * IRQL <= APC_LEVEL
+ */
+
+s32 req_global_uninit(bht_dev_ext_t *pdx)
+{
+ DbgInfo(MODULE_REQ_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ func_autotimer_cancel(pdx);
+ thermal_uninit(pdx);
+ host_uninit(&pdx->host, TRUE);
+
+ req_cancel_all_io(pdx);
+
+ os_layer_uinit(pdx, &pdx->os);
+ DbgInfo(MODULE_REQ_MNG, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+ return 0;
+}
+
+/*
+ * Function Name: scsi_check_card_ready
+ * Abstract: This Function is used to by scsi cmd to check whether UNIT IS READY OR NOT
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ * sd_card_t *card,
+ *
+ * Output:
+ *
+ *
+ * Return value:
+ * TRUE: Card is ready
+ * FALSE Card is not ready
+ */
+
+static bool scsi_check_card_ready(bht_dev_ext_t *pdx, sd_card_t *card)
+{
+ bool result = FALSE;
+
+ if (pdx->scsi.scsi_eject)
+ goto exit;
+
+ /* if card not preset, return failed */
+ if (card->card_type == CARD_ERROR || card->card_type == CARD_NONE)
+ goto exit;
+
+ if (card->card_present == FALSE || card->initialized_once == FALSE
+ || card->card_chg)
+ goto exit;
+
+ if (card->locked)
+ goto exit;
+
+ result = TRUE;
+exit:
+ return result;
+}
+
+/*
+ * Function Name: req_gen_io_add
+ * Abstract: This Function is used to add srb request to General IO
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ * srb_ext_t *srb_ext: caller need to fill request_t req;
+ * Output:
+ *
+ *
+ * Return value:
+ *
+ * e_req_result: the result of this command,
+ * scsi layer use this value to determine scsi cmd status
+ */
+static bool append_general_io_queue(srb_ext_t **head, srb_ext_t *node)
+{
+ if (head == NULL)
+ return FALSE;
+
+ if (*head == NULL)
+ *head = node;
+ else {
+ srb_ext_t *tail = *head;
+
+ while (tail->next != NULL)
+ tail = tail->next;
+ tail->next = node;
+ }
+ return TRUE;
+}
+
+e_req_result req_gen_io_add(bht_dev_ext_t *pdx, srb_ext_t *srb_ext)
+{
+ e_req_result result = REQ_RESULT_QUEUE_BUSY;
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ /* If currently working at general IO, we can't start tag queue io */
+#if (0)
+ if (pdx->p_srb_ext != NULL)
+ if (pdx->p_srb_ext->req.type == REQ_TYPE_GEN_IO)
+ goto exit;
+#endif
+
+ result = REQ_RESULT_PENDING;
+ srb_ext->req.type = REQ_TYPE_GEN_IO;
+ srb_ext->req.result = REQ_RESULT_PENDING;
+ srb_ext->next = NULL;
+ /* check whether the taq queue is empty */
+ if (tq_is_empty(pdx) == FALSE) {
+ append_general_io_queue(&(pdx->p_srb_ext_bak), srb_ext);
+ } else {
+ append_general_io_queue(&(pdx->p_srb_ext), srb_ext);
+ func_autotimer_stop(pdx);
+#if CFG_OS_LINUX
+ os_set_event(&pdx->os, EVENT_GEN_IO);
+#else
+ os_set_event(pdx, &pdx->os, EVENT_TASK_OCCUR, EVENT_GEN_IO);
+#endif
+ }
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Exit %s ret=%d\n", __func__, result);
+ return result;
+
+}
+
+/*
+ * Function Name: req_tag_io_add
+ * Abstract: This Function is used to add srb request to tag queue
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ * srb_ext_t *srb_ext: caller need to fill request_t req;
+ * Output:
+ *
+ *
+ * Return value:
+ *
+ * e_req_result: the result of this command,
+ * scsi layer use this value to determine scsi cmd status
+ */
+
+e_req_result req_tag_io_add(bht_dev_ext_t *pdx, srb_ext_t *srb_ext)
+{
+ e_req_result result = REQ_RESULT_QUEUE_BUSY;
+ sd_card_t *card = &pdx->card;
+ u32 sec_cnt;
+ u32 sec_addr;
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_RW_TRACE, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ /* If currently working at general IO, we can't start tag queue io */
+ if (pdx->p_srb_ext != NULL)
+ if (pdx->p_srb_ext->req.type == REQ_TYPE_GEN_IO)
+ goto exit;
+
+ if (scsi_check_card_ready(pdx, card) == FALSE) {
+ result = REQ_RESULT_NO_CARD;
+ goto exit;
+ }
+
+ /* check write protected */
+ if (card->write_protected && srb_ext->req.data_dir == DATA_DIR_OUT) {
+ result = REQ_RESULT_PROTECTED;
+ goto exit;
+ }
+
+ sec_addr = srb_ext->req.tag_req_t.sec_addr;
+ sec_cnt = srb_ext->req.tag_req_t.sec_cnt;
+
+ /*
+ * check request oversize
+ * todo: emmc boot partition case
+ */
+ if ((card->sec_count < sec_addr)
+ || (card->sec_count < sec_cnt)
+ || ((card->sec_count - sec_addr) < sec_cnt)) {
+ result = REQ_RESULT_OVERSIZE;
+ goto exit;
+ }
+
+ /* recaculate 1.0 card sector addr */
+
+ if (card_is_low_capacity(card)) {
+ sec_addr *= SD_BLOCK_LEN;
+ srb_ext->req.tag_req_t.sec_addr = sec_addr;
+ }
+
+ /* for PIO case , forware the request to gen io */
+ if (pdx->cfg->host_item.test_dma_mode_setting.dma_mode == 0xF) {
+ srb_ext->req.gen_req_t.code = GEN_IO_CODE_PIORW;
+ srb_ext->req.gen_req_t.arg1 = sec_addr;
+ srb_ext->req.gen_req_t.arg2 = sec_cnt;
+ result = req_gen_io_add(pdx, srb_ext);
+ } else {
+ /* update the request accroing to card type */
+ srb_ext->req.type = REQ_TYPE_TAG_IO;
+ srb_ext->req.result = REQ_RESULT_PENDING;
+ result = tq_add_request(pdx, srb_ext, card);
+ if (result == REQ_RESULT_PENDING)
+ func_autotimer_stop(pdx);
+ }
+exit:
+ DbgInfo(MODULE_REQ_MNG, FEATURE_RW_TRACE, NOT_TO_RAM,
+ "Exit %s ret=%d\n", __func__, result);
+ return result;
+}
+
+/*
+ * Function Name: req_card_ready
+ * Abstract: This Function is used to by scsi cmd to check whether UNIT IS READY OR NOT
+ *
+ * Input:
+ * bht_dev_ext_t *pdx
+ * Output:
+ *
+ *
+ * Return value:
+ * TRUE: Card is ready
+ * FALSE Card is not ready
+ */
+bool req_card_ready(bht_dev_ext_t *pdx)
+{
+ return scsi_check_card_ready(pdx, &pdx->card);
+}
+
+/*
+ * Function Name: scsi_check_card_ready
+ * Abstract: This Function is used to by scsi cmd to check whether UNIT IS READY OR NOT
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ *
+ * Output:
+ * e_req_result *result
+ *
+ * Return value:
+ * reutrn card if card is initialized
+ */
+e_req_result req_chk_card_info(bht_dev_ext_t *pdx, srb_ext_t *srb_ext)
+{
+ sd_card_t *card = &pdx->card;
+ e_req_result result = REQ_RESULT_NO_CARD;
+
+ if (pdx->scsi.scsi_eject)
+ goto exit;
+
+ if (card->card_present == FALSE)
+ goto exit;
+
+ /* check whether card has initailaze once */
+ if (card->initialized_once == FALSE) {
+ if (pdx->dump_mode == FALSE)
+ result = req_gen_io_add(pdx, srb_ext);
+ else
+ goto exit;
+
+ if (result != REQ_RESULT_PENDING)
+ DbgErr("req chk card info add gen io failed\n");
+ } else {
+ result = REQ_RESULT_OK;
+ }
+
+exit:
+ return result;
+}
+
+/*
+ * Function Name: req_eject
+ * Abstract: This Function is used by scsi cmd to eject(poweroff) sd card
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ *
+ * Output:
+ * e_req_result result
+ *
+ * Return value:
+ * reutrn card if card is initialized
+ */
+
+e_req_result req_eject(bht_dev_ext_t *pdx, srb_ext_t *srb_ext)
+{
+ sd_card_t *card = &pdx->card;
+ e_req_result result = REQ_RESULT_NO_CARD;
+
+ DbgInfo(MODULE_REQ_MNG, FEATURE_SCSICMD_TRACE, NOT_TO_RAM,
+ "Enter %s ret=%d\n", __func__, result);
+
+ if (card->card_present == FALSE)
+ goto exit;
+
+ /* If card not power off, send request to thread to do poweroff */
+ if (card->state != CARD_STATE_POWEROFF) {
+ result = req_gen_io_add(pdx, srb_ext);
+ if (result != REQ_RESULT_PENDING)
+ DbgErr("eject add gen io failed\n");
+ goto exit;
+ }
+
+ result = REQ_RESULT_OK;
+
+exit:
+ DbgInfo(MODULE_REQ_MNG, FEATURE_SCSICMD_TRACE, NOT_TO_RAM,
+ "Exit %s ret=%d\n", __func__, result);
+ return result;
+}
new file mode 100644
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015 BHT Inc.
+ *
+ * File Name: testcase.c
+ *
+ * Abstract: This source file used to implement testcase interface
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 1/13/2015 Creation Peter.Guo
+ */
+
+#include "../include/basic.h"
+#include "../include/cardapi.h"
+#include "../include/reqapi.h"
+#include "../include/tqapi.h"
+#include "../include/hostapi.h"
+#include "../include/cmdhandler.h"
+#include "../include/funcapi.h"
+#include "funcapi.h"
+#include "../include/debug.h"
+#include "../card/cardcommon.h"
+#include "../include/hostvenapi.h"
+
+typedef struct {
+ bool (*test_prepare)(bht_dev_ext_t *pdx);
+ bool (*test_execute)(bht_dev_ext_t *pdx);
+ char name[24];
+} test_func_t;
+
+/*
+ * This function is used to init card
+ */
+static bool test_init_card(bht_dev_ext_t *pdx)
+{
+ bool result = FALSE;
+ sd_card_t *card = &pdx->card;
+
+ DbgInfo(MODULE_TEST, FEATURE_CARD_INIT, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ card->card_chg = FALSE;
+#if CFG_OS_LINUX
+ os_sleep(200);
+#else
+ os_sleep((PVOID) pdx, 200);
+
+#endif
+ /* Init card here */
+ result = card_init(card, 10, FALSE);
+
+ DbgInfo(MODULE_TEST, FEATURE_CARD_INIT, NOT_TO_RAM, "Exit %s ret=%d\n",
+ __func__, result);
+ return result;
+}
+
+/* ---------------UHS2 Test Case--------------- */
+static bool test_uhs2_dmt(bht_dev_ext_t *pdx)
+{
+ sd_card_t *card = &pdx->card;
+ sd_command_t sd_cmd;
+ bool hbr = (pdx->testcase.test_param1 == 0) ? 0 : 1;
+
+ if (card->uhs2_info.uhs2_cap.hibernate == 0)
+ hbr = 0;
+
+ if (card->card_type != CARD_UHS2 || card->card_present == FALSE) {
+ DbgErr("Test uhs2 dmt failed for not uhs2 card\n");
+ return FALSE;
+ }
+
+ if (uhs2_enter_dmt(card, &sd_cmd, card->host, hbr) == FALSE)
+ return FALSE;
+
+ if (uhs2_resume_dmt(card, &sd_cmd, card->host, hbr) == FALSE)
+ return FALSE;
+
+ return TRUE;
+}
+
+static bool test_uhs2_fullreset(bht_dev_ext_t *pdx)
+{
+ sd_card_t *card = &pdx->card;
+
+ if (card->card_type != CARD_UHS2 || card->card_present == FALSE) {
+ DbgErr("Test uhs2 fullreset failed for not uhs2 card\n");
+ return FALSE;
+ }
+
+ if (uhs2_full_reset_card(card) == FALSE)
+ return FALSE;
+
+ return card_init(card, 1, TRUE);
+}
+
+test_func_t test_with_card_array[2] = {
+ /* TEST CASE1 */
+ { test_init_card, test_uhs2_dmt, "uhs2dmt" },
+ /* TEST CASE2 */
+ { test_init_card, test_uhs2_fullreset, "uhs2fullreset" },
+
+};
+
+test_func_t test_host_only_array[1] = {
+ { 0, 0, "nulltest" }
+
+};
+
+void testcase_main(bht_dev_ext_t *pdx, byte type)
+{
+ u32 id = pdx->testcase.test_id;
+ u32 loop = 0;
+ u32 testloop = pdx->testcase.test_loop;
+ bool binfinite = (testloop) ? 0 : 1;
+ test_func_t *test = NULL;
+
+ if (pdx->card.card_present == 0) {
+ host_init(&pdx->host);
+ card_stuct_uinit(&pdx->card);
+ PrintMsg("TEST remove card\n");
+ return;
+ }
+
+ if (type != pdx->testcase.test_type)
+ return;
+
+ if (type == 1)
+ test = &test_with_card_array[id - 1];
+ else
+ test = &test_host_only_array[id - 1];
+
+ if (test == NULL || test->test_prepare == NULL) {
+ DbgErr("Test(%d) prepare is null\n", id);
+ return;
+ }
+
+ if (test->test_prepare(pdx) == FALSE) {
+ DbgErr("Test(%s) prepare failed\n", test->name);
+ return;
+ }
+
+ PrintMsg("Test(%s) type=%d begin infinite=%d totalloop=%d\n",
+ test->name, type, binfinite, pdx->testcase.test_loop);
+
+ while (os_thread_is_freeze(pdx) == FALSE) {
+ loop++;
+ PrintMsg("Test(%s) loop=%d\n", test->name, loop);
+ if (test->test_execute(pdx) == FALSE) {
+ DbgErr("Test(%s) excute failed loop=%d\n", test->name,
+ loop);
+ break;
+ }
+
+ if (binfinite == 0) {
+ testloop--;
+ if (testloop == 0)
+ break;
+ }
+ }
+
+ PrintMsg("Test(%s) loop=%d end\n", test->name, loop);
+ host_poweroff(&pdx->host, 0);
+}
+
+void testcase_init(bht_dev_ext_t *pdx)
+{
+ if (pdx->testcase.test_type == 0)
+ return;
+
+ pdx->testcase.test_id = pdx->cfg->test_item.test_id;
+ pdx->testcase.test_loop = pdx->cfg->test_item.test_loop;
+ pdx->testcase.test_param1 = pdx->cfg->test_item.test_param1;
+ pdx->testcase.test_param2 = pdx->cfg->test_item.test_param2;
+ PrintMsg("testid=%d param1=0x%08X param2=0x%08X\n",
+ pdx->testcase.test_id, pdx->testcase.test_param1,
+ pdx->testcase.test_param2);
+
+ /* If test id is out of range */
+ if (pdx->testcase.test_id == 0)
+ pdx->testcase.test_type = 0;
+
+ /* card test */
+ if (pdx->testcase.test_type == 1) {
+ if (pdx->testcase.test_id >
+ sizeof(test_with_card_array) / sizeof(test_func_t))
+ pdx->testcase.test_type = 0;
+
+ if (pdx->card.card_present) {
+#if CFG_OS_LINUX
+ os_set_event(&pdx->os, EVENT_CARD_CHG);
+#else
+ os_set_event(pdx, &pdx->os, EVENT_TASK_OCCUR,
+ TASK_CARD_CHG);
+#endif
+ }
+ }
+ /* host only test */
+ else if (pdx->testcase.test_type == 2) {
+ if (pdx->testcase.test_id >
+ sizeof(test_host_only_array) / sizeof(test_func_t))
+ pdx->testcase.test_type = 0;
+ else {
+ /* todo insert test event */
+ }
+ }
+}
new file mode 100644
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 BHT Inc.
+ *
+ * File Name: thread.c
+ *
+ * Abstract: This file is used to handle thread event
+ *
+ * Version: 1.00
+ *
+ * Author: Peter.Guo
+ *
+ * Environment: OS Independent
+ *
+ * History:
+ *
+ * 8/25/2014 Creation Peter.Guo
+ */
+
+#include "../include/basic.h"
+#include "../include/cardapi.h"
+#include "../include/reqapi.h"
+#include "../include/tqapi.h"
+#include "../include/hostapi.h"
+#include "../include/cmdhandler.h"
+#include "../include/funcapi.h"
+#include "funcapi.h"
+#include "../include/debug.h"
+#include "../include/hostvenapi.h"
+#include "../linux_os/linux_scsi.h"
+
+/*
+ * Function Name: thread_init_card
+ * Abstract: This Function is used to by thread to init card
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ * bool init_err_card, for error card case need to do init or not
+ * bool send_bus_chg : need to send bus change or not
+ * int retry_num : init retry time
+ *
+ * Return value:
+ * TRUE: means ok
+ * others error
+ *
+ * Notes:
+ * run in thread context
+ */
+static bool thread_init_card(bht_dev_ext_t *pdx, bool init_err_card,
+ bool send_bus_chg, int retry_num)
+{
+ bool result = FALSE;
+ sd_card_t *card = &pdx->card;
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "Enter %s init_err=%d\n", __func__, init_err_card);
+
+ /* If error card and don't reinit err_card */
+ if (card->card_type == CARD_ERROR && init_err_card == FALSE)
+ goto exit;
+
+ card->card_chg = FALSE;
+
+ if (card->card_type != CARD_ERROR && card->card_type != CARD_NONE) {
+ if (card->state == CARD_STATE_WORKING) {
+ result = TRUE;
+ goto exit;
+ }
+ }
+
+ /* Init card here */
+ result = card_init(card, retry_num, FALSE);
+
+ /* todo degrade mode control if init failed */
+
+ /* If Card Init ok and scsi last presetn is 0 and need to enable to send bus change */
+ if (result == TRUE && pdx->scsi.last_present == 0 && send_bus_chg
+ && card->card_type != CARD_SD70) {
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "Exec Bus Change for Ins Card\n");
+
+ /* add for LCFC s3/s4 card change issue 20160830 */
+ if ((pdx->pre_card.pre_sec_count != 0)
+ && ((pdx->pre_card.pre_sec_count != pdx->card.sec_count)
+ ||
+ (os_memcpr
+ (&(pdx->pre_card.pre_cid[0]),
+ &(pdx->card.info.raw_cid[0]), CID_LEN) != CID_LEN))
+ && (pdx->pre_card.s3s4_resume_for_card_init)) {
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE,
+ NOT_TO_RAM,
+ "LCFC s3 s4 resume card change issue!\n");
+ pdx->card.card_present = FALSE;
+ thread_exec_high_prio_job(pdx, os_bus_change, pdx);
+ /* Use 500ms timer to set the card present to TRUE and send bus change */
+ pdx->auto_timer.s3reusme_cardchg_issuefix_en = TRUE;
+ pdx->auto_timer.s3reusme_timer_expect_cnt = 2;
+ pdx->auto_timer.s3reusme_timer_actual_cnt = 2;
+ } else {
+ /* callback execute successfully */
+ if (thread_exec_high_prio_job(pdx, os_bus_change, pdx))
+ pdx->scsi.last_present = 1;
+ }
+ pdx->pre_card.pre_sec_count = pdx->card.sec_count;
+ os_memcpy(&(pdx->pre_card.pre_cid[0]),
+ &(pdx->card.info.raw_cid[0]), CID_LEN);
+
+ }
+
+exit:
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "Exit %s ret=%d\n", __func__, result);
+ return result;
+
+}
+
+/*
+ * Function Name: thread_wakeup_card
+ * Abstract: This Function is used to by thread to wake up card from low power state
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ *
+ * Return value:
+ * TRUE: means ok
+ * others error
+ *
+ * Notes:
+ * run in thread context
+ */
+e_req_result thread_wakeup_card(bht_dev_ext_t *pdx)
+{
+ e_req_result result = REQ_RESULT_OK;
+ sd_card_t *card = &pdx->card;
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_RW_TRACE | FEATURE_IOCTL_TRACE,
+ NOT_TO_RAM, "Enter %s\n", __func__);
+
+ if (card->card_present == FALSE) {
+ result = REQ_RESULT_NO_CARD;
+ goto exit;
+ }
+
+ if (card->state == CARD_STATE_SLEEP ||
+ card->state == CARD_STATE_DEEP_SLEEP) {
+ if (card_resume_sleep(card, TRUE) == FALSE)
+ result = REQ_RESULT_ACCESS_ERR;
+ }
+ /* If card is power off then reinit card */
+ if (card->state == CARD_STATE_POWEROFF) {
+ if (thread_init_card(pdx, FALSE, FALSE, CARD_REINIT_RETRY) ==
+ FALSE) {
+ result = REQ_RESULT_ACCESS_ERR;
+ goto exit;
+ }
+ }
+
+exit:
+ if (result == FALSE)
+ DbgErr("Wakeup card failed\n");
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_RW_TRACE | FEATURE_IOCTL_TRACE,
+ NOT_TO_RAM, "Exit %s result=%d\n", __func__, result);
+ return result;
+}
+
+typedef struct {
+ bht_dev_ext_t *pdx;
+ srb_ext_t *srb_ext;
+} req_io_item_t;
+
+static void thread_io_done(void *p_item)
+{
+ req_io_item_t *item = p_item;
+
+ if (item->srb_ext->req.srb_done_cb)
+ item->srb_ext->req.srb_done_cb(item->pdx, item->srb_ext);
+ /* default handler */
+ else {
+ if (item->pdx)
+ item->pdx->p_srb_ext = NULL;
+ }
+
+}
+
+/*
+ * Function Name: thread_tag_io
+ * Abstract: This Function is used to by thread to trigger tag io
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ *
+ * Return value:
+ * TRUE: means ok
+ * others error
+ *
+ * Notes:
+ * run in thread context
+ */
+static void thread_tag_io(bht_dev_ext_t *pdx)
+{
+ e_req_result result;
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_RW_TRACE, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+
+ result = tag_queue_rw_data(pdx);
+ if (result == REQ_RESULT_NO_CARD || result == REQ_RESULT_ABORT) {
+ /* do nothing for low level api will cancel all io */
+ } else if (result == REQ_RESULT_ACCESS_ERR) {
+ if (tq_is_empty(pdx) == FALSE)
+ os_set_event(&pdx->os, EVENT_TAG_IO);
+ }
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_RW_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+
+}
+
+/*
+ * Function Name: thread_remove_card
+ * Abstract: This Function is used to by thread to trigger tag io
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ *
+ * Return value:
+ * TRUE: means ok
+ * others error
+ *
+ * Notes:
+ * run in thread context
+ */
+static void thread_remove_card(bht_dev_ext_t *pdx, bool eject)
+{
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "Enter %s eject=%d\n", __func__, eject);
+ if (eject == FALSE) {
+ host_init(&pdx->host);
+
+ card_stuct_uinit(&pdx->card);
+ /* host reset for all and reopen card init */
+ if (pdx->scsi.last_present == 1) {
+ /* callback execute successfully */
+ if (thread_exec_high_prio_job(pdx, os_bus_change, pdx))
+ pdx->scsi.last_present = 0;
+ }
+
+ /* When card removed or not present, let Hardware control the host main power. */
+ hostven_main_power_ctrl(&pdx->host, FALSE);
+ /* todo call ltr featre */
+ }
+ /* card is still present, and this remove is called by eject */
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM, "Exit %s\n",
+ __func__);
+
+}
+
+/*
+ * Function Name: thread_gen_io
+ * Abstract: This Function is used to by thread to trigger tag io
+ *
+ * Input:
+ * bht_dev_ext_t *pdx,
+ *
+ * Return value:
+ * TRUE: means ok
+ * others error
+ *
+ * Notes:
+ * run in thread context
+ */
+static void thread_gen_io(bht_dev_ext_t *pdx)
+{
+ e_req_result result = REQ_RESULT_OK;
+ srb_ext_t *srb_ext = pdx->p_srb_ext;
+ sd_card_t *card = &pdx->card;
+ req_io_item_t item;
+ bool ret = FALSE;
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "Enter %s\n",
+ __func__);
+ if (srb_ext == NULL)
+ goto exit;
+
+ if (srb_ext->req.type != REQ_TYPE_GEN_IO) {
+ DbgWarn(MODULE_MAIN_THR, NOT_TO_RAM,
+ "pdx srb_ext should be genio type\n");
+ goto exit;
+ }
+
+ item.pdx = pdx;
+ item.srb_ext = srb_ext;
+ os_set_dev_busy(pdx);
+
+ switch (srb_ext->req.gen_req_t.code) {
+ case GEN_IO_CODE_INIT_CARD:
+ if (thread_init_card(pdx, FALSE, TRUE, 3) == FALSE)
+ result = REQ_RESULT_NO_CARD;
+ break;
+ case GEN_IO_CODE_EJECT:
+ /* TODO currently we can only do phy card poweroff */
+ thread_remove_card(pdx, TRUE);
+ break;
+ case GEN_IO_CODE_PIORW:
+ result = thread_wakeup_card(pdx);
+ if (result == REQ_RESULT_OK) {
+ ret = card_piorw_data(card, srb_ext->req.gen_req_t.arg1,
+ srb_ext->req.gen_req_t.arg2,
+ srb_ext->req.data_dir,
+ srb_ext->req.srb_buff);
+ if (ret == TRUE)
+ break;
+ if (card->card_present == FALSE)
+ result = REQ_RESULT_NO_CARD;
+ else
+ result = REQ_RESULT_ACCESS_ERR;
+ }
+ break;
+ case GEN_IO_CODE_CPRM:
+ result = thread_wakeup_card(pdx);
+ if (result == REQ_RESULT_OK) {
+ ret = func_cprm(card, &(srb_ext->req));
+ if (ret == TRUE)
+ break;
+ result = REQ_RESULT_ACCESS_ERR;
+ if (card->card_present == FALSE)
+ result = REQ_RESULT_NO_CARD;
+ else
+ result = REQ_RESULT_ACCESS_ERR;
+ }
+ break;
+ case GEN_IO_CODE_IO:
+ ret = func_io_reg(card, &(srb_ext->req));
+
+ break;
+ case GEN_IO_CODE_NSM:
+ result = thread_wakeup_card(pdx);
+ if (result == REQ_RESULT_OK) {
+ ret = func_nsm(card, &(srb_ext->req), pdx);
+ if (ret == TRUE)
+ break;
+ result = REQ_RESULT_ACCESS_ERR;
+ if (card->card_present == FALSE)
+ result = REQ_RESULT_NO_CARD;
+ else
+ result = REQ_RESULT_ACCESS_ERR;
+ }
+ break;
+ case GEN_IO_CODE_RECFG:
+ DbgInfo(MODULE_MAIN_THR,
+ FEATURE_DRIVER_INIT | FEATURE_IOCTL_TRACE, 0,
+ "Begin do Reload Cfg\n");
+ func_autotimer_stop(pdx);
+ card_power_off(&pdx->card, FALSE);
+
+ cfgmng_init_chipcfg(pdx->host.chip_type, pdx->cfg, TRUE);
+ pdx->cfg =
+ cfgmng_get(pdx, pdx->host.chip_type, pdx->cfg->boot_flag);
+ pdx->host.cfg = pdx->cfg;
+
+ req_global_reinit(pdx);
+
+ if (card->card_present) {
+ if (thread_init_card
+ (pdx, FALSE, FALSE, CARD_REINIT_RETRY) == FALSE) {
+ result = REQ_RESULT_ACCESS_ERR;
+ break;
+ }
+ }
+
+ result = REQ_RESULT_OK;
+ break;
+ case GEN_IO_CODE_CSD:
+
+ result = thread_wakeup_card(pdx);
+ if (result == REQ_RESULT_OK) {
+
+ if (srb_ext->req.data_dir == DATA_DIR_OUT) {
+
+ ret =
+ card_program_csd(&pdx->card,
+ (u8 *) srb_ext->req.srb_buff);
+ if (!ret)
+ result = REQ_RESULT_ACCESS_ERR;
+
+ } else if (srb_ext->req.data_dir == DATA_DIR_IN) {
+
+ ret =
+ card_read_csd(&pdx->card,
+ (u8 *) srb_ext->req.srb_buff);
+ if (!ret)
+ result = REQ_RESULT_ACCESS_ERR;
+
+ }
+
+ }
+
+ break;
+
+ default:
+ /* CPRM function is to do */
+ break;
+ }
+
+ srb_ext->req.result = result;
+
+ /* As card is removed we dont' need to enable timer */
+ if (srb_ext->req.gen_req_t.code != GEN_IO_CODE_EJECT)
+ thread_exec_high_prio_job(pdx,
+ (cb_soft_intr_t) func_autotimer_start,
+ pdx);
+
+ os_set_dev_idle(pdx);
+ thread_exec_high_prio_job(pdx, thread_io_done, &item);
+
+exit:
+ DbgInfo(MODULE_MAIN_THR, FEATURE_IOCTL_TRACE, NOT_TO_RAM,
+ "Exit %s %d\n", __func__);
+}
+
+void thread_handle_card_event(bht_dev_ext_t *pdx)
+{
+ if (pdx->card.card_present) {
+ if (thread_init_card(pdx, TRUE, TRUE, CARD_FIRST_INIT_RETRY) ==
+ TRUE)
+ thread_exec_high_prio_job(pdx, (cb_soft_intr_t)
+ func_autotimer_start, pdx);
+ else if (pdx->card.card_type == CARD_SDIO) {
+ DbgInfo(MODULE_MAIN_THR, FEATURE_CARD_INIT, TO_RAM,
+ "Failed Init with SDIO\n");
+ os_set_sdio_val(pdx, 1, FALSE);
+ }
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_CARD_INIT, TO_RAM,
+ "THREAD init card\n");
+ } else {
+ thread_remove_card(pdx, FALSE);
+ DbgInfo(MODULE_MAIN_THR, FEATURE_CARD_INIT, TO_RAM,
+ "THREAD remove card\n");
+ }
+ pdx->pre_card.s3s4_resume_for_card_init = FALSE;
+
+}
+
+void thread_main(void *param)
+{
+ bht_dev_ext_t *pdx = (bht_dev_ext_t *) param;
+ e_event_t evt = EVENT_NONE;
+ os_struct *os = &pdx->os;
+
+ for (;;) {
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "thread wait evt\n");
+ evt = os_wait_event(os);
+ os_clear_event(os, evt);
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "Thr get Event=%d\n", evt);
+ switch (evt) {
+ case EVENT_CARD_CHG:
+ os_set_dev_busy(pdx);
+ if (pdx->pm_state.rtd3_en && pdx->pm_state.rtd3_entered)
+ break;
+
+ if (pdx->testcase.test_type == 0
+ || pdx->testcase.test_type == 3)
+ thread_handle_card_event(pdx);
+ else
+ /* with card test */
+ testcase_main(pdx, 1);
+
+ os_set_dev_idle(pdx);
+ break;
+ case EVENT_TERMINATE:
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, TO_RAM,
+ "terminal task\n");
+ goto exit;
+ case EVENT_PENDING:
+ os->thread.pending_lock = TRUE;
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, TO_RAM,
+ "pending thread start freeze=%d\n",
+ os->thread.freeze);
+ if (os->thread.freeze)
+ os_wait_for_completion(pdx,
+ &os->thread.break_pending, 0);
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, TO_RAM,
+ "pending thread stop\n");
+ break;
+ case EVENT_TAG_IO:
+ calc_thr_start(&pdx->tick);
+ thread_tag_io(pdx);
+ DbgInfo(MODULE_MAIN_THR, FEATURE_RW_TRACE, NOT_TO_RAM,
+ "rw evt task\n");
+ break;
+ case EVENT_GEN_IO:
+ thread_gen_io(pdx);
+ DbgInfo(MODULE_MAIN_THR, FEATURE_IOCTL_TRACE,
+ NOT_TO_RAM, "io_ctl task\n");
+ break;
+ case EVENT_RUNTIME_D3:
+ DbgInfo(MODULE_MAIN_THR, FEATURE_PM_TRACE, TO_RAM,
+ "rtd3 task\n");
+ os_rtd3_req_wait_wake(pdx);
+ break;
+ case EVENT_AUTO_TIMER:
+ func_timer_thread(pdx);
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE,
+ NOT_TO_RAM, "autoTimer task\n");
+ break;
+ case EVENT_SDIO:
+ DbgInfo(MODULE_MAIN_THR, MODULE_OTHER_CARD, TO_RAM,
+ "sdio task\n");
+ break;
+
+ default:
+ break;
+ }
+
+ DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
+ "Thr done Event=%d\n", evt);
+
+ }
+exit:
+ DbgInfo(MODULE_MAIN_THR, FEATURE_DRIVER_INIT, NOT_TO_RAM,
+ "exit thread\n");
+}