RE: [PATCH v4 15/16] scsi: ufs: ufs-exynos: introduce exynosauto v9 virtual host

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> 
> 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





[Index of Archives]     [Linux SoC Development]     [Linux Rockchip Development]     [Linux for Synopsys ARC Processors]    
  • [Linux on Unisoc (RDA Micro) SoCs]     [Linux Actions SoC]     [Linux USB Development]     [Video for Linux]     [Linux Audio Users]     [Linux SCSI]     [Yosemite News]

  •   Powered by Linux