static int rtsx_pci_ms_set_param(struct memstick_host *msh, enum memstick_param param, int value) { struct realtek_pci_ms *host = memstick_priv(msh); struct rtsx_pcr *pcr = host->pcr; unsigned int clock = 0; u8 ssc_depth = 0; int err; dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", __func__, param, value); err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD); if (err) return err; switch (param) { case MEMSTICK_POWER: if (value == MEMSTICK_POWER_ON) err = ms_power_on(host); else if (value == MEMSTICK_POWER_OFF) err = ms_power_off(host); else return -EINVAL; break; case MEMSTICK_INTERFACE: if (value == MEMSTICK_SERIAL) { clock = 19000000; ssc_depth = RTSX_SSC_DEPTH_500K; err = rtsx_pci_write_register(pcr, MS_CFG, 0x18, MS_BUS_WIDTH_1); if (err < 0) return err; } else if (value == MEMSTICK_PAR4) { clock = 39000000; ssc_depth = RTSX_SSC_DEPTH_1M; err = rtsx_pci_write_register(pcr, MS_CFG, 0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD); if (err < 0) return err; } else { return -EINVAL; } err = rtsx_pci_switch_clock(pcr, clock, ssc_depth, false, true, false); if (err < 0) return err; host->ssc_depth = ssc_depth; host->clock = clock; host->ifmode = value; break; } return 0; }
static void rtsx_pci_ms_handle_req(struct work_struct *work) { struct realtek_pci_ms *host = container_of(work, struct realtek_pci_ms, handle_req); struct rtsx_pcr *pcr = host->pcr; struct memstick_host *msh = host->msh; int rc; mutex_lock(&pcr->pcr_mutex); rtsx_pci_start_run(pcr); rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth, false, true, false); rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL); rtsx_pci_write_register(pcr, CARD_SHARE_MODE, CARD_SHARE_MASK, CARD_SHARE_48_MS); if (!host->req) { do { rc = memstick_next_req(msh, &host->req); dev_dbg(ms_dev(host), "next req %d\n", rc); if (!rc) host->req->error = rtsx_pci_ms_issue_cmd(host); } while (!rc); } mutex_unlock(&pcr->pcr_mutex); }
static void sd_request(struct work_struct *work) { struct realtek_pci_sdmmc *host = container_of(work, struct realtek_pci_sdmmc, work); struct rtsx_pcr *pcr = host->pcr; struct mmc_host *mmc = host->mmc; struct mmc_request *mrq = host->mrq; struct mmc_command *cmd = mrq->cmd; struct mmc_data *data = mrq->data; unsigned int data_size = 0; int err; if (host->eject) { cmd->error = -ENOMEDIUM; goto finish; } err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); if (err) { cmd->error = err; goto finish; } mutex_lock(&pcr->pcr_mutex); rtsx_pci_start_run(pcr); rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, host->initial_mode, host->double_clk, host->vpclk); rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL); rtsx_pci_write_register(pcr, CARD_SHARE_MODE, CARD_SHARE_MASK, CARD_SHARE_48_SD); mutex_lock(&host->host_mutex); host->mrq = mrq; mutex_unlock(&host->host_mutex); if (mrq->data) data_size = data->blocks * data->blksz; if (!data_size || sd_rw_cmd(cmd)) { sd_send_cmd_get_rsp(host, cmd); if (!cmd->error && data_size) { sd_rw_multi(host, mrq); if (!host->using_cookie) sdmmc_post_req(host->mmc, host->mrq, 0); if (mmc_op_multi(cmd->opcode) && mrq->stop) sd_send_cmd_get_rsp(host, mrq->stop); } } else { sd_normal_rw(host, mrq); } if (mrq->data) { if (cmd->error || data->error) data->bytes_xfered = 0; else data->bytes_xfered = data->blocks * data->blksz; } mutex_unlock(&pcr->pcr_mutex); finish: if (cmd->error) dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); mutex_lock(&host->host_mutex); host->mrq = NULL; mutex_unlock(&host->host_mutex); mmc_request_done(mmc, mrq); }
static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct realtek_pci_sdmmc *host = mmc_priv(mmc); struct rtsx_pcr *pcr = host->pcr; struct mmc_command *cmd = mrq->cmd; struct mmc_data *data = mrq->data; unsigned int data_size = 0; if (host->eject) { cmd->error = -ENOMEDIUM; goto finish; } mutex_lock(&pcr->pcr_mutex); rtsx_pci_start_run(pcr); rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, host->initial_mode, host->double_clk, host->vpclk); rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL); rtsx_pci_write_register(pcr, CARD_SHARE_MODE, CARD_SHARE_MASK, CARD_SHARE_48_SD); mutex_lock(&host->host_mutex); host->mrq = mrq; mutex_unlock(&host->host_mutex); if (mrq->data) data_size = data->blocks * data->blksz; if (!data_size || mmc_op_multi(cmd->opcode) || (cmd->opcode == MMC_READ_SINGLE_BLOCK) || (cmd->opcode == MMC_WRITE_BLOCK)) { sd_send_cmd_get_rsp(host, cmd); if (!cmd->error && data_size) { sd_rw_multi(host, mrq); if (mmc_op_multi(cmd->opcode) && mrq->stop) sd_send_cmd_get_rsp(host, mrq->stop); } } else { sd_normal_rw(host, mrq); } if (mrq->data) { if (cmd->error || data->error) data->bytes_xfered = 0; else data->bytes_xfered = data->blocks * data->blksz; } mutex_unlock(&pcr->pcr_mutex); finish: if (cmd->error) dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); mutex_lock(&host->host_mutex); host->mrq = NULL; mutex_unlock(&host->host_mutex); mmc_request_done(mmc, mrq); }