diff options
Diffstat (limited to 'drivers/ufs')
| -rw-r--r-- | drivers/ufs/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/ufs/ufs-amd-versal2.c | 1 | ||||
| -rw-r--r-- | drivers/ufs/ufs-mediatek.c | 42 | ||||
| -rw-r--r-- | drivers/ufs/ufs-mediatek.h | 2 | ||||
| -rw-r--r-- | drivers/ufs/ufs-qcom.c | 54 | ||||
| -rw-r--r-- | drivers/ufs/ufs-renesas-rcar-gen5.c | 16 | ||||
| -rw-r--r-- | drivers/ufs/ufs-rockchip.c | 13 | ||||
| -rw-r--r-- | drivers/ufs/ufs-uclass.c | 10 |
8 files changed, 98 insertions, 46 deletions
diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig index 49472933de3..c1b84bd7559 100644 --- a/drivers/ufs/Kconfig +++ b/drivers/ufs/Kconfig @@ -19,12 +19,12 @@ config UFS_AMD_VERSAL2 config UFS_CADENCE bool "Cadence platform driver for UFS" depends on UFS - help + help This selects the platform driver for the Cadence UFS host controller present on present TI's J721e devices. config UFS_MEDIATEK - tristate "MediaTek UFS Host Controller Driver" + bool "MediaTek UFS Host Controller Driver" depends on UFS && ARCH_MEDIATEK select PHY_MTK_UFS help @@ -51,7 +51,7 @@ config UFS_PCI config UFS_QCOM bool "Qualcomm Host Controller driver for UFS" depends on UFS && ARCH_SNAPDRAGON - help + help This selects the platform driver for the UFS host controller present on Qualcomm Snapdragon SoCs. diff --git a/drivers/ufs/ufs-amd-versal2.c b/drivers/ufs/ufs-amd-versal2.c index 6c949b2ca76..3369d32d924 100644 --- a/drivers/ufs/ufs-amd-versal2.c +++ b/drivers/ufs/ufs-amd-versal2.c @@ -563,4 +563,5 @@ U_BOOT_DRIVER(ufs_versal2_pltfm) = { .id = UCLASS_UFS, .of_match = ufs_versal2_ids, .probe = ufs_versal2_probe, + .priv_auto = sizeof(struct ufs_versal2_priv), }; diff --git a/drivers/ufs/ufs-mediatek.c b/drivers/ufs/ufs-mediatek.c index e860d765eea..268627d5863 100644 --- a/drivers/ufs/ufs-mediatek.c +++ b/drivers/ufs/ufs-mediatek.c @@ -182,19 +182,15 @@ static int ufs_mtk_bind_mphy(struct ufs_hba *hba) struct ufs_mtk_host *host = dev_get_priv(hba->dev); int err = 0; - err = generic_phy_get_by_index(hba->dev, 0, host->mphy); + err = generic_phy_get_by_index(hba->dev, 0, &host->mphy); - if (IS_ERR(host->mphy)) { - err = PTR_ERR(host->mphy); - if (err != -ENODEV) { - dev_info(hba->dev, "%s: Could NOT get a valid PHY %d\n", __func__, - err); - } + if (err) { + if (err == -ENOENT) + return 0; /* no PHY, nothing to do */ + dev_err(hba->dev, "Failed to get PHY: %d.\n", err); + return err; } - if (err) - host->mphy = NULL; - return err; } @@ -321,19 +317,35 @@ static int ufs_mtk_init(struct ufs_hba *hba) ufs_mtk_init_reset(hba); - // TODO: Clocking + err = clk_get_bulk(hba->dev, &priv->clks); + if (err) { + dev_err(hba->dev, "failed to initialize clocks, err:%d\n", err); + return err; + } + + err = clk_enable_bulk(&priv->clks); + if (err) { + dev_err(hba->dev, "failed to enable clocks, err:%d\n", err); + goto err_clk_enable; + } - err = generic_phy_power_on(priv->mphy); + err = generic_phy_power_on(&priv->mphy); if (err) { dev_err(hba->dev, "%s: phy init failed, err = %d\n", __func__, err); - return err; + goto err_phy_power_on; } ufs_mtk_setup_ref_clk(hba, true); ufs_mtk_get_hw_ip_version(hba); return 0; + +err_phy_power_on: + clk_disable_bulk(&priv->clks); +err_clk_enable: + clk_release_bulk(&priv->clks); + return err; } static int ufs_mtk_device_reset(struct ufs_hba *hba) @@ -383,7 +395,9 @@ static int ufs_mtk_probe(struct udevice *dev) static const struct udevice_id ufs_mtk_ids[] = { { .compatible = "mediatek,mt6878-ufshci" }, - {}, + { .compatible = "mediatek,mt8183-ufshci" }, + { .compatible = "mediatek,mt8195-ufshci" }, + { } }; U_BOOT_DRIVER(mediatek_ufshci) = { diff --git a/drivers/ufs/ufs-mediatek.h b/drivers/ufs/ufs-mediatek.h index 11a83d34c5b..0ffd0483eff 100644 --- a/drivers/ufs/ufs-mediatek.h +++ b/drivers/ufs/ufs-mediatek.h @@ -154,7 +154,7 @@ struct ufs_mtk_mcq_intr_info { }; struct ufs_mtk_host { - struct phy *mphy; + struct phy mphy; struct reset_ctl *unipro_reset; struct reset_ctl *crypto_reset; struct reset_ctl *hci_reset; diff --git a/drivers/ufs/ufs-qcom.c b/drivers/ufs/ufs-qcom.c index dc40ee62daf..f5f5a6eb110 100644 --- a/drivers/ufs/ufs-qcom.c +++ b/drivers/ufs/ufs-qcom.c @@ -30,6 +30,7 @@ #define UFS_CPU_MAX_BANDWIDTH 819200 static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_hba *hba, bool enable); +static u32 ufs_qcom_get_core_clk_unipro_max_freq(struct ufs_hba *hba); static int ufs_qcom_enable_clks(struct ufs_qcom_priv *priv) { @@ -47,17 +48,6 @@ static int ufs_qcom_enable_clks(struct ufs_qcom_priv *priv) return 0; } -static int ufs_qcom_init_clks(struct ufs_qcom_priv *priv) -{ - int err; - struct udevice *dev = priv->hba->dev; - - err = clk_get_bulk(dev, &priv->clks); - if (err) - return err; - - return 0; -} static int ufs_qcom_check_hibern8(struct ufs_hba *hba) { @@ -557,10 +547,45 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_hba *hba, bool enable) static int ufs_qcom_init(struct ufs_hba *hba) { struct ufs_qcom_priv *priv = dev_get_priv(hba->dev); + struct udevice *dev = hba->dev; + struct clk clk; + u32 max_freq; + long rate; int err; priv->hba = hba; + /* Get maximum frequency for core_clk_unipro from device tree */ + max_freq = ufs_qcom_get_core_clk_unipro_max_freq(hba); + + /* Get and configure core_clk_unipro */ + err = clk_get_by_name(dev, "core_clk_unipro", &clk); + if (err) { + dev_err(dev, "Failed to get core_clk_unipro: %d\n", err); + return err; + } + + rate = clk_set_rate(&clk, max_freq); + if (rate < 0) { + dev_err(dev, "Failed to set core_clk_unipro rate to %u Hz: %ld\n", + max_freq, rate); + } + + /* Get all clocks */ + err = clk_get_bulk(dev, &priv->clks); + if (err) { + dev_err(dev, "clk_get_bulk failed: %d\n", err); + return err; + } + + /* Enable clocks */ + err = ufs_qcom_enable_clks(priv); + if (err) { + dev_err(dev, "failed to enable clocks: %d\n", err); + clk_release_bulk(&priv->clks); + return err; + } + /* setup clocks */ ufs_qcom_setup_clocks(hba, true, PRE_CHANGE); @@ -579,14 +604,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) priv->hw_ver.minor, priv->hw_ver.step); - err = ufs_qcom_init_clks(priv); - if (err) { - dev_err(hba->dev, "failed to initialize clocks, err:%d\n", err); - return err; - } - ufs_qcom_advertise_quirks(hba); - ufs_qcom_setup_clocks(hba, true, POST_CHANGE); return 0; } diff --git a/drivers/ufs/ufs-renesas-rcar-gen5.c b/drivers/ufs/ufs-renesas-rcar-gen5.c index a21ae3f390e..a9473cd60b1 100644 --- a/drivers/ufs/ufs-renesas-rcar-gen5.c +++ b/drivers/ufs/ufs-renesas-rcar-gen5.c @@ -92,14 +92,14 @@ static int ufs_renesas_pre_init(struct ufs_hba *hba) ufs_dme_command(hba, 0x00000002, 0x81010000, 0x00000000, 0x00000005); ufs_dme_command(hba, 0x00000002, 0x81150000, 0x00000000, 0x00000001); ufs_dme_command(hba, 0x00000002, 0x81180000, 0x00000000, 0x00000001); - ufs_dme_command(hba, 0x00000002, 0x80090000, 0x00000000, 0x00000000); - ufs_dme_command(hba, 0x00000002, 0x800a0000, 0x00000000, 0x000000c8); - ufs_dme_command(hba, 0x00000002, 0x80090001, 0x00000000, 0x00000000); - ufs_dme_command(hba, 0x00000002, 0x800a0001, 0x00000000, 0x000000c8); - ufs_dme_command(hba, 0x00000002, 0x800a0004, 0x00000000, 0x00000000); - ufs_dme_command(hba, 0x00000002, 0x800b0004, 0x00000000, 0x00000064); - ufs_dme_command(hba, 0x00000002, 0x800a0005, 0x00000000, 0x00000000); - ufs_dme_command(hba, 0x00000002, 0x800b0005, 0x00000000, 0x00000064); + ufs_dme_command(hba, 0x00000002, 0x80090000, 0x00000000, 0x0000000c); + ufs_dme_command(hba, 0x00000002, 0x800a0000, 0x00000000, 0x00000080); + ufs_dme_command(hba, 0x00000002, 0x80090001, 0x00000000, 0x0000000c); + ufs_dme_command(hba, 0x00000002, 0x800a0001, 0x00000000, 0x00000080); + ufs_dme_command(hba, 0x00000002, 0x800a0004, 0x00000000, 0x00000003); + ufs_dme_command(hba, 0x00000002, 0x800b0004, 0x00000000, 0x000000ea); + ufs_dme_command(hba, 0x00000002, 0x800a0005, 0x00000000, 0x00000003); + ufs_dme_command(hba, 0x00000002, 0x800b0005, 0x00000000, 0x000000ea); ufs_dme_command(hba, 0x00000002, 0xd0850000, 0x00000000, 0x00000001); writew(0x0001, priv->phy_base + 0x20000); diff --git a/drivers/ufs/ufs-rockchip.c b/drivers/ufs/ufs-rockchip.c index a13236c7f76..dc4b9b5c86d 100644 --- a/drivers/ufs/ufs-rockchip.c +++ b/drivers/ufs/ufs-rockchip.c @@ -19,13 +19,22 @@ #include "unipro.h" #include "ufs-rockchip.h" +static void ufs_rockchip_controller_reset(struct ufs_rockchip_host *host) +{ + reset_assert_bulk(&host->rsts); + udelay(1); + reset_deassert_bulk(&host->rsts); +} + static int ufs_rockchip_hce_enable_notify(struct ufs_hba *hba, enum ufs_notify_change_status status) { int err = 0; - if (status != POST_CHANGE) + if (status != POST_CHANGE) { + ufs_rockchip_controller_reset(dev_get_priv(hba->dev)); return 0; + } ufshcd_dme_reset(hba); ufshcd_dme_enable(hba); @@ -150,6 +159,8 @@ static int ufs_rockchip_common_init(struct ufs_hba *hba) return err; } + ufs_rockchip_controller_reset(host); + err = gpio_request_by_name(dev, "reset-gpios", 0, &host->device_reset, GPIOD_IS_OUT | GPIOD_ACTIVE_LOW); if (err) { diff --git a/drivers/ufs/ufs-uclass.c b/drivers/ufs/ufs-uclass.c index 81fd431f951..6a51f337e47 100644 --- a/drivers/ufs/ufs-uclass.c +++ b/drivers/ufs/ufs-uclass.c @@ -1751,7 +1751,15 @@ static int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, goto out; } - buff_ascii = kmalloc(ascii_len, GFP_KERNEL); + /* + * utf-8 is encoded using up to 4-Bytes per character, + * however, we only allocate such a buffer because the + * utf16_to_utf8() converts the entire $ascii_len worth + * of input characters into up to 4-Byte long utf-8 + * characters. The rest of the function uses only up to + * $ascii_len bytes of that utf-8 string. + */ + buff_ascii = kmalloc(ascii_len * 4, GFP_KERNEL); if (!buff_ascii) { err = -ENOMEM; goto out; |
