Loading Documentation/devicetree/bindings/mmc/sdhci-msm.txt +5 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ Required properties: Required "interrupt-names" are "hc_irq" and "pwr_irq". - <supply-name>-supply: phandle to the regulator device tree node Required "supply-name" are "vdd" and "vdd-io". - qcom,ice-clk-rates: this is an array that specifies supported Inline Crypto Engine (ICE) clock frequencies, Units - Hz. - sdhc-msm-crypto: phandle to SDHC ICE node Required alias: - The slot number is specified via an alias with the following format Loading Loading @@ -121,6 +124,7 @@ Example: reg-names = "hc_mem", "core_mem"; interrupts = <0 123 0>, <0 138 0>; interrupt-names = "hc_irq", "pwr_irq"; sdhc-msm-crypto = <&sdcc1_ice>; vdd-supply = <&pm8941_l21>; vdd-io-supply = <&pm8941_l13>; Loading @@ -143,6 +147,7 @@ Example: qcom,nonremovable; qcom,large-address-bus; qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v"; qcom,ice-clk-rates = <300000000 150000000>; qcom,scaling-lower-bus-speed-mode = "DDR52"; Loading drivers/mmc/host/sdhci-msm.c +139 −4 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <trace/events/mmc.h> #include "sdhci-msm.h" #include "sdhci-msm-ice.h" #include "cmdq_hci.h" #define QOS_REMOVE_DELAY_MS 10 Loading Loading @@ -1814,6 +1815,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, int len, i; int clk_table_len; u32 *clk_table = NULL; int ice_clk_table_len; u32 *ice_clk_table = NULL; enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW; const char *lower_bus_speed = NULL; Loading Loading @@ -1871,6 +1874,20 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, pdata->sup_clk_table = clk_table; pdata->sup_clk_cnt = clk_table_len; if (msm_host->ice.pdev) { if (sdhci_msm_dt_get_array(dev, "qcom,ice-clk-rates", &ice_clk_table, &ice_clk_table_len, 0)) { dev_err(dev, "failed parsing supported ice clock rates\n"); goto out; } if (!ice_clk_table || !ice_clk_table_len) { dev_err(dev, "Invalid clock table\n"); goto out; } pdata->sup_ice_clk_table = ice_clk_table; pdata->sup_ice_clk_cnt = ice_clk_table_len; } pdata->vreg_data = devm_kzalloc(dev, sizeof(struct sdhci_msm_slot_reg_data), GFP_KERNEL); Loading Loading @@ -2957,12 +2974,23 @@ static int sdhci_msm_enable_controller_clock(struct sdhci_host *host) goto disable_pclk; } if (!IS_ERR(msm_host->ice_clk)) { rc = clk_prepare_enable(msm_host->ice_clk); if (rc) { pr_err("%s: %s: failed to enable the ice-clk with error %d\n", mmc_hostname(host->mmc), __func__, rc); goto disable_host_clk; } } atomic_set(&msm_host->controller_clock, 1); pr_debug("%s: %s: enabled controller clock\n", mmc_hostname(host->mmc), __func__); sdhci_msm_registers_restore(host); goto out; disable_host_clk: if (!IS_ERR(msm_host->clk)) clk_disable_unprepare(msm_host->clk); disable_pclk: if (!IS_ERR(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); Loading @@ -2982,10 +3010,10 @@ static void sdhci_msm_disable_controller_clock(struct sdhci_host *host) sdhci_msm_registers_save(host); if (!IS_ERR(msm_host->clk)) clk_disable_unprepare(msm_host->clk); if (!IS_ERR(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); if (!IS_ERR(msm_host->ice_clk)) clk_disable_unprepare(msm_host->ice_clk); if (!IS_ERR(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); sdhci_msm_bus_voting(host, 0); atomic_set(&msm_host->controller_clock, 0); pr_debug("%s: %s: disabled controller clock\n", Loading Loading @@ -3073,6 +3101,8 @@ static int sdhci_msm_prepare_clocks(struct sdhci_host *host, bool enable) disable_controller_clk: if (!IS_ERR_OR_NULL(msm_host->clk)) clk_disable_unprepare(msm_host->clk); if (!IS_ERR(msm_host->ice_clk)) clk_disable_unprepare(msm_host->ice_clk); if (!IS_ERR_OR_NULL(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); atomic_set(&msm_host->controller_clock, 0); Loading Loading @@ -3378,6 +3408,7 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) int i, index = 0; u32 test_bus_val = 0; u32 debug_reg[MAX_TEST_BUS] = {0}; u32 sts = 0; sdhci_msm_cache_debug_data(host); pr_info("----------- VENDOR REGISTER DUMP -----------\n"); Loading Loading @@ -3440,6 +3471,22 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) pr_info(" Test bus[%d to %d]: 0x%08x 0x%08x 0x%08x 0x%08x\n", i, i + 3, debug_reg[i], debug_reg[i+1], debug_reg[i+2], debug_reg[i+3]); if (host->is_crypto_en) { sdhci_msm_ice_get_status(host, &sts); pr_info("%s: ICE status %x\n", mmc_hostname(host->mmc), sts); } } static void sdhci_msm_reset(struct sdhci_host *host, u8 mask) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; /* Set ICE core to be reset in sync with SDHC core */ if (msm_host->ice.pdev) writel_relaxed(1, host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL); sdhci_reset(host, mask); } /* Loading Loading @@ -4022,6 +4069,8 @@ static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host) } static struct sdhci_ops sdhci_msm_ops = { .crypto_engine_cfg = sdhci_msm_ice_cfg, .crypto_engine_reset = sdhci_msm_ice_reset, .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .check_power_status = sdhci_msm_check_power_status, .platform_execute_tuning = sdhci_msm_execute_tuning, Loading @@ -4035,7 +4084,7 @@ static struct sdhci_ops sdhci_msm_ops = { .config_auto_tuning_cmd = sdhci_msm_config_auto_tuning_cmd, .enable_controller_clock = sdhci_msm_enable_controller_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, .reset = sdhci_msm_reset, .clear_set_dumpregs = sdhci_msm_clear_set_dumpregs, .enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask, .reset_workaround = sdhci_msm_reset_workaround, Loading Loading @@ -4234,7 +4283,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); if (IS_ERR(host)) { ret = PTR_ERR(host); goto out; goto out_host_free; } pltfm_host = sdhci_priv(host); Loading @@ -4242,6 +4291,31 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->mmc = host->mmc; msm_host->pdev = pdev; /* get the ice device vops if present */ ret = sdhci_msm_ice_get_dev(host); if (ret == -EPROBE_DEFER) { /* * SDHCI driver might be probed before ICE driver does. * In that case we would like to return EPROBE_DEFER code * in order to delay its probing. */ dev_err(&pdev->dev, "%s: required ICE device not probed yet err = %d\n", __func__, ret); goto out_host_free; } else if (ret == -ENODEV) { /* * ICE device is not enabled in DTS file. No need for further * initialization of ICE driver. */ dev_warn(&pdev->dev, "%s: ICE device is not enabled", __func__); } else if (ret) { dev_err(&pdev->dev, "%s: sdhci_msm_ice_get_dev failed %d\n", __func__, ret); goto out_host_free; } /* Extract platform data */ if (pdev->dev.of_node) { ret = of_alias_get_id(pdev->dev.of_node, "sdhc"); Loading Loading @@ -4301,6 +4375,28 @@ static int sdhci_msm_probe(struct platform_device *pdev) } atomic_set(&msm_host->controller_clock, 1); if (msm_host->ice.pdev) { /* Setup SDC ICE clock */ msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice_core_clk"); if (!IS_ERR(msm_host->ice_clk)) { /* ICE core has only one clock frequency for now */ ret = clk_set_rate(msm_host->ice_clk, msm_host->pdata->sup_ice_clk_table[0]); if (ret) { dev_err(&pdev->dev, "ICE_CLK rate set failed (%d) for %u\n", ret, msm_host->pdata->sup_ice_clk_table[0]); goto pclk_disable; } ret = clk_prepare_enable(msm_host->ice_clk); if (ret) goto pclk_disable; msm_host->ice_clk_rate = msm_host->pdata->sup_clk_table[0]; } } /* Setup SDC MMC clock */ msm_host->clk = devm_clk_get(&pdev->dev, "core_clk"); if (IS_ERR(msm_host->clk)) { Loading Loading @@ -4527,6 +4623,21 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->mmc->sdr104_wa = msm_host->pdata->sdr104_wa; /* Initialize ICE if present */ if (msm_host->ice.pdev) { ret = sdhci_msm_ice_init(host); if (ret) { dev_err(&pdev->dev, "%s: SDHCi ICE init failed (%d)\n", mmc_hostname(host->mmc), ret); ret = -EINVAL; goto vreg_deinit; } host->is_crypto_en = true; /* Packed commands cannot be encrypted/decrypted using ICE */ msm_host->mmc->caps2 &= ~(MMC_CAP2_PACKED_WR | MMC_CAP2_PACKED_WR_CONTROL); } init_completion(&msm_host->pwr_irq_completion); if (gpio_is_valid(msm_host->pdata->status_gpio)) { Loading Loading @@ -4666,6 +4777,8 @@ static int sdhci_msm_probe(struct platform_device *pdev) clk_disable_unprepare(msm_host->bus_clk); pltfm_free: sdhci_pltfm_free(pdev); out_host_free: devm_kfree(&pdev->dev, msm_host); out: pr_debug("%s: Exit %s\n", dev_name(&pdev->dev), __func__); return ret; Loading Loading @@ -4755,6 +4868,7 @@ static int sdhci_msm_runtime_suspend(struct device *dev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; ktime_t start = ktime_get(); int ret; if (host->mmc->card && mmc_card_sdio(host->mmc->card)) goto defer_disable_host_irq; Loading @@ -4776,6 +4890,12 @@ static int sdhci_msm_runtime_suspend(struct device *dev) trace_sdhci_msm_runtime_suspend(mmc_hostname(host->mmc), 0, ktime_to_us(ktime_sub(ktime_get(), start))); if (host->is_crypto_en) { ret = sdhci_msm_ice_suspend(host); if (ret < 0) pr_err("%s: failed to suspend crypto engine %d\n", mmc_hostname(host->mmc), ret); } return 0; } Loading @@ -4785,6 +4905,21 @@ static int sdhci_msm_runtime_resume(struct device *dev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; ktime_t start = ktime_get(); int ret; if (host->is_crypto_en) { ret = sdhci_msm_enable_controller_clock(host); if (ret) { pr_err("%s: Failed to enable reqd clocks\n", mmc_hostname(host->mmc)); goto skip_ice_resume; } ret = sdhci_msm_ice_resume(host); if (ret) pr_err("%s: failed to resume crypto engine %d\n", mmc_hostname(host->mmc), ret); } skip_ice_resume: if (host->mmc->card && mmc_card_sdio(host->mmc->card)) goto defer_enable_host_irq; Loading drivers/mmc/host/sdhci.c +42 −0 Original line number Diff line number Diff line Loading @@ -305,6 +305,8 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) /* Resetting the controller clears many */ host->preset_enabled = false; } if (host->is_crypto_en) host->crypto_reset_reqd = true; } static void sdhci_init(struct sdhci_host *host, int soft) Loading Loading @@ -1749,6 +1751,33 @@ static int sdhci_get_tuning_cmd(struct sdhci_host *host) return MMC_SEND_TUNING_BLOCK; } static int sdhci_crypto_cfg(struct sdhci_host *host, struct mmc_request *mrq, u32 slot) { int err = 0; if (host->crypto_reset_reqd && host->ops->crypto_engine_reset) { err = host->ops->crypto_engine_reset(host); if (err) { pr_err("%s: crypto reset failed\n", mmc_hostname(host->mmc)); goto out; } host->crypto_reset_reqd = false; } if (host->ops->crypto_engine_cfg) { err = host->ops->crypto_engine_cfg(host, mrq, slot); if (err) { pr_err("%s: failed to configure crypto\n", mmc_hostname(host->mmc)); goto out; } } out: return err; } static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct sdhci_host *host; Loading Loading @@ -1815,6 +1844,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) sdhci_get_tuning_cmd(host)); } if (host->is_crypto_en) { spin_unlock_irqrestore(&host->lock, flags); if (sdhci_crypto_cfg(host, mrq, 0)) goto end_req; spin_lock_irqsave(&host->lock, flags); } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) sdhci_send_command(host, mrq->sbc); else Loading @@ -1823,6 +1859,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) mmiowb(); spin_unlock_irqrestore(&host->lock, flags); return; end_req: mrq->cmd->error = -EIO; if (mrq->data) mrq->data->error = -EIO; mmc_request_done(host->mmc, mrq); } void sdhci_set_bus_width(struct sdhci_host *host, int width) Loading drivers/mmc/host/sdhci.h +5 −0 Original line number Diff line number Diff line Loading @@ -628,6 +628,8 @@ struct sdhci_host { enum sdhci_power_policy power_policy; bool sdio_irq_async_status; bool is_crypto_en; bool crypto_reset_reqd; u32 auto_cmd_err_sts; struct ratelimit_state dbg_dump_rs; Loading Loading @@ -666,6 +668,9 @@ struct sdhci_ops { unsigned int (*get_ro)(struct sdhci_host *host); void (*reset)(struct sdhci_host *host, u8 mask); int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); int (*crypto_engine_cfg)(struct sdhci_host *host, struct mmc_request *mrq, u32 slot); int (*crypto_engine_reset)(struct sdhci_host *host); void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); void (*hw_reset)(struct sdhci_host *host); void (*adma_workaround)(struct sdhci_host *host, u32 intmask); Loading Loading
Documentation/devicetree/bindings/mmc/sdhci-msm.txt +5 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ Required properties: Required "interrupt-names" are "hc_irq" and "pwr_irq". - <supply-name>-supply: phandle to the regulator device tree node Required "supply-name" are "vdd" and "vdd-io". - qcom,ice-clk-rates: this is an array that specifies supported Inline Crypto Engine (ICE) clock frequencies, Units - Hz. - sdhc-msm-crypto: phandle to SDHC ICE node Required alias: - The slot number is specified via an alias with the following format Loading Loading @@ -121,6 +124,7 @@ Example: reg-names = "hc_mem", "core_mem"; interrupts = <0 123 0>, <0 138 0>; interrupt-names = "hc_irq", "pwr_irq"; sdhc-msm-crypto = <&sdcc1_ice>; vdd-supply = <&pm8941_l21>; vdd-io-supply = <&pm8941_l13>; Loading @@ -143,6 +147,7 @@ Example: qcom,nonremovable; qcom,large-address-bus; qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v"; qcom,ice-clk-rates = <300000000 150000000>; qcom,scaling-lower-bus-speed-mode = "DDR52"; Loading
drivers/mmc/host/sdhci-msm.c +139 −4 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <trace/events/mmc.h> #include "sdhci-msm.h" #include "sdhci-msm-ice.h" #include "cmdq_hci.h" #define QOS_REMOVE_DELAY_MS 10 Loading Loading @@ -1814,6 +1815,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, int len, i; int clk_table_len; u32 *clk_table = NULL; int ice_clk_table_len; u32 *ice_clk_table = NULL; enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW; const char *lower_bus_speed = NULL; Loading Loading @@ -1871,6 +1874,20 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev, pdata->sup_clk_table = clk_table; pdata->sup_clk_cnt = clk_table_len; if (msm_host->ice.pdev) { if (sdhci_msm_dt_get_array(dev, "qcom,ice-clk-rates", &ice_clk_table, &ice_clk_table_len, 0)) { dev_err(dev, "failed parsing supported ice clock rates\n"); goto out; } if (!ice_clk_table || !ice_clk_table_len) { dev_err(dev, "Invalid clock table\n"); goto out; } pdata->sup_ice_clk_table = ice_clk_table; pdata->sup_ice_clk_cnt = ice_clk_table_len; } pdata->vreg_data = devm_kzalloc(dev, sizeof(struct sdhci_msm_slot_reg_data), GFP_KERNEL); Loading Loading @@ -2957,12 +2974,23 @@ static int sdhci_msm_enable_controller_clock(struct sdhci_host *host) goto disable_pclk; } if (!IS_ERR(msm_host->ice_clk)) { rc = clk_prepare_enable(msm_host->ice_clk); if (rc) { pr_err("%s: %s: failed to enable the ice-clk with error %d\n", mmc_hostname(host->mmc), __func__, rc); goto disable_host_clk; } } atomic_set(&msm_host->controller_clock, 1); pr_debug("%s: %s: enabled controller clock\n", mmc_hostname(host->mmc), __func__); sdhci_msm_registers_restore(host); goto out; disable_host_clk: if (!IS_ERR(msm_host->clk)) clk_disable_unprepare(msm_host->clk); disable_pclk: if (!IS_ERR(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); Loading @@ -2982,10 +3010,10 @@ static void sdhci_msm_disable_controller_clock(struct sdhci_host *host) sdhci_msm_registers_save(host); if (!IS_ERR(msm_host->clk)) clk_disable_unprepare(msm_host->clk); if (!IS_ERR(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); if (!IS_ERR(msm_host->ice_clk)) clk_disable_unprepare(msm_host->ice_clk); if (!IS_ERR(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); sdhci_msm_bus_voting(host, 0); atomic_set(&msm_host->controller_clock, 0); pr_debug("%s: %s: disabled controller clock\n", Loading Loading @@ -3073,6 +3101,8 @@ static int sdhci_msm_prepare_clocks(struct sdhci_host *host, bool enable) disable_controller_clk: if (!IS_ERR_OR_NULL(msm_host->clk)) clk_disable_unprepare(msm_host->clk); if (!IS_ERR(msm_host->ice_clk)) clk_disable_unprepare(msm_host->ice_clk); if (!IS_ERR_OR_NULL(msm_host->pclk)) clk_disable_unprepare(msm_host->pclk); atomic_set(&msm_host->controller_clock, 0); Loading Loading @@ -3378,6 +3408,7 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) int i, index = 0; u32 test_bus_val = 0; u32 debug_reg[MAX_TEST_BUS] = {0}; u32 sts = 0; sdhci_msm_cache_debug_data(host); pr_info("----------- VENDOR REGISTER DUMP -----------\n"); Loading Loading @@ -3440,6 +3471,22 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host) pr_info(" Test bus[%d to %d]: 0x%08x 0x%08x 0x%08x 0x%08x\n", i, i + 3, debug_reg[i], debug_reg[i+1], debug_reg[i+2], debug_reg[i+3]); if (host->is_crypto_en) { sdhci_msm_ice_get_status(host, &sts); pr_info("%s: ICE status %x\n", mmc_hostname(host->mmc), sts); } } static void sdhci_msm_reset(struct sdhci_host *host, u8 mask) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; /* Set ICE core to be reset in sync with SDHC core */ if (msm_host->ice.pdev) writel_relaxed(1, host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL); sdhci_reset(host, mask); } /* Loading Loading @@ -4022,6 +4069,8 @@ static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host) } static struct sdhci_ops sdhci_msm_ops = { .crypto_engine_cfg = sdhci_msm_ice_cfg, .crypto_engine_reset = sdhci_msm_ice_reset, .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .check_power_status = sdhci_msm_check_power_status, .platform_execute_tuning = sdhci_msm_execute_tuning, Loading @@ -4035,7 +4084,7 @@ static struct sdhci_ops sdhci_msm_ops = { .config_auto_tuning_cmd = sdhci_msm_config_auto_tuning_cmd, .enable_controller_clock = sdhci_msm_enable_controller_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, .reset = sdhci_msm_reset, .clear_set_dumpregs = sdhci_msm_clear_set_dumpregs, .enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask, .reset_workaround = sdhci_msm_reset_workaround, Loading Loading @@ -4234,7 +4283,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); if (IS_ERR(host)) { ret = PTR_ERR(host); goto out; goto out_host_free; } pltfm_host = sdhci_priv(host); Loading @@ -4242,6 +4291,31 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->mmc = host->mmc; msm_host->pdev = pdev; /* get the ice device vops if present */ ret = sdhci_msm_ice_get_dev(host); if (ret == -EPROBE_DEFER) { /* * SDHCI driver might be probed before ICE driver does. * In that case we would like to return EPROBE_DEFER code * in order to delay its probing. */ dev_err(&pdev->dev, "%s: required ICE device not probed yet err = %d\n", __func__, ret); goto out_host_free; } else if (ret == -ENODEV) { /* * ICE device is not enabled in DTS file. No need for further * initialization of ICE driver. */ dev_warn(&pdev->dev, "%s: ICE device is not enabled", __func__); } else if (ret) { dev_err(&pdev->dev, "%s: sdhci_msm_ice_get_dev failed %d\n", __func__, ret); goto out_host_free; } /* Extract platform data */ if (pdev->dev.of_node) { ret = of_alias_get_id(pdev->dev.of_node, "sdhc"); Loading Loading @@ -4301,6 +4375,28 @@ static int sdhci_msm_probe(struct platform_device *pdev) } atomic_set(&msm_host->controller_clock, 1); if (msm_host->ice.pdev) { /* Setup SDC ICE clock */ msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice_core_clk"); if (!IS_ERR(msm_host->ice_clk)) { /* ICE core has only one clock frequency for now */ ret = clk_set_rate(msm_host->ice_clk, msm_host->pdata->sup_ice_clk_table[0]); if (ret) { dev_err(&pdev->dev, "ICE_CLK rate set failed (%d) for %u\n", ret, msm_host->pdata->sup_ice_clk_table[0]); goto pclk_disable; } ret = clk_prepare_enable(msm_host->ice_clk); if (ret) goto pclk_disable; msm_host->ice_clk_rate = msm_host->pdata->sup_clk_table[0]; } } /* Setup SDC MMC clock */ msm_host->clk = devm_clk_get(&pdev->dev, "core_clk"); if (IS_ERR(msm_host->clk)) { Loading Loading @@ -4527,6 +4623,21 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->mmc->sdr104_wa = msm_host->pdata->sdr104_wa; /* Initialize ICE if present */ if (msm_host->ice.pdev) { ret = sdhci_msm_ice_init(host); if (ret) { dev_err(&pdev->dev, "%s: SDHCi ICE init failed (%d)\n", mmc_hostname(host->mmc), ret); ret = -EINVAL; goto vreg_deinit; } host->is_crypto_en = true; /* Packed commands cannot be encrypted/decrypted using ICE */ msm_host->mmc->caps2 &= ~(MMC_CAP2_PACKED_WR | MMC_CAP2_PACKED_WR_CONTROL); } init_completion(&msm_host->pwr_irq_completion); if (gpio_is_valid(msm_host->pdata->status_gpio)) { Loading Loading @@ -4666,6 +4777,8 @@ static int sdhci_msm_probe(struct platform_device *pdev) clk_disable_unprepare(msm_host->bus_clk); pltfm_free: sdhci_pltfm_free(pdev); out_host_free: devm_kfree(&pdev->dev, msm_host); out: pr_debug("%s: Exit %s\n", dev_name(&pdev->dev), __func__); return ret; Loading Loading @@ -4755,6 +4868,7 @@ static int sdhci_msm_runtime_suspend(struct device *dev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; ktime_t start = ktime_get(); int ret; if (host->mmc->card && mmc_card_sdio(host->mmc->card)) goto defer_disable_host_irq; Loading @@ -4776,6 +4890,12 @@ static int sdhci_msm_runtime_suspend(struct device *dev) trace_sdhci_msm_runtime_suspend(mmc_hostname(host->mmc), 0, ktime_to_us(ktime_sub(ktime_get(), start))); if (host->is_crypto_en) { ret = sdhci_msm_ice_suspend(host); if (ret < 0) pr_err("%s: failed to suspend crypto engine %d\n", mmc_hostname(host->mmc), ret); } return 0; } Loading @@ -4785,6 +4905,21 @@ static int sdhci_msm_runtime_resume(struct device *dev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; ktime_t start = ktime_get(); int ret; if (host->is_crypto_en) { ret = sdhci_msm_enable_controller_clock(host); if (ret) { pr_err("%s: Failed to enable reqd clocks\n", mmc_hostname(host->mmc)); goto skip_ice_resume; } ret = sdhci_msm_ice_resume(host); if (ret) pr_err("%s: failed to resume crypto engine %d\n", mmc_hostname(host->mmc), ret); } skip_ice_resume: if (host->mmc->card && mmc_card_sdio(host->mmc->card)) goto defer_enable_host_irq; Loading
drivers/mmc/host/sdhci.c +42 −0 Original line number Diff line number Diff line Loading @@ -305,6 +305,8 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) /* Resetting the controller clears many */ host->preset_enabled = false; } if (host->is_crypto_en) host->crypto_reset_reqd = true; } static void sdhci_init(struct sdhci_host *host, int soft) Loading Loading @@ -1749,6 +1751,33 @@ static int sdhci_get_tuning_cmd(struct sdhci_host *host) return MMC_SEND_TUNING_BLOCK; } static int sdhci_crypto_cfg(struct sdhci_host *host, struct mmc_request *mrq, u32 slot) { int err = 0; if (host->crypto_reset_reqd && host->ops->crypto_engine_reset) { err = host->ops->crypto_engine_reset(host); if (err) { pr_err("%s: crypto reset failed\n", mmc_hostname(host->mmc)); goto out; } host->crypto_reset_reqd = false; } if (host->ops->crypto_engine_cfg) { err = host->ops->crypto_engine_cfg(host, mrq, slot); if (err) { pr_err("%s: failed to configure crypto\n", mmc_hostname(host->mmc)); goto out; } } out: return err; } static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct sdhci_host *host; Loading Loading @@ -1815,6 +1844,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) sdhci_get_tuning_cmd(host)); } if (host->is_crypto_en) { spin_unlock_irqrestore(&host->lock, flags); if (sdhci_crypto_cfg(host, mrq, 0)) goto end_req; spin_lock_irqsave(&host->lock, flags); } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) sdhci_send_command(host, mrq->sbc); else Loading @@ -1823,6 +1859,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) mmiowb(); spin_unlock_irqrestore(&host->lock, flags); return; end_req: mrq->cmd->error = -EIO; if (mrq->data) mrq->data->error = -EIO; mmc_request_done(host->mmc, mrq); } void sdhci_set_bus_width(struct sdhci_host *host, int width) Loading
drivers/mmc/host/sdhci.h +5 −0 Original line number Diff line number Diff line Loading @@ -628,6 +628,8 @@ struct sdhci_host { enum sdhci_power_policy power_policy; bool sdio_irq_async_status; bool is_crypto_en; bool crypto_reset_reqd; u32 auto_cmd_err_sts; struct ratelimit_state dbg_dump_rs; Loading Loading @@ -666,6 +668,9 @@ struct sdhci_ops { unsigned int (*get_ro)(struct sdhci_host *host); void (*reset)(struct sdhci_host *host, u8 mask); int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); int (*crypto_engine_cfg)(struct sdhci_host *host, struct mmc_request *mrq, u32 slot); int (*crypto_engine_reset)(struct sdhci_host *host); void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); void (*hw_reset)(struct sdhci_host *host); void (*adma_workaround)(struct sdhci_host *host, u32 intmask); Loading