scsi: ufs-mediatek: Create reset control device_link
authorPeter Wang <peter.wang@mediatek.com>
Wed, 2 Jun 2021 02:42:00 +0000 (10:42 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 16 Jun 2021 02:36:23 +0000 (22:36 -0400)
Mediatek UFS reset function relies on Reset Control provided by
reset-ti-syscon. To make Mediatek Reset Control work properly, select
reset-ti-syscon to ensure it is being built.

In addition, establish device_link to wait until reset-ti-syscon
initialization is complete during UFS probing.

Link: https://lore.kernel.org/r/1622601720-22466-1-git-send-email-peter.wang@mediatek.com
Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/ufs/Kconfig
drivers/scsi/ufs/ufs-mediatek.c

index 07cf415..2d13795 100644 (file)
@@ -115,6 +115,7 @@ config SCSI_UFS_MEDIATEK
        tristate "Mediatek specific hooks to UFS controller platform driver"
        depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK
        select PHY_MTK_UFS
        tristate "Mediatek specific hooks to UFS controller platform driver"
        depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK
        select PHY_MTK_UFS
+       select RESET_TI_SYSCON
        help
          This selects the Mediatek specific additions to UFSHCD platform driver.
          UFS host on Mediatek needs some vendor specific configuration before
        help
          This selects the Mediatek specific additions to UFSHCD platform driver.
          UFS host on Mediatek needs some vendor specific configuration before
index bbe0596..e883cab 100644 (file)
@@ -1068,9 +1068,38 @@ static int ufs_mtk_probe(struct platform_device *pdev)
 {
        int err;
        struct device *dev = &pdev->dev;
 {
        int err;
        struct device *dev = &pdev->dev;
+       struct device_node *reset_node;
+       struct platform_device *reset_pdev;
+       struct device_link *link;
+
+       reset_node = of_find_compatible_node(NULL, NULL,
+                                            "ti,syscon-reset");
+       if (!reset_node) {
+               dev_notice(dev, "find ti,syscon-reset fail\n");
+               goto skip_reset;
+       }
+       reset_pdev = of_find_device_by_node(reset_node);
+       if (!reset_pdev) {
+               dev_notice(dev, "find reset_pdev fail\n");
+               goto skip_reset;
+       }
+       link = device_link_add(dev, &reset_pdev->dev,
+               DL_FLAG_AUTOPROBE_CONSUMER);
+       if (!link) {
+               dev_notice(dev, "add reset device_link fail\n");
+               goto skip_reset;
+       }
+       /* supplier is not probed */
+       if (link->status == DL_STATE_DORMANT) {
+               err = -EPROBE_DEFER;
+               goto out;
+       }
 
 
+skip_reset:
        /* perform generic probe */
        err = ufshcd_pltfrm_init(pdev, &ufs_hba_mtk_vops);
        /* perform generic probe */
        err = ufshcd_pltfrm_init(pdev, &ufs_hba_mtk_vops);
+
+out:
        if (err)
                dev_info(dev, "probe failed %d\n", err);
 
        if (err)
                dev_info(dev, "probe failed %d\n", err);