> > This patch introduces virtual host driver of exynosauto v9 ufs mHCI. > VH(Virtual Host) only supports data transfer functions. So, most of physical > features are broken. So, we need to set below quirks. > - UFSHCD_QUIRK_BROKEN_UIC_CMD > - UFSHCD_QUIRK_SKIP_PH_CONFIGURATION Oh - you set it here. Maybe just add a comment in your commit log of patches 1 & 2 that you are doing it later. > Before initialization, the VH is necessary to wait until PH is ready. > It's implemented as polling at the moment. > > Cc: Alim Akhtar <alim.akhtar@xxxxxxxxxxx> > Cc: Kiwoong Kim <kwmad.kim@xxxxxxxxxxx> > Cc: Krzysztof Kozlowski <krzysztof.kozlowski@xxxxxxxxxxxxx> > Signed-off-by: Chanho Park <chanho61.park@xxxxxxxxxxx> > --- > drivers/scsi/ufs/ufs-exynos.c | 84 +++++++++++++++++++++++++++++++++++ > 1 file changed, 84 insertions(+) > > diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c index > 32f73c906018..c2b654027b0f 100644 > --- a/drivers/scsi/ufs/ufs-exynos.c > +++ b/drivers/scsi/ufs/ufs-exynos.c > @@ -121,6 +121,8 @@ > #define HCI_MH_ALLOWABLE_TRAN_OF_VH 0x30C > #define HCI_MH_IID_IN_TASK_TAG 0X308 > > +#define PH_READY_TIMEOUT_MS (5 * MSEC_PER_SEC) > + > enum { > UNIPRO_L1_5 = 0,/* PHY Adapter */ > UNIPRO_L2, /* Data Link */ > @@ -1403,6 +1405,68 @@ static int exynos_ufs_resume(struct ufs_hba *hba, > enum ufs_pm_op pm_op) > return 0; > } > > +static int exynosauto_ufs_vh_link_startup_notify(struct ufs_hba *hba, > + enum > +ufs_notify_change_status status) { > + if (status == POST_CHANGE) { > + ufshcd_set_link_active(hba); > + ufshcd_set_ufs_dev_active(hba); > + hba->wlun_dev_clr_ua = true; wlun_dev_clr_ua no longer exists - needs rebase > + } > + > + return 0; > +} > + > +static int exynosauto_ufs_vh_wait_ph_ready(struct ufs_hba *hba) { > + u32 mbox; > + ktime_t start, stop; > + > + start = ktime_get(); > + stop = ktime_add(start, ms_to_ktime(PH_READY_TIMEOUT_MS)); > + > + do { > + mbox = ufshcd_readl(hba, PH2VH_MBOX); > + if ((mbox & MH_MSG_MASK) == MH_MSG_PH_READY) > + return 0; Maybe add a comment here that the mbox protocol will be defined later. Thanks, Avri > + > + usleep_range(40, 50); > + } while (ktime_before(ktime_get(), stop)); > + > + return -ETIME; > +} > + > +static int exynosauto_ufs_vh_init(struct ufs_hba *hba) { > + struct device *dev = hba->dev; > + struct platform_device *pdev = to_platform_device(dev); > + struct exynos_ufs *ufs; > + int ret; > + > + ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL); > + if (!ufs) > + return -ENOMEM; > + > + /* exynos-specific hci */ > + ufs->reg_hci = devm_platform_ioremap_resource_byname(pdev, > "vs_hci"); > + if (IS_ERR(ufs->reg_hci)) { > + dev_err(dev, "cannot ioremap for hci vendor register\n"); > + return PTR_ERR(ufs->reg_hci); > + } > + > + ret = exynosauto_ufs_vh_wait_ph_ready(hba); > + if (ret) > + return ret; > + > + ufs->drv_data = device_get_match_data(dev); > + if (!ufs->drv_data) > + return -ENODEV; > + > + exynos_ufs_priv_init(hba, ufs); > + > + return 0; > +} > + > static struct ufs_hba_variant_ops ufs_hba_exynos_ops = { > .name = "exynos_ufs", > .init = exynos_ufs_init, > @@ -1417,6 +1481,12 @@ static struct ufs_hba_variant_ops > ufs_hba_exynos_ops = { > .resume = exynos_ufs_resume, > }; > > +static struct ufs_hba_variant_ops ufs_hba_exynosauto_vh_ops = { > + .name = "exynosauto_ufs_vh", > + .init = exynosauto_ufs_vh_init, > + .link_startup_notify = exynosauto_ufs_vh_link_startup_notify, > +}; > + > static int exynos_ufs_probe(struct platform_device *pdev) { > int err; > @@ -1485,6 +1555,18 @@ static struct exynos_ufs_drv_data > exynosauto_ufs_drvs = { > .post_pwr_change = exynosauto_ufs_post_pwr_change, > }; > > +static struct exynos_ufs_drv_data exynosauto_ufs_vh_drvs = { > + .vops = &ufs_hba_exynosauto_vh_ops, > + .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | > + UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | > + UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | > + UFSHCI_QUIRK_BROKEN_HCE | > + UFSHCD_QUIRK_BROKEN_UIC_CMD | > + UFSHCD_QUIRK_SKIP_PH_CONFIGURATION | > + UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, > + .opts = EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX, > +}; > + > static struct exynos_ufs_drv_data exynos_ufs_drvs = { > .uic_attr = &exynos7_uic_attr, > .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | > @@ -1512,6 +1594,8 @@ static const struct of_device_id > exynos_ufs_of_match[] = { > .data = &exynos_ufs_drvs }, > { .compatible = "samsung,exynosautov9-ufs", > .data = &exynosauto_ufs_drvs }, > + { .compatible = "samsung,exynosautov9-ufs-vh", > + .data = &exynosauto_ufs_vh_drvs }, > {}, > }; > > -- > 2.33.0