void do_remaining_work(struct rtsx_chip *chip) { struct sd_info *sd_card = &(chip->sd_card); #ifdef XD_DELAY_WRITE struct xd_info *xd_card = &(chip->xd_card); #endif struct ms_info *ms_card = &(chip->ms_card); if (chip->card_ready & SD_CARD) { if (sd_card->seq_mode) { rtsx_set_stat(chip, RTSX_STAT_RUN); sd_card->cleanup_counter ++; } else { sd_card->cleanup_counter = 0; } } #ifdef XD_DELAY_WRITE if (chip->card_ready & XD_CARD) { if (xd_card->delay_write.delay_write_flag) { rtsx_set_stat(chip, RTSX_STAT_RUN); xd_card->cleanup_counter ++; } else { xd_card->cleanup_counter = 0; } } #endif if (chip->card_ready & MS_CARD) { if (CHK_MSPRO(ms_card)) { if (ms_card->seq_mode) { rtsx_set_stat(chip, RTSX_STAT_RUN); ms_card->cleanup_counter ++; } else { ms_card->cleanup_counter = 0; } } else { #ifdef MS_DELAY_WRITE if (ms_card->delay_write.delay_write_flag) { rtsx_set_stat(chip, RTSX_STAT_RUN); ms_card->cleanup_counter ++; } else { ms_card->cleanup_counter = 0; } #endif } } if (sd_card->cleanup_counter > POLLING_WAIT_CNT) { sd_cleanup_work(chip); } if (xd_card->cleanup_counter > POLLING_WAIT_CNT) { xd_cleanup_work(chip); } if (ms_card->cleanup_counter > POLLING_WAIT_CNT) { ms_cleanup_work(chip); } }
int switch_ssc_clock(struct rtsx_chip *chip, int clk) { struct sd_info *sd_card = &(chip->sd_card); struct ms_info *ms_card = &(chip->ms_card); int retval; u8 N = (u8)(clk - 2), min_N, max_N; u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask; int sd_vpclk_phase_reset = 0; if (chip->cur_clk == clk) return STATUS_SUCCESS; if (CHECK_PID(chip, 0x5209)) { min_N = 80; max_N = 208; max_div = CLK_DIV_8; } else { min_N = 60; max_N = 120; max_div = CLK_DIV_4; } if (CHECK_PID(chip, 0x5209) && (chip->cur_card == SD_CARD)) { struct sd_info *sd_card = &(chip->sd_card); if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card)) sd_vpclk_phase_reset = 1; } RTSX_DEBUGP("Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk); if ((clk <= 2) || (N > max_N)) { TRACE_RET(chip, STATUS_FAIL); } mcu_cnt = (u8)(125/clk + 3); if (CHECK_PID(chip, 0x5209)) { if (mcu_cnt > 15) mcu_cnt = 15; } else { if (mcu_cnt > 7) mcu_cnt = 7; } div = CLK_DIV_1; while ((N < min_N) && (div < max_div)) { N = (N + 2) * 2 - 2; div++; } RTSX_DEBUGP("N = %d, div = %d\n", N, div); if (chip->ssc_en) { if (CHECK_PID(chip, 0x5209)) { if (chip->cur_card == SD_CARD) { if (CHK_SD_SDR104(sd_card)) { ssc_depth = chip->ssc_depth_sd_sdr104; } else if (CHK_SD_SDR50(sd_card)) { ssc_depth = chip->ssc_depth_sd_sdr50; } else if (CHK_SD_DDR50(sd_card)) { ssc_depth = double_depth(chip->ssc_depth_sd_ddr50); } else if (CHK_SD_HS(sd_card)) { ssc_depth = double_depth(chip->ssc_depth_sd_hs); } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { ssc_depth = double_depth(chip->ssc_depth_mmc_52m); } else { ssc_depth = double_depth(chip->ssc_depth_low_speed); } } else if (chip->cur_card == MS_CARD) { if (CHK_MSPRO(ms_card)) { if (CHK_HG8BIT(ms_card)) { ssc_depth = double_depth(chip->ssc_depth_ms_hg); } else { ssc_depth = double_depth(chip->ssc_depth_ms_4bit); } } else { if (CHK_MS4BIT(ms_card)) { ssc_depth = double_depth(chip->ssc_depth_ms_4bit); } else { ssc_depth = double_depth(chip->ssc_depth_low_speed); } } } else { ssc_depth = double_depth(chip->ssc_depth_low_speed); } if (ssc_depth) { if (div == CLK_DIV_2) { if (ssc_depth > 1) { ssc_depth -= 1; } else { ssc_depth = SSC_DEPTH_4M; } } else if (div == CLK_DIV_4) { if (ssc_depth > 2) { ssc_depth -= 2; } else { ssc_depth = SSC_DEPTH_4M; } } else if (div == CLK_DIV_8) { if (ssc_depth > 3) { ssc_depth -= 3; } else { ssc_depth = SSC_DEPTH_4M; } } } } else { ssc_depth = 0x01; N -= 2; } } else { ssc_depth = 0; } if (CHECK_PID(chip, 0x5209)) { ssc_depth_mask = SSC_DEPTH_MASK; } else { ssc_depth_mask = 0x03; } RTSX_DEBUGP("ssc_depth = %d\n", ssc_depth); rtsx_init_cmd(chip); rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); if (sd_vpclk_phase_reset) { rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); } retval = rtsx_send_cmd(chip, 0, WAIT_TIME); if (retval < 0) { TRACE_RET(chip, STATUS_ERROR); } udelay(10); RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); chip->cur_clk = clk; return STATUS_SUCCESS; }