static void dw_mci_exynos_register_dump(struct dw_mci *host) { bool is_smu; is_smu = (host->pdata->quirks & DW_MCI_QUIRK_BYPASS_SMU) ? true : false; if (is_smu) { dev_err(host->dev, ": EMMCP_BASE: 0x%08x\n", mci_readl(host, EMMCP_BASE)); dev_err(host->dev, ": MPSTAT: 0x%08x\n", mci_readl(host, MPSTAT)); dev_err(host->dev, ": MPSBEGIN: 0x%08x\n", mci_readl(host, MPSBEGIN0)); dev_err(host->dev, ": MPSEND: 0x%08x\n", mci_readl(host, MPSEND0)); dev_err(host->dev, ": MPSCTRL: 0x%08x\n", mci_readl(host, MPSCTRL0)); } dev_err(host->dev, ": DDR200_RDDQS_EN: 0x%08x\n", mci_readl(host, DDR200_RDDQS_EN)); dev_err(host->dev, ": DDR200_ASYNC_FIFO_CTRL: 0x%08x\n", mci_readl(host, DDR200_ASYNC_FIFO_CTRL)); dev_err(host->dev, ": DDR200_DLINE_CTRL: 0x%08x\n", mci_readl(host, DDR200_DLINE_CTRL)); }
static int dw_mci_3_3v_signal_voltage_switch(struct dw_mci_slot *slot) { struct dw_mci *host = slot->host; u32 reg; int ret = 0; ret = dw_mci_set_sel18(0); if (ret) { dev_err(host->dev, " dw_mci_set_sel18 error!\n"); return ret; } /* Wait for 5ms */ usleep_range(5000, 5500); if (host->vqmmc) { ret = regulator_set_voltage(host->vqmmc, 2950000, 2950000); if (ret) { dev_warn(host->dev, "Switching to 3.3V signalling " "voltage failed\n"); return -EIO; } } else { reg = mci_readl(slot->host, UHS_REG); reg &= ~(0x1 << slot->id); mci_writel(slot->host, UHS_REG, reg); } /* Wait for 5ms */ usleep_range(5000, 5500); return ret; }
static int hs_dwmmc_card_busy(struct dw_mci *host) { if ((mci_readl(host, STATUS) & SDMMC_DATA_BUSY) || host->cmd || host->data || host->mrq || (host->state != STATE_IDLE)) { dev_vdbg(host->dev, " card is busy!"); return 1; } return 0; }
static void dw_mci_hs_set_parent(struct dw_mci *host, int timing) { struct dw_mci_hs_priv_data *priv = host->priv; int id = priv->id; struct clk *clk_parent = NULL; int reg_value; if (id != DW_MCI_EMMC_ID) return; /* first disable GPIO div clock */ reg_value = mci_readl(host, GPIO); mci_writel(host, GPIO, reg_value & ~GPIO_CLK_ENABLE); udelay(1); #ifndef CONFIG_ARCH_HI3630 /* select 19.2M clk */ if (timing == MMC_TIMING_LEGACY) { clk_parent = clk_get_parent_by_index(host->parent_clk, 0); if (IS_ERR_OR_NULL(clk_parent)) { dev_err(host->dev, " fail to get parent clk. \n"); } clk_set_parent(host->parent_clk, clk_parent); } else { clk_parent = clk_get_parent_by_index(host->parent_clk, 4); if (IS_ERR_OR_NULL(clk_parent)) { dev_err(host->dev, " fail to get parent clk. \n"); } clk_set_parent(host->parent_clk, clk_parent); } #else clk_parent = clk_get_parent_by_index(host->parent_clk, 4); if (IS_ERR_OR_NULL(clk_parent)) { dev_err(host->dev, " fail to get parent clk. \n"); } clk_set_parent(host->parent_clk, clk_parent); #endif /* enable internal GPIO div clock */ mci_writel(host, GPIO, reg_value | GPIO_CLK_ENABLE); }
void dw_mci_reg_dump(struct dw_mci *host) { u32 reg; dev_err(host->dev, ": ============== REGISTER DUMP ==============\n"); dev_err(host->dev, ": CTRL: 0x%08x\n", mci_readl(host, CTRL)); dev_err(host->dev, ": PWREN: 0x%08x\n", mci_readl(host, PWREN)); dev_err(host->dev, ": CLKDIV: 0x%08x\n", mci_readl(host, CLKDIV)); dev_err(host->dev, ": CLKSRC: 0x%08x\n", mci_readl(host, CLKSRC)); dev_err(host->dev, ": CLKENA: 0x%08x\n", mci_readl(host, CLKENA)); dev_err(host->dev, ": TMOUT: 0x%08x\n", mci_readl(host, TMOUT)); dev_err(host->dev, ": CTYPE: 0x%08x\n", mci_readl(host, CTYPE)); dev_err(host->dev, ": BLKSIZ: 0x%08x\n", mci_readl(host, BLKSIZ)); dev_err(host->dev, ": BYTCNT: 0x%08x\n", mci_readl(host, BYTCNT)); dev_err(host->dev, ": INTMSK: 0x%08x\n", mci_readl(host, INTMASK)); dev_err(host->dev, ": CMDARG: 0x%08x\n", mci_readl(host, CMDARG)); dev_err(host->dev, ": CMD: 0x%08x\n", mci_readl(host, CMD)); dev_err(host->dev, ": RESP0: 0x%08x\n", mci_readl(host, RESP0)); dev_err(host->dev, ": RESP1: 0x%08x\n", mci_readl(host, RESP1)); dev_err(host->dev, ": RESP2: 0x%08x\n", mci_readl(host, RESP2)); dev_err(host->dev, ": RESP3: 0x%08x\n", mci_readl(host, RESP3)); dev_err(host->dev, ": MINTSTS: 0x%08x\n", mci_readl(host, MINTSTS)); dev_err(host->dev, ": RINTSTS: 0x%08x\n", mci_readl(host, RINTSTS)); dev_err(host->dev, ": STATUS: 0x%08x\n", mci_readl(host, STATUS)); dev_err(host->dev, ": FIFOTH: 0x%08x\n", mci_readl(host, FIFOTH)); dev_err(host->dev, ": CDETECT: 0x%08x\n", mci_readl(host, CDETECT)); dev_err(host->dev, ": WRTPRT: 0x%08x\n", mci_readl(host, WRTPRT)); dev_err(host->dev, ": GPIO: 0x%08x\n", mci_readl(host, GPIO)); dev_err(host->dev, ": TCBCNT: 0x%08x\n", mci_readl(host, TCBCNT)); dev_err(host->dev, ": TBBCNT: 0x%08x\n", mci_readl(host, TBBCNT)); dev_err(host->dev, ": DEBNCE: 0x%08x\n", mci_readl(host, DEBNCE)); dev_err(host->dev, ": USRID: 0x%08x\n", mci_readl(host, USRID)); dev_err(host->dev, ": VERID: 0x%08x\n", mci_readl(host, VERID)); dev_err(host->dev, ": HCON: 0x%08x\n", mci_readl(host, HCON)); dev_err(host->dev, ": UHS_REG: 0x%08x\n", mci_readl(host, UHS_REG)); dev_err(host->dev, ": BMOD: 0x%08x\n", mci_readl(host, BMOD)); dev_err(host->dev, ": PLDMND: 0x%08x\n", mci_readl(host, PLDMND)); dev_err(host->dev, ": DBADDRL: 0x%08x\n", mci_readl(host, DBADDRL)); dev_err(host->dev, ": DBADDRU: 0x%08x\n", mci_readl(host, DBADDRU)); dev_err(host->dev, ": DSCADDRL: 0x%08x\n", mci_readl(host, DSCADDRL)); dev_err(host->dev, ": DSCADDRU: 0x%08x\n", mci_readl(host, DSCADDRU)); dev_err(host->dev, ": BUFADDR: 0x%08x\n", mci_readl(host, BUFADDR)); dev_err(host->dev, ": BUFADDRU: 0x%08x\n", mci_readl(host, BUFADDRU)); dev_err(host->dev, ": DBADDR: 0x%08x\n", mci_readl(host, DBADDR)); dev_err(host->dev, ": DSCADDR: 0x%08x\n", mci_readl(host, DSCADDR)); dev_err(host->dev, ": BUFADDR: 0x%08x\n", mci_readl(host, BUFADDR)); dev_err(host->dev, ": CLKSEL: 0x%08x\n", mci_readl(host, CLKSEL)); dev_err(host->dev, ": IDSTS: 0x%08x\n", mci_readl(host, IDSTS)); dev_err(host->dev, ": IDSTS64: 0x%08x\n", mci_readl(host, IDSTS64)); dev_err(host->dev, ": IDINTEN: 0x%08x\n", mci_readl(host, IDINTEN)); dev_err(host->dev, ": IDINTEN64: 0x%08x\n", mci_readl(host, IDINTEN64)); dev_err(host->dev, ": RESP_TAT: 0x%08x\n", mci_readl(host, RESP_TAT)); dev_err(host->dev, ": FORCE_CLK_STOP: 0x%08x\n", mci_readl(host, FORCE_CLK_STOP)); dev_err(host->dev, ": CDTHRCTL: 0x%08x\n", mci_readl(host, CDTHRCTL)); dw_mci_exynos_register_dump(host); dev_err(host->dev, ": ============== STATUS DUMP ================\n"); dev_err(host->dev, ": cmd_status: 0x%08x\n", host->cmd_status); dev_err(host->dev, ": data_status: 0x%08x\n", host->data_status); dev_err(host->dev, ": pending_events: 0x%08lx\n", host->pending_events); dev_err(host->dev, ": completed_events:0x%08lx\n", host->completed_events); dev_err(host->dev, ": state: %d\n", host->state); dev_err(host->dev, ": gate-clk: %s\n", atomic_read(&host->ciu_clk_cnt) ? "enable" : "disable"); dev_err(host->dev, ": ciu_en_win: %d\n", atomic_read(&host->ciu_en_win)); reg = mci_readl(host, CMD); dev_err(host->dev, ": ================= CMD REG =================\n"); dev_err(host->dev, ": read/write : %s\n", (reg & (0x1 << 10)) ? "write" : "read"); dev_err(host->dev, ": data expected : %d\n", (reg >> 9) & 0x1); dev_err(host->dev, ": cmd index : %d\n", (reg >> 0) & 0x3f); reg = mci_readl(host, STATUS); dev_err(host->dev, ": ================ STATUS REG ===============\n"); dev_err(host->dev, ": fifocount : %d\n", (reg >> 17) & 0x1fff); dev_err(host->dev, ": response index : %d\n", (reg >> 11) & 0x3f); dev_err(host->dev, ": data state mc busy: %d\n", (reg >> 10) & 0x1); dev_err(host->dev, ": data busy : %d\n", (reg >> 9) & 0x1); dev_err(host->dev, ": data 3 state : %d\n", (reg >> 8) & 0x1); dev_err(host->dev, ": command fsm state : %d\n", (reg >> 4) & 0xf); dev_err(host->dev, ": fifo full : %d\n", (reg >> 3) & 0x1); dev_err(host->dev, ": fifo empty : %d\n", (reg >> 2) & 0x1); dev_err(host->dev, ": fifo tx watermark : %d\n", (reg >> 1) & 0x1); dev_err(host->dev, ": fifo rx watermark : %d\n", (reg >> 0) & 0x1); dev_err(host->dev, ": ===========================================\n"); }
static int dw_mci_1_8v_signal_voltage_switch(struct dw_mci_slot *slot) { unsigned long loop_count = 0x100000; struct dw_mci *host = slot->host; int ret = -1; int intrs; /* disable interrupt upon voltage switch. handle interrupt here * and DO NOT triggle irq */ mci_writel(host, CTRL, (mci_readl(host, CTRL) & ~SDMMC_CTRL_INT_ENABLE)); /* stop clock */ mci_writel(host, CLKENA, (0x0 << 0)); mci_writel(host, CMD, SDMMC_CMD_ONLY_CLK | SDMMC_VOLT_SWITCH); do { if (!(mci_readl(host, CMD) & SDMMC_CMD_START)) break; loop_count--; } while (loop_count); if (!loop_count) dev_err(host->dev, " disable clock failed in voltage_switch\n"); mmiowb(); if (host->vqmmc) { ret = regulator_set_voltage(host->vqmmc, 1800000, 1800000); if (ret) { dev_warn(host->dev, "Switching to 1.8V signalling " "voltage failed\n"); return -EIO; } } /* Wait for 5ms */ usleep_range(10000, 10500); ret = dw_mci_set_sel18(1); if (ret) { dev_err(host->dev, " dw_mci_set_sel18 error!\n"); return ret; } /* start clock */ mci_writel(host, CLKENA, (0x1 << 0)); mci_writel(host, CMD, SDMMC_CMD_ONLY_CLK | SDMMC_VOLT_SWITCH); loop_count = 0x100000; do { if (!(mci_readl(host, CMD) & SDMMC_CMD_START)) break; loop_count--; } while (loop_count); if (!loop_count) dev_err(host->dev, " enable clock failed in voltage_switch\n"); /* poll cd interrupt */ loop_count = 0x100000; do { intrs = mci_readl(host, RINTSTS); if (intrs & SDMMC_INT_CMD_DONE) { dev_err(host->dev, " cd 0x%x in voltage_switch\n", intrs); mci_writel(host, RINTSTS, intrs); break; } loop_count--; } while (loop_count); if (!loop_count) dev_err(host->dev, " poll cd failed in voltage_switch\n"); /* enable interrupt */ mci_writel(host, CTRL, (mci_readl(host, CTRL) | SDMMC_CTRL_INT_ENABLE)); mmiowb(); return ret; }
void dw_mci_dsm_dump(struct dw_mci *host, int err_num) { u32 status, mintsts; if (dclient == NULL){ printk(KERN_ERR "dclient is not initialization\n"); return; } if(host== NULL) { printk(KERN_ERR "sdio host NULL.\n"); return; } dev_err(host->dev, "dsm_sido err_num = %d \n", err_num); if(!dsm_client_ocuppy(dclient)){ dsm_client_record(dclient, "CTRL:0x%x\n", mci_readl(host, CTRL)); dsm_client_record(dclient, "PWREN:0x%x\n", mci_readl(host, PWREN)); dsm_client_record(dclient, "CLKDIV:0x%x\n", mci_readl(host, CLKDIV)); dsm_client_record(dclient, "CLKSRC:0x%x\n", mci_readl(host, CLKSRC)); dsm_client_record(dclient, "CLKENA:0x%x\n", mci_readl(host, CLKENA)); dsm_client_record(dclient, "TMOUT:0x%x\n", mci_readl(host, TMOUT)); dsm_client_record(dclient, "CTYPE:0x%x\n", mci_readl(host, CTYPE)); dsm_client_record(dclient, "BLKSIZ:0x%x\n", mci_readl(host, BLKSIZ)); dsm_client_record(dclient, "BYTCNT:0x%x\n", mci_readl(host, BYTCNT)); dsm_client_record(dclient, "INTMSK:0x%x\n", mci_readl(host, INTMASK)); dsm_client_record(dclient, "CMDARG:0x%x\n", mci_readl(host, CMDARG)); dsm_client_record(dclient, "CMD:0x%x\n", mci_readl(host, CMD)); dsm_client_record(dclient, "MINTSTS:0x%x\n", mci_readl(host, MINTSTS)); dsm_client_record(dclient, "RINTSTS:0x%x\n", mci_readl(host, RINTSTS)); dsm_client_record(dclient, "STATUS:0x%x\n", mci_readl(host, STATUS)); dsm_client_record(dclient, "FIFOTH:0x%x\n", mci_readl(host, FIFOTH)); dsm_client_record(dclient, "CDETECT:0x%x\n", mci_readl(host, CDETECT)); dsm_client_record(dclient, "WRTPRT:0x%x\n", mci_readl(host, WRTPRT)); dsm_client_record(dclient, "GPIO:0x%x\n", mci_readl(host, GPIO)); dsm_client_record(dclient, "TCBCNT:0x%x\n", mci_readl(host, TCBCNT)); dsm_client_record(dclient, "TBBCNT:0x%x\n", mci_readl(host, TBBCNT)); dsm_client_record(dclient, "DEBNCE:0x%x\n", mci_readl(host, DEBNCE)); dsm_client_record(dclient, "USRID:0x%x\n", mci_readl(host, USRID)); dsm_client_record(dclient, "VERID:0x%x\n", mci_readl(host, VERID)); dsm_client_record(dclient, "HCON:0x%x\n", mci_readl(host, HCON)); dsm_client_record(dclient, "UHS_REG:0x%x\n", mci_readl(host, UHS_REG)); dsm_client_record(dclient, "BMOD:0x%x\n", mci_readl(host, BMOD)); dsm_client_record(dclient, "PLDMND:0x%x\n", mci_readl(host, PLDMND)); dsm_client_record(dclient, "DBADDR:0x%x\n", mci_readl(host, DBADDR)); dsm_client_record(dclient, "IDSTS:0x%x\n", mci_readl(host, IDSTS)); dsm_client_record(dclient, "IDINTEN:0x%x\n", mci_readl(host, IDINTEN)); dsm_client_record(dclient, "DSCADDR:0x%x\n", mci_readl(host, DSCADDR)); dsm_client_record(dclient, "BUFADDR:0x%x\n", mci_readl(host, BUFADDR)); dsm_client_record(dclient, "CARDTHRCTL:0x%x\n", mci_readl(host, CARDTHRCTL)); dsm_client_record(dclient, "UHS_REG_EXT:0x%x\n", mci_readl(host, UHS_REG_EXT)); dsm_client_record(dclient, "cmd_status:0x%x\n", host->cmd_status); dsm_client_record(dclient, "data_status:0x%x\n", host->data_status); dsm_client_record(dclient, "pending_events:0x%x\n", host->pending_events); dsm_client_record(dclient, "completed_events:0x%x\n", host->completed_events); dsm_client_record(dclient, "state:%d\n", host->state); /* summary */ dsm_client_record(dclient, "MINTSTS = %d\n", mci_readl(host, MINTSTS)); dsm_client_record(dclient, "STATUS = %d\n", mci_readl(host, STATUS)); dsm_client_record(dclient, "CMD=%d\n",mci_readl(host, CMD)); dsm_client_record(dclient, "ARG=0x%x \n",mci_readl(host, CMDARG)); dsm_client_record(dclient, "RESP0:0x%x\n", mci_readl(host, RESP0)); dsm_client_record(dclient, "RESP1:0x%x\n", mci_readl(host, RESP1)); dsm_client_record(dclient, "RESP2:0x%x\n", mci_readl(host, RESP2)); dsm_client_record(dclient, "RESP3:0x%x\n", mci_readl(host, RESP3)); dsm_client_record(dclient, "host :cmd_status=0x%x.\n", host->cmd_status); dsm_client_record(dclient, "data_status=0x%x.\n", host->data_status); dsm_client_record(dclient, "host:pending_events=0x%x\n", host->pending_events); dsm_client_record(dclient,"completed_events=0x%x.\n", host->completed_events); dsm_client_notify(dclient, err_num); }else printk("DSM CALL FAIL, MCI ID: %d\n", host->hw_mmc_id); }
static void dw_mci_hs_set_timing(struct dw_mci *host, int id, int timing, int sam_phase, int clk_div) { int cclk_div; int drive_sel; int sam_dly; int sam_phase_max, sam_phase_min; int sam_phase_val; int reg_value; int enable_shift = 0; int use_sam_dly = 0; int d_value = 0; if ((host->hw_mmc_id == DWMMC_SD_ID) && (timing == MMC_TIMING_LEGACY)) cclk_div = hs_timing_config[id][timing][1]; else cclk_div = clk_div; if (host->hw_mmc_id == DWMMC_SD_ID) { d_value = cclk_div - hs_timing_config[id][timing][1]; } drive_sel = hs_timing_config[id][timing][2]; sam_dly = hs_timing_config[id][timing][3] + d_value; #ifdef CONFIG_ARCH_HI3630 sam_phase_max = hs_timing_config[id][timing][4]; #else sam_phase_max = hs_timing_config[id][timing][4] + 2 * d_value; #endif sam_phase_min = hs_timing_config[id][timing][5]; if (sam_phase == -1) sam_phase_val = (sam_phase_max + sam_phase_min) / 2; else sam_phase_val = sam_phase; #ifndef CONFIG_ARCH_HI3630 /* enable_shift and use_sam_dly setting code */ /* warning! different with K3V3 */ switch(id){ case DW_MCI_EMMC_ID: switch(timing){ case MMC_TIMING_UHS_DDR50: if(4 <= sam_phase_val && sam_phase_val <= 6) enable_shift = 1; break; case MMC_TIMING_MMC_HS200: if(4 <= sam_phase_val && sam_phase_val <= 14) enable_shift = 1; if(9 <= sam_phase_val && sam_phase_val <= 14) use_sam_dly = 1; break; } break; case DW_MCI_SD_ID: switch(timing){ case MMC_TIMING_UHS_SDR12: use_sam_dly = 1; break; case MMC_TIMING_UHS_DDR50: if(4 <= sam_phase_val && sam_phase_val <= 11) enable_shift = 1; break; case MMC_TIMING_UHS_SDR50: if (10 + 2 * d_value <= sam_phase_val && sam_phase_val <= 12 + 2 * d_value) use_sam_dly = 1; if (4 + d_value <= sam_phase_val && sam_phase_val <= 12 + d_value) enable_shift = 1; break; case MMC_TIMING_UHS_SDR104: if (8 + 2 * d_value <= sam_phase_val && sam_phase_val <= 12 + 2 * d_value) use_sam_dly = 1; if (4 + d_value <= sam_phase_val && sam_phase_val <= 12 + d_value) enable_shift = 1; break; } break; case DW_MCI_SDIO_ID: switch(timing){ case MMC_TIMING_UHS_SDR12: use_sam_dly = 1; break; case MMC_TIMING_UHS_DDR50: if(4 <= sam_phase_val && sam_phase_val <= 11) enable_shift = 1; break; case MMC_TIMING_UHS_SDR50: if(4 <= sam_phase_val && sam_phase_val <= 9) enable_shift = 1; break; case MMC_TIMING_UHS_SDR104: if(9 <= sam_phase_val && sam_phase_val <= 14) use_sam_dly = 1; if(4 <= sam_phase_val && sam_phase_val <= 14) enable_shift = 1; break; } break; } #else if (timing == MMC_TIMING_LEGACY) enable_shift = 1; if ((id == 0) && (timing == MMC_TIMING_MMC_HS200)) { switch (sam_phase_val) { case 0: case 10: case 11: case 12: case 13: case 14: case 15: use_sam_dly = 1; break; default: use_sam_dly = 0; } } if ((id == 1) && (timing == MMC_TIMING_UHS_SDR104)) { if ((sam_phase_val == 0) || (sam_phase_val >= 10)) use_sam_dly = 1; } if ((id == 2) && (timing == MMC_TIMING_UHS_SDR104)) { switch (sam_phase_val) { case 0: case 10: case 11: case 12: case 13: case 14: case 15: use_sam_dly = 1; break; default: use_sam_dly = 0; } } #endif /* first disabl clk */ /* mci_writel(host, GPIO, ~GPIO_CLK_ENABLE); */ mci_writel(host, GPIO, 0x0); udelay(1); reg_value = SDMMC_UHS_REG_EXT_VALUE(sam_phase_val, sam_dly); mci_writel(host, UHS_REG_EXT, reg_value); mci_writel(host, ENABLE_SHIFT, enable_shift); reg_value = SDMMC_GPIO_VALUE(cclk_div, use_sam_dly, drive_sel); mci_writel(host, GPIO, reg_value | GPIO_CLK_ENABLE); dev_info( host->dev, "id=%d,timing=%d,UHS_REG_EXT=0x%x,ENABLE_SHIFT=0x%x,GPIO=0x%x\n", id, timing, mci_readl(host, UHS_REG_EXT), mci_readl(host, ENABLE_SHIFT), mci_readl(host, GPIO)); }