int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, int num_sg, bool read, int timeout) { int err = 0, count; pcr_dbg(pcr, "--> %s: num_sg = %d\n", __func__, num_sg); count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read); if (count < 1) return -EINVAL; pcr_dbg(pcr, "DMA mapping count: %d\n", count); err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout); rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); return err; }
int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout) { struct completion trans_done; u32 val = 1 << 31; long timeleft; unsigned long flags; int err = 0; spin_lock_irqsave(&pcr->lock, flags); /* set up data structures for the wakeup system */ pcr->done = &trans_done; pcr->trans_result = TRANS_NOT_READY; init_completion(&trans_done); rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr); val |= (u32)(pcr->ci * 4) & 0x00FFFFFF; /* Hardware Auto Response */ val |= 0x40000000; rtsx_pci_writel(pcr, RTSX_HCBCTLR, val); spin_unlock_irqrestore(&pcr->lock, flags); /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout( &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__); err = -ETIMEDOUT; goto finish_send_cmd; } spin_lock_irqsave(&pcr->lock, flags); if (pcr->trans_result == TRANS_RESULT_FAIL) err = -EINVAL; else if (pcr->trans_result == TRANS_RESULT_OK) err = 0; else if (pcr->trans_result == TRANS_NO_DEVICE) err = -ENODEV; spin_unlock_irqrestore(&pcr->lock, flags); finish_send_cmd: spin_lock_irqsave(&pcr->lock, flags); pcr->done = NULL; spin_unlock_irqrestore(&pcr->lock, flags); if ((err < 0) && (err != -ENODEV)) rtsx_pci_stop_cmd(pcr); if (pcr->finish_me) complete(pcr->finish_me); return err; }
static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr) { u32 reg1 = 0; u8 reg3 = 0; rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®1); pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1); if (!rtsx_vendor_setting_valid(reg1)) return; pcr->aspm_en = rtsx_reg_to_aspm(reg1); pcr->sd30_drive_sel_1v8 = map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1)); pcr->card_drive_sel &= 0x3F; pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1); rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, ®3); pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3); pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3); }
static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr) { u32 reg; rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); if (!rtsx_vendor_setting_valid(reg)) { pcr_dbg(pcr, "skip fetch vendor setting\n"); return; } pcr->aspm_en = rtsx_reg_to_aspm(reg); pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg); pcr->card_drive_sel &= 0x3F; pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); if (rtsx_reg_check_reverse_socket(reg)) pcr->flags |= PCR_REVERSE_SOCKET; }
static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) { unsigned int card_exist; card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); card_exist &= CARD_EXIST; if (!card_exist) { /* Enable card CD */ rtsx_pci_write_register(pcr, CD_PAD_CTL, CD_DISABLE_MASK, CD_ENABLE); /* Enable card interrupt */ rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00); return 0; } if (hweight32(card_exist) > 1) { rtsx_pci_write_register(pcr, CARD_PWR_CTL, BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); msleep(100); card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); if (card_exist & MS_EXIST) card_exist = MS_EXIST; else if (card_exist & SD_EXIST) card_exist = SD_EXIST; else card_exist = 0; rtsx_pci_write_register(pcr, CARD_PWR_CTL, BPP_POWER_MASK, BPP_POWER_OFF); pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n", card_exist); } if (card_exist & MS_EXIST) { /* Disable SD interrupt */ rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40); rtsx_pci_write_register(pcr, CD_PAD_CTL, CD_DISABLE_MASK, MS_CD_EN_ONLY); } else if (card_exist & SD_EXIST) { /* Disable MS interrupt */ rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80); rtsx_pci_write_register(pcr, CD_PAD_CTL, CD_DISABLE_MASK, SD_CD_EN_ONLY); } return card_exist; }
static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr, dma_addr_t addr, unsigned int len, int end) { u64 *ptr = (u64 *)(pcr->host_sg_tbl_ptr) + pcr->sgi; u64 val; u8 option = SG_VALID | SG_TRANS_DATA; pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); if (end) option |= SG_END; val = ((u64)addr << 32) | ((u64)len << 12) | option; put_unaligned_le64(val, ptr); pcr->sgi++; }
static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) { u32 reg = 0; rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); if (!rtsx_vendor_setting_valid(reg)) return; pcr->aspm_en = rtsx_reg_to_aspm(reg); pcr->sd30_drive_sel_1v8 = map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg)); pcr->sd30_drive_sel_3v3 = map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg)); }
static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { int err; u16 append; switch (voltage) { case OUTPUT_3V3: err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK, PHY_TUNE_VOLTAGE_3V3); if (err < 0) return err; break; case OUTPUT_1V8: append = PHY_TUNE_D18_1V8; if (CHK_PCI_PID(pcr, 0x5249)) { err = rtsx_pci_update_phy(pcr, PHY_BACR, PHY_BACR_BASIC_MASK, 0); if (err < 0) return err; append = PHY_TUNE_D18_1V7; } err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK, append); if (err < 0) return err; break; default: pcr_dbg(pcr, "unknown output voltage %d\n", voltage); return -EINVAL; } /* set pad drive */ rtsx_pci_init_cmd(pcr); rts5249_fill_driving(pcr, voltage); return rtsx_pci_send_cmd(pcr, 100); }
static void rts5260_pwr_saving_setting(struct rtsx_pcr *pcr) { int lss_l1_1, lss_l1_2; lss_l1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN) | rtsx_check_dev_flag(pcr, PM_L1_1_EN); lss_l1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN) | rtsx_check_dev_flag(pcr, PM_L1_2_EN); if (lss_l1_2) { pcr_dbg(pcr, "Set parameters for L1.2."); rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL, 0xFF, PCIE_L1_2_EN); rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL, RTS5260_DVCC_OCP_EN | RTS5260_DVCC_OCP_CL_EN, RTS5260_DVCC_OCP_EN | RTS5260_DVCC_OCP_CL_EN); rtsx_pci_write_register(pcr, PWR_FE_CTL, 0xFF, PCIE_L1_2_PD_FE_EN); } else if (lss_l1_1) { pcr_dbg(pcr, "Set parameters for L1.1."); rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL, 0xFF, PCIE_L1_1_EN); rtsx_pci_write_register(pcr, PWR_FE_CTL, 0xFF, PCIE_L1_1_PD_FE_EN); } else { pcr_dbg(pcr, "Set parameters for L1."); rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL, 0xFF, PCIE_L1_0_EN); rtsx_pci_write_register(pcr, PWR_FE_CTL, 0xFF, PCIE_L1_0_PD_FE_EN); } rtsx_pci_write_register(pcr, CFG_L1_0_PCIE_DPHY_RET_VALUE, 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); rtsx_pci_write_register(pcr, CFG_L1_0_PCIE_MAC_RET_VALUE, 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); rtsx_pci_write_register(pcr, CFG_L1_0_CRC_SD30_RET_VALUE, 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); rtsx_pci_write_register(pcr, CFG_L1_0_CRC_SD40_RET_VALUE, 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); rtsx_pci_write_register(pcr, CFG_L1_0_SYS_RET_VALUE, 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); /*Option cut APHY*/ rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_0, 0xFF, CFG_PCIE_APHY_OFF_0_DEFAULT); rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_1, 0xFF, CFG_PCIE_APHY_OFF_1_DEFAULT); rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_2, 0xFF, CFG_PCIE_APHY_OFF_2_DEFAULT); rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_3, 0xFF, CFG_PCIE_APHY_OFF_3_DEFAULT); /*CDR DEC*/ rtsx_pci_write_register(pcr, PWC_CDR, 0xFF, PWC_CDR_DEFAULT); /*PWMPFM*/ rtsx_pci_write_register(pcr, CFG_LP_FPWM_VALUE, 0xFF, CFG_LP_FPWM_VALUE_DEFAULT); /*No Power Saving WA*/ rtsx_pci_write_register(pcr, CFG_L1_0_CRC_MISC_RET_VALUE, 0xFF, CFG_L1_0_CRC_MISC_RET_VALUE_DEFAULT); }