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; }
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 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 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 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); }
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 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 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 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 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 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 ms_read_bytes(struct realtek_pci_ms *host, u8 tpc, u8 cfg, u8 cnt, u8 *data, u8 *int_reg) { struct rtsx_pcr *pcr = host->pcr; int err, i; u8 *ptr; dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc); if (!data) return -EINVAL; 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_BYTE_CNT, 0xFF, cnt); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); for (i = 0; i < cnt - 1; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); if (cnt % 2) rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0); else rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt - 1, 0, 0); if (int_reg) rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0); err = rtsx_pci_send_cmd(pcr, 5000); if (err < 0) { u8 val; rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val); dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val); if (int_reg) *int_reg = val & 0x0F; ms_print_debug_regs(host); ms_clear_error(host); if (!(tpc & 0x08)) { if (val & MS_CRC16_ERR) return -EIO; } else { if (!(val & 0x80)) { if (val & (MS_INT_ERR | MS_INT_CMDNK)) return -EIO; } } return -ETIMEDOUT; } ptr = rtsx_pci_get_cmd_data(pcr) + 1; for (i = 0; i < cnt; i++) data[i] = *ptr++; if (int_reg) *int_reg = *ptr & 0x0F; return 0; }
static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) { struct rtsx_pcr *pcr = host->pcr; u8 cmd_idx = (u8)cmd->opcode; u32 arg = cmd->arg; int err = 0; int timeout = 100; int i; u8 *ptr; int stat_idx = 0; u8 rsp_type; int rsp_len = 5; bool clock_toggled = false; dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", __func__, cmd_idx, arg); /* Response type: * R0 * R1, R5, R6, R7 * R1b * R2 * R3, R4 */ switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: rsp_type = SD_RSP_TYPE_R0; rsp_len = 0; break; case MMC_RSP_R1: rsp_type = SD_RSP_TYPE_R1; break; case MMC_RSP_R1 & ~MMC_RSP_CRC: rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; break; case MMC_RSP_R1B: rsp_type = SD_RSP_TYPE_R1b; break; case MMC_RSP_R2: rsp_type = SD_RSP_TYPE_R2; rsp_len = 16; break; case MMC_RSP_R3: rsp_type = SD_RSP_TYPE_R3; break; default: dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n"); err = -EINVAL; goto out; } if (rsp_type == SD_RSP_TYPE_R1b) timeout = 3000; if (cmd->opcode == SD_SWITCH_VOLTAGE) { err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); if (err < 0) goto out; clock_toggled = true; } rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); 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, SD_TM_CMD_RSP | SD_TRANSFER_START); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE); if (rsp_type == SD_RSP_TYPE_R2) { /* Read data from ping-pong buffer */ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); stat_idx = 16; } else if (rsp_type != SD_RSP_TYPE_R0) { /* Read data from SD_CMDx registers */ for (i = SD_CMD0; i <= SD_CMD4; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); stat_idx = 5; } rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); err = rtsx_pci_send_cmd(pcr, timeout); if (err < 0) { sd_print_debug_regs(host); sd_clear_error(host); dev_dbg(sdmmc_dev(host), "rtsx_pci_send_cmd error (err = %d)\n", err); goto out; } if (rsp_type == SD_RSP_TYPE_R0) { err = 0; goto out; } /* Eliminate returned value of CHECK_REG_CMD */ ptr = rtsx_pci_get_cmd_data(pcr) + 1; /* Check (Start,Transmission) bit of Response */ if ((ptr[0] & 0xC0) != 0) { err = -EILSEQ; dev_dbg(sdmmc_dev(host), "Invalid response bit\n"); goto out; } /* Check CRC7 */ if (!(rsp_type & SD_NO_CHECK_CRC7)) { if (ptr[stat_idx] & SD_CRC7_ERR) { err = -EILSEQ; dev_dbg(sdmmc_dev(host), "CRC7 error\n"); goto out; } } if (rsp_type == SD_RSP_TYPE_R2) { /* * The controller offloads the last byte {CRC-7, end bit 1'b1} * of response type R2. Assign dummy CRC, 0, and end bit to the * byte(ptr[16], goes into the LSB of resp[3] later). */ ptr[16] = 1; for (i = 0; i < 4; i++) { cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", i, cmd->resp[i]); } } else { cmd->resp[0] = get_unaligned_be32(ptr + 1); dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", cmd->resp[0]); } out: cmd->error = err; if (err && clock_toggled) rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); }