Loading Documentation/devicetree/bindings/mmc/sdhci-msm.txt +3 −5 Original line number Diff line number Diff line Loading @@ -90,11 +90,9 @@ Optional Properties: contents will not be retained. It is software responsibility to restore the SDCC registers before resuming to normal operation. - qcom,force-sdhc1-probe: Force probing sdhc1 even if it is not the boot device. - qcom,ddr-config: Certain chipsets and platforms require particular settings for the RCLK delay DLL configuration register for HS400 mode to work. This value can vary between platforms and msms. If a msm/platform require a different DLL setting than the default/POR setting for HS400 mode, it can be specified using this field. - qcom,dll-hsr-list: List of DLL-HSR values which are tuned for given process-node and platform. The sequence of values in this list must follow the sequence listed in sdhci_msm_dll_hsr data structure. In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage). - qcom,<supply>-always-on - specifies whether supply should be kept "on" always. - qcom,<supply>-lpm_sup - specifies whether supply can be kept in low power mode (lpm). Loading drivers/mmc/host/sdhci-msm.c +82 −28 Original line number Diff line number Diff line Loading @@ -354,6 +354,9 @@ enum dll_init_context { DLL_INIT_FROM_CX_COLLAPSE_EXIT, }; static unsigned int sdhci_msm_get_sup_clk_rate(struct sdhci_host *host, u32 req_clk); /* MSM platform specific tuning */ static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll) Loading Loading @@ -755,6 +758,7 @@ static int msm_init_cm_dll(struct sdhci_host *host, if (msm_host->use_updated_dll_reset) { u32 mclk_freq = 0; u32 actual_clk = sdhci_msm_get_sup_clk_rate(host, host->clock); /* * Only configure the mclk_freq in normal DLL init Loading @@ -764,7 +768,7 @@ static int msm_init_cm_dll(struct sdhci_host *host, * proper value prior to getting here. */ if (init_context == DLL_INIT_NORMAL) { switch (host->clock) { switch (actual_clk) { case 208000000: case 202000000: case 201500000: Loading @@ -775,10 +779,9 @@ static int msm_init_cm_dll(struct sdhci_host *host, mclk_freq = 40; break; default: pr_err("%s: %s: Error. Unsupported clk freq\n", mmc_hostname(mmc), __func__); rc = -EINVAL; goto out; mclk_freq = (u32)((actual_clk / TCXO_FREQ) * 4); pr_info_once("%s: %s: Non standard clk freq =%u\n", mmc_hostname(mmc), __func__, actual_clk); } if ((readl_relaxed(host->ioaddr + Loading Loading @@ -815,13 +818,34 @@ static int msm_init_cm_dll(struct sdhci_host *host, /* Configure Tassadar DLL (Only applicable for 7FF projects) */ if (msm_host->use_7nm_dll) { if (msm_host->dll_hsr) { writel_relaxed(msm_host->dll_hsr->dll_usr_ctl, host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL); writel_relaxed(msm_host->dll_hsr->dll_config_3, host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_3); } else { writel_relaxed(DLL_USR_CTL_POR_VAL | FINE_TUNE_MODE_EN | ENABLE_DLL_LOCK_STATUS | BIAS_OK_SIGNAL, host->ioaddr + ENABLE_DLL_LOCK_STATUS | BIAS_OK_SIGNAL, host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL); writel_relaxed(DLL_CONFIG_3_POR_VAL, host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_3); } } /* * Update the lower two bytes of DLL_CONFIG only with HSR values. * Since these are the static settings. */ if (msm_host->dll_hsr) { writel_relaxed((readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG) | (msm_host->dll_hsr->dll_config & 0xffff)), host->ioaddr + msm_host_offset->CORE_DLL_CONFIG); } /* Set DLL_EN bit to 1. */ writel_relaxed((readl_relaxed(host->ioaddr + Loading Loading @@ -1003,8 +1027,8 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) * Reprogramming the value in case it might have been modified by * bootloaders. */ if (msm_host->pdata->rclk_wa) { writel_relaxed(msm_host->pdata->ddr_config, host->ioaddr + if (msm_host->dll_hsr && msm_host->dll_hsr->ddr_config) { writel_relaxed(msm_host->dll_hsr->ddr_config, host->ioaddr + msm_host_offset->CORE_DDR_CONFIG); } else if (msm_host->rclk_delay_fix) { writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + Loading Loading @@ -1948,6 +1972,34 @@ static void sdhci_msm_pm_qos_parse(struct device *dev, } } static int sdhci_msm_dt_parse_hsr_info(struct device *dev, struct sdhci_msm_host *msm_host) { u32 *dll_hsr_table = NULL; int dll_hsr_table_len, dll_hsr_reg_count; int ret = 0; if (sdhci_msm_dt_get_array(dev, "qcom,dll-hsr-list", &dll_hsr_table, &dll_hsr_table_len, 0)) goto skip_hsr; dll_hsr_reg_count = sizeof(struct sdhci_msm_dll_hsr) / sizeof(u32); if (dll_hsr_table_len != dll_hsr_reg_count) { dev_err(dev, "Number of HSR entries are not matching\n"); ret = -EINVAL; } else { msm_host->dll_hsr = (struct sdhci_msm_dll_hsr *)dll_hsr_table; } skip_hsr: if (!msm_host->dll_hsr) dev_info(dev, "Failed to get dll hsr settings from dt\n"); if (dll_hsr_table) devm_kfree(dev, dll_hsr_table); return ret; } /* Parse platform data */ static struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, Loading Loading @@ -2116,8 +2168,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, msm_host->regs_restore.is_supported = of_property_read_bool(np, "qcom,restore-after-cx-collapse"); if (!of_property_read_u32(np, "qcom,ddr-config", &pdata->ddr_config)) pdata->rclk_wa = true; if (sdhci_msm_dt_parse_hsr_info(dev, msm_host)) goto out; return pdata; out: Loading Loading @@ -3742,32 +3794,34 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) msm_host_offset->CORE_MCI_FIFO_CNT), sdhci_msm_readl_relaxed(host, msm_host_offset->CORE_MCI_STATUS)); pr_info("DLL cfg: 0x%08x | DLL sts: 0x%08x | SDCC ver: 0x%08x\n", pr_info("DLL sts: 0x%08x | DLL cfg: 0x%08x | DLL cfg2: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_STATUS), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG), sdhci_msm_readl_relaxed(host, msm_host_offset->CORE_DLL_CONFIG_2)); pr_info("DLL cfg3: 0x%08x | DLL usr ctl: 0x%08x | DDR cfg: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_STATUS), msm_host_offset->CORE_DLL_CONFIG_3), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL), sdhci_msm_readl_relaxed(host, msm_host_offset->CORE_MCI_VERSION)); pr_info("Vndr func: 0x%08x | Vndr adma err : addr0: 0x%08x addr1: 0x%08x\n", msm_host_offset->CORE_DDR_CONFIG)); pr_info("SDCC ver: 0x%08x | Vndr adma err : addr0: 0x%08x addr1: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC), msm_host_offset->CORE_MCI_VERSION), readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_ADMA_ERR_ADDR0), readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_ADMA_ERR_ADDR1)); pr_info("Vndr func2: 0x%08x | dll_config_2: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_FUNC2), pr_info("Vndr func: 0x%08x | Vndr func2 : 0x%08x Vndr func3: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_2)); pr_info("dll_config_3: 0x%08x | ddr_config: 0x%08x | dll_usr_ctl: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_3), msm_host_offset->CORE_VENDOR_SPEC), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DDR_CONFIG), msm_host_offset->CORE_VENDOR_SPEC_FUNC2), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL)); msm_host_offset->CORE_VENDOR_SPEC3)); /* * tbsel indicates [2:0] bits and tbsel2 indicates [7:4] bits * of CORE_TESTBUS_CONFIG register. Loading drivers/mmc/host/sdhci-msm.h +14 −2 Original line number Diff line number Diff line Loading @@ -147,8 +147,6 @@ struct sdhci_msm_pltfm_data { struct sdhci_msm_pm_qos_data pm_qos_data; u32 ice_clk_max; u32 ice_clk_min; u32 ddr_config; bool rclk_wa; u32 *bus_clk_table; unsigned char bus_clk_cnt; }; Loading Loading @@ -191,6 +189,19 @@ struct sdhci_msm_regs_restore { u32 dll_usr_ctl; }; /* * DLL registers which needs be programmed with HSR settings. * Add any new register only at the end and don't change the * sequence. */ struct sdhci_msm_dll_hsr { u32 dll_config; u32 dll_config_2; u32 dll_config_3; u32 dll_usr_ctl; u32 ddr_config; }; struct sdhci_msm_debug_data { struct mmc_host copy_mmc; struct mmc_card copy_card; Loading Loading @@ -254,6 +265,7 @@ struct sdhci_msm_host { struct workqueue_struct *pm_qos_wq; bool use_cdr; u32 transfer_mode; struct sdhci_msm_dll_hsr *dll_hsr; }; extern char *saved_command_line; Loading Loading
Documentation/devicetree/bindings/mmc/sdhci-msm.txt +3 −5 Original line number Diff line number Diff line Loading @@ -90,11 +90,9 @@ Optional Properties: contents will not be retained. It is software responsibility to restore the SDCC registers before resuming to normal operation. - qcom,force-sdhc1-probe: Force probing sdhc1 even if it is not the boot device. - qcom,ddr-config: Certain chipsets and platforms require particular settings for the RCLK delay DLL configuration register for HS400 mode to work. This value can vary between platforms and msms. If a msm/platform require a different DLL setting than the default/POR setting for HS400 mode, it can be specified using this field. - qcom,dll-hsr-list: List of DLL-HSR values which are tuned for given process-node and platform. The sequence of values in this list must follow the sequence listed in sdhci_msm_dll_hsr data structure. In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage). - qcom,<supply>-always-on - specifies whether supply should be kept "on" always. - qcom,<supply>-lpm_sup - specifies whether supply can be kept in low power mode (lpm). Loading
drivers/mmc/host/sdhci-msm.c +82 −28 Original line number Diff line number Diff line Loading @@ -354,6 +354,9 @@ enum dll_init_context { DLL_INIT_FROM_CX_COLLAPSE_EXIT, }; static unsigned int sdhci_msm_get_sup_clk_rate(struct sdhci_host *host, u32 req_clk); /* MSM platform specific tuning */ static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll) Loading Loading @@ -755,6 +758,7 @@ static int msm_init_cm_dll(struct sdhci_host *host, if (msm_host->use_updated_dll_reset) { u32 mclk_freq = 0; u32 actual_clk = sdhci_msm_get_sup_clk_rate(host, host->clock); /* * Only configure the mclk_freq in normal DLL init Loading @@ -764,7 +768,7 @@ static int msm_init_cm_dll(struct sdhci_host *host, * proper value prior to getting here. */ if (init_context == DLL_INIT_NORMAL) { switch (host->clock) { switch (actual_clk) { case 208000000: case 202000000: case 201500000: Loading @@ -775,10 +779,9 @@ static int msm_init_cm_dll(struct sdhci_host *host, mclk_freq = 40; break; default: pr_err("%s: %s: Error. Unsupported clk freq\n", mmc_hostname(mmc), __func__); rc = -EINVAL; goto out; mclk_freq = (u32)((actual_clk / TCXO_FREQ) * 4); pr_info_once("%s: %s: Non standard clk freq =%u\n", mmc_hostname(mmc), __func__, actual_clk); } if ((readl_relaxed(host->ioaddr + Loading Loading @@ -815,13 +818,34 @@ static int msm_init_cm_dll(struct sdhci_host *host, /* Configure Tassadar DLL (Only applicable for 7FF projects) */ if (msm_host->use_7nm_dll) { if (msm_host->dll_hsr) { writel_relaxed(msm_host->dll_hsr->dll_usr_ctl, host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL); writel_relaxed(msm_host->dll_hsr->dll_config_3, host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_3); } else { writel_relaxed(DLL_USR_CTL_POR_VAL | FINE_TUNE_MODE_EN | ENABLE_DLL_LOCK_STATUS | BIAS_OK_SIGNAL, host->ioaddr + ENABLE_DLL_LOCK_STATUS | BIAS_OK_SIGNAL, host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL); writel_relaxed(DLL_CONFIG_3_POR_VAL, host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_3); } } /* * Update the lower two bytes of DLL_CONFIG only with HSR values. * Since these are the static settings. */ if (msm_host->dll_hsr) { writel_relaxed((readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG) | (msm_host->dll_hsr->dll_config & 0xffff)), host->ioaddr + msm_host_offset->CORE_DLL_CONFIG); } /* Set DLL_EN bit to 1. */ writel_relaxed((readl_relaxed(host->ioaddr + Loading Loading @@ -1003,8 +1027,8 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) * Reprogramming the value in case it might have been modified by * bootloaders. */ if (msm_host->pdata->rclk_wa) { writel_relaxed(msm_host->pdata->ddr_config, host->ioaddr + if (msm_host->dll_hsr && msm_host->dll_hsr->ddr_config) { writel_relaxed(msm_host->dll_hsr->ddr_config, host->ioaddr + msm_host_offset->CORE_DDR_CONFIG); } else if (msm_host->rclk_delay_fix) { writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + Loading Loading @@ -1948,6 +1972,34 @@ static void sdhci_msm_pm_qos_parse(struct device *dev, } } static int sdhci_msm_dt_parse_hsr_info(struct device *dev, struct sdhci_msm_host *msm_host) { u32 *dll_hsr_table = NULL; int dll_hsr_table_len, dll_hsr_reg_count; int ret = 0; if (sdhci_msm_dt_get_array(dev, "qcom,dll-hsr-list", &dll_hsr_table, &dll_hsr_table_len, 0)) goto skip_hsr; dll_hsr_reg_count = sizeof(struct sdhci_msm_dll_hsr) / sizeof(u32); if (dll_hsr_table_len != dll_hsr_reg_count) { dev_err(dev, "Number of HSR entries are not matching\n"); ret = -EINVAL; } else { msm_host->dll_hsr = (struct sdhci_msm_dll_hsr *)dll_hsr_table; } skip_hsr: if (!msm_host->dll_hsr) dev_info(dev, "Failed to get dll hsr settings from dt\n"); if (dll_hsr_table) devm_kfree(dev, dll_hsr_table); return ret; } /* Parse platform data */ static struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, Loading Loading @@ -2116,8 +2168,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, msm_host->regs_restore.is_supported = of_property_read_bool(np, "qcom,restore-after-cx-collapse"); if (!of_property_read_u32(np, "qcom,ddr-config", &pdata->ddr_config)) pdata->rclk_wa = true; if (sdhci_msm_dt_parse_hsr_info(dev, msm_host)) goto out; return pdata; out: Loading Loading @@ -3742,32 +3794,34 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) msm_host_offset->CORE_MCI_FIFO_CNT), sdhci_msm_readl_relaxed(host, msm_host_offset->CORE_MCI_STATUS)); pr_info("DLL cfg: 0x%08x | DLL sts: 0x%08x | SDCC ver: 0x%08x\n", pr_info("DLL sts: 0x%08x | DLL cfg: 0x%08x | DLL cfg2: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_STATUS), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG), sdhci_msm_readl_relaxed(host, msm_host_offset->CORE_DLL_CONFIG_2)); pr_info("DLL cfg3: 0x%08x | DLL usr ctl: 0x%08x | DDR cfg: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_STATUS), msm_host_offset->CORE_DLL_CONFIG_3), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL), sdhci_msm_readl_relaxed(host, msm_host_offset->CORE_MCI_VERSION)); pr_info("Vndr func: 0x%08x | Vndr adma err : addr0: 0x%08x addr1: 0x%08x\n", msm_host_offset->CORE_DDR_CONFIG)); pr_info("SDCC ver: 0x%08x | Vndr adma err : addr0: 0x%08x addr1: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC), msm_host_offset->CORE_MCI_VERSION), readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_ADMA_ERR_ADDR0), readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_ADMA_ERR_ADDR1)); pr_info("Vndr func2: 0x%08x | dll_config_2: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_FUNC2), pr_info("Vndr func: 0x%08x | Vndr func2 : 0x%08x Vndr func3: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_2)); pr_info("dll_config_3: 0x%08x | ddr_config: 0x%08x | dll_usr_ctl: 0x%08x\n", readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_3), msm_host_offset->CORE_VENDOR_SPEC), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DDR_CONFIG), msm_host_offset->CORE_VENDOR_SPEC_FUNC2), readl_relaxed(host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL)); msm_host_offset->CORE_VENDOR_SPEC3)); /* * tbsel indicates [2:0] bits and tbsel2 indicates [7:4] bits * of CORE_TESTBUS_CONFIG register. Loading
drivers/mmc/host/sdhci-msm.h +14 −2 Original line number Diff line number Diff line Loading @@ -147,8 +147,6 @@ struct sdhci_msm_pltfm_data { struct sdhci_msm_pm_qos_data pm_qos_data; u32 ice_clk_max; u32 ice_clk_min; u32 ddr_config; bool rclk_wa; u32 *bus_clk_table; unsigned char bus_clk_cnt; }; Loading Loading @@ -191,6 +189,19 @@ struct sdhci_msm_regs_restore { u32 dll_usr_ctl; }; /* * DLL registers which needs be programmed with HSR settings. * Add any new register only at the end and don't change the * sequence. */ struct sdhci_msm_dll_hsr { u32 dll_config; u32 dll_config_2; u32 dll_config_3; u32 dll_usr_ctl; u32 ddr_config; }; struct sdhci_msm_debug_data { struct mmc_host copy_mmc; struct mmc_card copy_card; Loading Loading @@ -254,6 +265,7 @@ struct sdhci_msm_host { struct workqueue_struct *pm_qos_wq; bool use_cdr; u32 transfer_mode; struct sdhci_msm_dll_hsr *dll_hsr; }; extern char *saved_command_line; Loading