static int rts5249_card_power_on(struct rtsx_pcr *pcr, int card) { int err; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x02); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; msleep(5); rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, SD_POWER_MASK, SD_VCC_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x06); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; return 0; }
static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card) { int err; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, SD_POWER_MASK, SD_PARTIAL_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x02); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; /* To avoid too large in-rush current */ udelay(150); rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, SD_POWER_MASK, SD_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x06); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; return 0; }
static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) { u16 cap; rtsx_pci_init_cmd(pcr); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); /* Switch LDO3318 source from DV33 to card_3v3 */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); /* Configure LTR */ pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap); if (cap & PCI_EXP_DEVCTL2_LTR_EN) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); /* Configure OBFF */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); /* Configure driving */ rts5227_fill_driving(pcr, OUTPUT_3V3); /* Configure force_clock_req */ if (pcr->flags & PCR_REVERSE_SOCKET) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); /* Reset ASPM state to default value */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0); /* Switch LDO3318 source from DV33 to card_3v3 */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); /* Configure driving */ rts5249_fill_driving(pcr, OUTPUT_3V3); if (pcr->flags & PCR_REVERSE_SOCKET) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); return rtsx_pci_send_cmd(pcr, 100); }
int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val) { int err, i, finished = 0; u8 tmp; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; for (i = 0; i < 100000; i++) { err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp); if (err < 0) return err; if (!(tmp & 0x80)) { finished = 1; break; } } if (!finished) return -ETIMEDOUT; return 0; }
static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point, bool rx) { struct rtsx_pcr *pcr = host->pcr; int err; dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n", __func__, rx ? "RX" : "TX", sample_point); rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK); if (rx) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPTX_CTL, 0x1F, sample_point); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; return 0; }
static int ms_power_on(struct realtek_pci_ms *host) { struct rtsx_pcr *pcr = host->pcr; int err; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, CARD_SHARE_MASK, CARD_SHARE_48_MS); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, MS_CLK_EN); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD); if (err < 0) return err; err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD); if (err < 0) return err; /* Wait ms power stable */ msleep(150); err = rtsx_pci_write_register(pcr, CARD_OE, MS_OUTPUT_EN, MS_OUTPUT_EN); if (err < 0) return err; return 0; }
static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir, u8 tpc, u8 cfg, struct scatterlist *sg) { struct rtsx_pcr *pcr = host->pcr; int err; unsigned int length = sg->length; u16 sec_cnt = (u16)(length / 512); u8 val, trans_mode, dma_dir; dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n", __func__, tpc, (data_dir == READ) ? "READ" : "WRITE", length); if (data_dir == READ) { dma_dir = DMA_DIR_FROM_CARD; trans_mode = MS_TM_AUTO_READ; } else { dma_dir = DMA_DIR_TO_CARD; trans_mode = MS_TM_AUTO_WRITE; } rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); rtsx_pci_send_cmd_no_wait(pcr); err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000); if (err < 0) { ms_clear_error(host); return err; } rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val); if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) return -EIO; return 0; }
static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, u8 *buf, int buf_len, int timeout) { struct rtsx_pcr *pcr = host->pcr; int err, i; u8 trans_mode; dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, cmd[0] - 0x40); if (!buf) buf_len = 0; if ((cmd[0] & 0x3F) == MMC_SEND_TUNING_BLOCK) trans_mode = SD_TM_AUTO_TUNING; else trans_mode = SD_TM_NORMAL_READ; rtsx_pci_init_cmd(pcr); for (i = 0; i < 5; i++) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); if (trans_mode != SD_TM_AUTO_TUNING) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); err = rtsx_pci_send_cmd(pcr, timeout); if (err < 0) { sd_print_debug_regs(host); dev_dbg(sdmmc_dev(host), "rtsx_pci_send_cmd fail (err = %d)\n", err); return err; } if (buf && buf_len) { err = rtsx_pci_read_ppbuf(pcr, buf, buf_len); if (err < 0) { dev_dbg(sdmmc_dev(host), "rtsx_pci_read_ppbuf fail (err = %d)\n", err); return err; } } return 0; }
int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val) { int err, i, finished = 0; u16 data; u8 *ptr, tmp; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; for (i = 0; i < 100000; i++) { err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp); if (err < 0) return err; if (!(tmp & 0x80)) { finished = 1; break; } } if (!finished) return -ETIMEDOUT; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0); rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; ptr = rtsx_pci_get_cmd_data(pcr); data = ((u16)ptr[1] << 8) | ptr[0]; if (val) *val = data; return 0; }
static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card) { rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, SD_POWER_MASK, SD_POWER_OFF); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x00); return rtsx_pci_send_cmd(pcr, 100); }
static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, u8 *buf, int buf_len, int timeout) { struct rtsx_pcr *pcr = host->pcr; int err, i; u8 trans_mode; if (!buf) buf_len = 0; if (buf && buf_len) { err = rtsx_pci_write_ppbuf(pcr, buf, buf_len); if (err < 0) { dev_dbg(sdmmc_dev(host), "rtsx_pci_write_ppbuf fail (err = %d)\n", err); return err; } } trans_mode = cmd ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3; rtsx_pci_init_cmd(pcr); if (cmd) { dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d\n", __func__, cmd[0] - 0x40); for (i = 0; i < 5; i++) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]); } rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); err = rtsx_pci_send_cmd(pcr, timeout); if (err < 0) { sd_print_debug_regs(host); dev_dbg(sdmmc_dev(host), "rtsx_pci_send_cmd fail (err = %d)\n", err); return err; } return 0; }
static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 0xFF, pcr->sd30_drive_sel_3v3); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5209_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); /* Turn off LED */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5229_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); /* Switch LDO3318 source from DV33 to card_3v3 */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFE78, 0x03, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFE78, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFC1E, 0x0F, 0x02); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card) { int err; u8 pwr_mask, partial_pwr_on, pwr_on; pwr_mask = SD_POWER_MASK; partial_pwr_on = SD_PARTIAL_POWER_ON; pwr_on = SD_POWER_ON; if (pcr->ms_pmos && (card == RTSX_MS_CARD)) { pwr_mask = MS_POWER_MASK; partial_pwr_on = MS_PARTIAL_POWER_ON; pwr_on = MS_POWER_ON; } rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, partial_pwr_on); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x04); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; /* To avoid too large in-rush current */ udelay(150); rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x00); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; return 0; }
static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); if (rtl8411b_is_qfn48(pcr)) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xF5); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 0xFF, pcr->sd30_drive_sel_3v3); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL, 0x06, 0x00); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) { u8 pwr_mask, pwr_off; pwr_mask = SD_POWER_MASK; pwr_off = SD_POWER_OFF; if (pcr->ms_pmos && (card == RTSX_MS_CARD)) { pwr_mask = MS_POWER_MASK; pwr_off = MS_POWER_OFF; } rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0X06); return rtsx_pci_send_cmd(pcr, 100); }
static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) { struct rtsx_pcr *pcr = host->pcr; u16 i; u8 *ptr; /* Print SD host internal registers */ rtsx_pci_init_cmd(pcr); for (i = 0xFDA0; i <= 0xFDAE; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); for (i = 0xFD52; i <= 0xFD69; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); rtsx_pci_send_cmd(pcr, 100); ptr = rtsx_pci_get_cmd_data(pcr); for (i = 0xFDA0; i <= 0xFDAE; i++) dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); for (i = 0xFD52; i <= 0xFD69; i++) dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); }
static int ms_power_off(struct realtek_pci_ms *host) { struct rtsx_pcr *pcr = host->pcr; int err; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD); if (err < 0) return err; return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD); }
static int rts5229_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); /* Reset ASPM state to default value */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0); /* Force CLKREQ# PIN to drive 0 to request clock */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08); /* Switch LDO3318 source from DV33 to card_3v3 */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); /* Configure driving */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 0xFF, pcr->sd30_drive_sel_3v3); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) { rtsx_pci_init_cmd(pcr); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); /* Switch LDO3318 source from DV33 to card_3v3 */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); /* Correct driving */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, 0xFF, 0x99); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, 0xFF, 0x99); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, 0xFF, 0x92); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) { struct rtsx_cr_option *option = &(pcr->option); rts5249_init_from_cfg(pcr); rts5249_init_from_hw(pcr); rtsx_pci_init_cmd(pcr); /* Rest L1SUB Config */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00); /* Configure GPIO as output */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); /* Reset ASPM state to default value */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0); /* Switch LDO3318 source from DV33 to card_3v3 */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); /* LED shine disabled, set initial shine cycle period */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); /* Configure driving */ rts5249_fill_driving(pcr, OUTPUT_3V3); if (pcr->flags & PCR_REVERSE_SOCKET) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80); /* * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced * to drive low, and we forcibly request clock. */ if (option->force_clkreq_0) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); return rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF); }
static int rts525a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { switch (voltage) { case OUTPUT_3V3: rtsx_pci_write_register(pcr, LDO_CONFIG2, LDO_D3318_MASK, LDO_D3318_33V); rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, 0); break; case OUTPUT_1V8: rtsx_pci_write_register(pcr, LDO_CONFIG2, LDO_D3318_MASK, LDO_D3318_18V); rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, SD_IO_USING_1V8); break; default: return -EINVAL; } rtsx_pci_init_cmd(pcr); rts5249_fill_driving(pcr, voltage); return rtsx_pci_send_cmd(pcr, 100); }
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 int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card) { int err; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL, BPP_LDO_POWB, BPP_LDO_SUSPEND); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; /* To avoid too large in-rush current */ udelay(150); err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON); if (err < 0) return err; udelay(150); err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON); if (err < 0) return err; udelay(150); err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, BPP_POWER_MASK, BPP_POWER_ON); if (err < 0) return err; return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON); }
static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { int err; u8 clk_drive, cmd_drive, dat_drive; if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24); if (err < 0) return err; clk_drive = 0x99; cmd_drive = 0x99; dat_drive = 0x92; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02); if (err < 0) return err; err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24); if (err < 0) return err; clk_drive = 0xb3; cmd_drive = 0xb3; dat_drive = 0xb3; } else { return -EINVAL; } /* set pad drive */ rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, 0xFF, clk_drive); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, 0xFF, cmd_drive); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, 0xFF, dat_drive); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { int err; if (voltage == OUTPUT_3V3) { err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24); if (err < 0) return err; } else if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02); if (err < 0) return err; err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24); if (err < 0) return err; } else { return -EINVAL; } /* set pad drive */ rtsx_pci_init_cmd(pcr); rts5249_fill_driving(pcr, voltage); return rtsx_pci_send_cmd(pcr, 100); }
static int rts5260_init_hw(struct rtsx_pcr *pcr) { int err; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG1, AUX_CLK_ACTIVE_SEL_MASK, MAC_CKSW_DONE); /* Rest L1SUB Config */ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CLK_FORCE_CTL, CLK_PM_EN, CLK_PM_EN); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWD_SUSPEND_EN, 0xFF, 0xFF); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, PWR_GATE_EN, PWR_GATE_EN); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, REG_VREF, PWD_SUSPND_EN, PWD_SUSPND_EN); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RBCTL, U_AUTO_DMA_EN_MASK, U_AUTO_DMA_DISABLE); if (pcr->flags & PCR_REVERSE_SOCKET) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, OBFF_EN_MASK, OBFF_DISABLE); err = rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF); if (err < 0) return err; rtsx_pci_init_ocp(pcr); return 0; }
static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) { struct rtsx_pcr *pcr = host->pcr; struct mmc_host *mmc = host->mmc; struct mmc_card *card = mmc->card; struct mmc_data *data = mrq->data; int uhs = mmc_card_uhs(card); int read = (data->flags & MMC_DATA_READ) ? 1 : 0; u8 cfg2, trans_mode; int err; size_t data_len = data->blksz * data->blocks; if (read) { cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; trans_mode = SD_TM_AUTO_READ_3; } else { cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; trans_mode = SD_TM_AUTO_WRITE_3; } if (!uhs) cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, (u8)data->blocks); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, (u8)(data->blocks >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(data_len >> 24)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(data_len >> 16)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(data_len >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); if (read) { rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, DMA_DIR_FROM_CARD | DMA_EN | DMA_512); } else { rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, DMA_DIR_TO_CARD | DMA_EN | DMA_512); } rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); rtsx_pci_send_cmd_no_wait(pcr); err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000); if (err < 0) { sd_clear_error(host); return err; } return 0; }