Loading drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c +26 −51 Original line number Original line Diff line number Diff line Loading @@ -30,36 +30,27 @@ #define UFS_PHY_NAME "ufs_msm_phy_qmp_20nm" #define UFS_PHY_NAME "ufs_msm_phy_qmp_20nm" static void ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *phy) static int ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy) { { struct ufs_msm_phy_calibration *tbl; struct ufs_msm_phy_calibration *tbl_A, *tbl_B; int tbl_size; int tbl_size_A, tbl_size_B; int i; int rate = UFS_MSM_LIMIT_HS_RATE; int err; tbl_size = ARRAY_SIZE(phy_cal_table_rate_A); tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A); tbl = phy_cal_table_rate_A; tbl_A = phy_cal_table_rate_A; /* tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); * calibration according phy_cal_table_rate_A happens tbl_B = phy_cal_table_rate_B; * regardless of the rate we intend to work with. * Only in case we would like to work in rate B, we need * to override a subset of registers of phy_cal_table_rate_A * table, with phy_cal_table_rate_B table. */ for (i = 0; i < tbl_size; i++) writel_relaxed(tbl[i].cfg_value, phy->mmio + tbl[i].reg_offset); if (UFS_MSM_LIMIT_HS_RATE == PA_HS_MODE_B) { err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A, tbl = phy_cal_table_rate_B; tbl_B, tbl_size_B, rate); tbl_size = ARRAY_SIZE(phy_cal_table_rate_B); for (i = 0; i < tbl_size; i++) if (err) writel_relaxed(tbl[i].cfg_value, dev_err(ufs_msm_phy->dev, "%s: ufs_msm_phy_calibrate() failed %d\n", phy->mmio + tbl[i].reg_offset); __func__, err); } /* flush buffered writes */ return err; mb(); } } static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy) static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy) Loading Loading @@ -192,7 +183,6 @@ static int ufs_msm_phy_qmp_20nm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device *dev = &pdev->dev; struct phy *generic_phy; struct phy *generic_phy; struct ufs_msm_phy_qmp_20nm *phy; struct ufs_msm_phy_qmp_20nm *phy; struct phy_provider *phy_provider; int err = 0; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); Loading @@ -202,31 +192,16 @@ static int ufs_msm_phy_qmp_20nm_probe(struct platform_device *pdev) goto out; goto out; } } err = ufs_msm_phy_base_init(pdev, &phy->common_cfg); generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg, if (err) { &ufs_msm_phy_qmp_20nm_phy_ops, &phy_20nm_ops); dev_err(dev, "%s: phy base init failed %d\n", __func__, err); goto out; } phy->common_cfg.phy_spec_ops = &phy_20nm_ops; phy->common_cfg.cached_regs = NULL; phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (IS_ERR(phy_provider)) { err = PTR_ERR(phy_provider); dev_err(dev, "%s: failed to register phy %d\n", __func__, err); goto out; } generic_phy = devm_phy_create(dev, &ufs_msm_phy_qmp_20nm_phy_ops, NULL); if (!generic_phy) { if (IS_ERR(generic_phy)) { dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n", devm_of_phy_provider_unregister(dev, phy_provider); __func__); err = PTR_ERR(generic_phy); err = -EIO; dev_err(dev, "%s: failed to create phy %d\n", __func__, err); goto out; goto out; } } phy->common_cfg.dev = dev; phy_set_drvdata(generic_phy, phy); phy_set_drvdata(generic_phy, phy); strlcpy(phy->common_cfg.name, UFS_PHY_NAME, strlcpy(phy->common_cfg.name, UFS_PHY_NAME, Loading drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c +26 −50 Original line number Original line Diff line number Diff line Loading @@ -97,46 +97,34 @@ out: return err; return err; } } static void ufs_msm_phy_qmp_28nm_calibrate(struct ufs_msm_phy *ufs_msm_phy) static int ufs_msm_phy_qmp_28nm_calibrate(struct ufs_msm_phy *ufs_msm_phy) { { struct ufs_msm_phy_calibration *tbl; struct ufs_msm_phy_calibration *tbl_A, *tbl_B; int tbl_size; int tbl_size_A, tbl_size_B; int i; int rate = UFS_MSM_LIMIT_HS_RATE; u8 major = ufs_msm_phy->host_ctrl_rev_major; u8 major = ufs_msm_phy->host_ctrl_rev_major; u16 minor = ufs_msm_phy->host_ctrl_rev_minor; u16 minor = ufs_msm_phy->host_ctrl_rev_minor; u16 step = ufs_msm_phy->host_ctrl_rev_step; u16 step = ufs_msm_phy->host_ctrl_rev_step; int err; if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) { if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) { tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A); tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A); tbl = phy_cal_table_ctrl_1_1_0_rate_A; tbl_A = phy_cal_table_ctrl_1_1_0_rate_A; } else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { } else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A); tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A); tbl = phy_cal_table_ctrl_1_1_1_rate_A; tbl_A = phy_cal_table_ctrl_1_1_1_rate_A; } } /* tbl_B = phy_cal_table_rate_B; * calibration according phy_cal_table_ctrl_x_x_x_rate_A tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); * happens regardless of the rate we intend to work with. * Only in case we would like to work in rate B, we need * to override a subset of registers of * phy_cal_table_ctrl_x_x_x_rate_A table, with phy_cal_table_rate_B * table. */ for (i = 0; i < tbl_size; i++) writel_relaxed(tbl[i].cfg_value, ufs_msm_phy->mmio + tbl[i].reg_offset); if (UFS_MSM_LIMIT_HS_RATE == PA_HS_MODE_B) { tbl = phy_cal_table_rate_B; tbl_size = ARRAY_SIZE(phy_cal_table_rate_B); for (i = 0; i < tbl_size; i++) err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A, writel_relaxed(tbl[i].cfg_value, tbl_B, tbl_size_B, rate); ufs_msm_phy->mmio + tbl[i].reg_offset); if (err) } dev_err(ufs_msm_phy->dev, "%s: ufs_msm_phy_calibrate() failed %d\n", __func__, err); /* flush buffered writes */ return err; mb(); } } static static Loading Loading @@ -286,7 +274,7 @@ static int ufs_msm_phy_qmp_28nm_resume(struct phy *generic_phy) return err; return err; } } struct phy_ops ufs_msm_phy_ops = { struct phy_ops ufs_msm_phy_qmp_28nm_phy_ops = { .init = ufs_msm_phy_qmp_28nm_init, .init = ufs_msm_phy_qmp_28nm_init, .exit = ufs_msm_phy_exit, .exit = ufs_msm_phy_exit, .power_on = ufs_msm_phy_power_on, .power_on = ufs_msm_phy_power_on, Loading @@ -312,7 +300,6 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device *dev = &pdev->dev; int err = 0; int err = 0; struct phy *generic_phy; struct phy *generic_phy; struct phy_provider *phy_provider; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); if (!phy) { if (!phy) { Loading @@ -321,37 +308,26 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev) goto out; goto out; } } err = ufs_msm_phy_base_init(pdev, &phy->common_cfg); if (err) { dev_err(dev, "%s: phy base init failed %d\n", __func__, err); goto out; } phy->common_cfg.phy_spec_ops = &phy_28nm_ops; phy->common_cfg.cached_regs = phy->common_cfg.cached_regs = (struct ufs_msm_phy_calibration *)cached_phy_regs; (struct ufs_msm_phy_calibration *)cached_phy_regs; phy->common_cfg.cached_regs_table_size = phy->common_cfg.cached_regs_table_size = ARRAY_SIZE(cached_phy_regs); ARRAY_SIZE(cached_phy_regs); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg, if (IS_ERR(phy_provider)) { &ufs_msm_phy_qmp_28nm_phy_ops, &phy_28nm_ops); err = PTR_ERR(phy_provider); dev_err(dev, "%s: failed to register phy %d\n", __func__, err); goto out; } generic_phy = devm_phy_create(dev, &ufs_msm_phy_ops, NULL); if (!generic_phy) { if (IS_ERR(generic_phy)) { dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n", err = PTR_ERR(generic_phy); __func__); dev_err(dev, "%s: failed to create phy %d\n", __func__, err); err = -EIO; goto out; goto out; } } phy->common_cfg.dev = dev; phy_set_drvdata(generic_phy, phy); phy_set_drvdata(generic_phy, phy); strlcpy(phy->common_cfg.name, UFS_PHY_NAME, strlcpy(phy->common_cfg.name, UFS_PHY_NAME, sizeof(phy->common_cfg.name)); sizeof(phy->common_cfg.name)); out: out: return err; return err; } } Loading drivers/scsi/ufs/ufs-msm-phy.c +85 −2 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,87 @@ #include "ufs-msm.h" #include "ufs-msm.h" #include "ufs-msm-phy.h" #include "ufs-msm-phy.h" int ufs_msm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy, struct ufs_msm_phy_calibration *tbl_A, int tbl_size_A, struct ufs_msm_phy_calibration *tbl_B, int tbl_size_B, int rate) { int i; int ret = 0; if (!tbl_A) { dev_err(ufs_msm_phy->dev, "%s: tbl_A is NULL", __func__); ret = EINVAL; goto out; } for (i = 0; i < tbl_size_A; i++) writel_relaxed(tbl_A[i].cfg_value, ufs_msm_phy->mmio + tbl_A[i].reg_offset); /* * In case we would like to work in rate B, we need * to override a registers that were configured in rate A table * with registers of rate B table. * table. */ if (rate == PA_HS_MODE_B) { if (!tbl_B) { dev_err(ufs_msm_phy->dev, "%s: tbl_B is NULL", __func__); ret = EINVAL; goto out; } for (i = 0; i < tbl_size_B; i++) writel_relaxed(tbl_B[i].cfg_value, ufs_msm_phy->mmio + tbl_B[i].reg_offset); } /* flush buffered writes */ mb(); out: return ret; } struct phy *ufs_msm_phy_generic_probe(struct platform_device *pdev, struct ufs_msm_phy *common_cfg, struct phy_ops *ufs_msm_phy_gen_ops, struct ufs_msm_phy_specific_ops *phy_spec_ops) { int err; struct device *dev = &pdev->dev; struct phy *generic_phy = NULL; struct phy_provider *phy_provider; err = ufs_msm_phy_base_init(pdev, common_cfg); if (err) { dev_err(dev, "%s: phy base init failed %d\n", __func__, err); goto out; } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (IS_ERR(phy_provider)) { err = PTR_ERR(phy_provider); dev_err(dev, "%s: failed to register phy %d\n", __func__, err); goto out; } generic_phy = devm_phy_create(dev, ufs_msm_phy_gen_ops, NULL); if (IS_ERR(generic_phy)) { err = PTR_ERR(generic_phy); dev_err(dev, "%s: failed to create phy %d\n", __func__, err); goto out; } common_cfg->phy_spec_ops = phy_spec_ops; common_cfg->dev = dev; out: return generic_phy; } /* /* * This assumes the embedded phy structure inside generic_phy is of type * This assumes the embedded phy structure inside generic_phy is of type * struct ufs_msm_phy. In order to function properly it's crucial * struct ufs_msm_phy. In order to function properly it's crucial Loading Loading @@ -447,8 +528,10 @@ int ufs_msm_phy_calibrate_phy(struct phy *generic_phy) __func__); __func__); ret = -ENOTSUPP; ret = -ENOTSUPP; } else { } else { ufs_msm_phy->phy_spec_ops-> ret = ufs_msm_phy->phy_spec_ops-> calibrate_phy(ufs_msm_phy); calibrate_phy(ufs_msm_phy); dev_err(ufs_msm_phy->dev, "%s: calibrate_phy() failed %d\n", __func__, ret); } } return ret; return ret; Loading drivers/scsi/ufs/ufs-msm-phy.h +9 −1 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,7 @@ struct ufs_msm_phy { * and writes to QSERDES_RX_SIGDET_CNTRL attribute * and writes to QSERDES_RX_SIGDET_CNTRL attribute */ */ struct ufs_msm_phy_specific_ops { struct ufs_msm_phy_specific_ops { void (*calibrate_phy) (struct ufs_msm_phy *phy); int (*calibrate_phy) (struct ufs_msm_phy *phy); void (*start_serdes) (struct ufs_msm_phy *phy); void (*start_serdes) (struct ufs_msm_phy *phy); void (*save_configuration)(struct ufs_msm_phy *phy); void (*save_configuration)(struct ufs_msm_phy *phy); int (*is_physical_coding_sublayer_ready) (struct ufs_msm_phy *phy); int (*is_physical_coding_sublayer_ready) (struct ufs_msm_phy *phy); Loading Loading @@ -173,4 +173,12 @@ int ufs_msm_phy_init_vregulators(struct phy *generic_phy, struct ufs_msm_phy *phy_common); struct ufs_msm_phy *phy_common); int ufs_msm_phy_remove(struct phy *generic_phy, int ufs_msm_phy_remove(struct phy *generic_phy, struct ufs_msm_phy *ufs_msm_phy); struct ufs_msm_phy *ufs_msm_phy); struct phy *ufs_msm_phy_generic_probe(struct platform_device *pdev, struct ufs_msm_phy *common_cfg, struct phy_ops *ufs_msm_phy_gen_ops, struct ufs_msm_phy_specific_ops *phy_spec_ops); int ufs_msm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy, struct ufs_msm_phy_calibration *tbl_A, int tbl_size_A, struct ufs_msm_phy_calibration *tbl_B, int tbl_size_B, int rate); #endif #endif Loading
drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c +26 −51 Original line number Original line Diff line number Diff line Loading @@ -30,36 +30,27 @@ #define UFS_PHY_NAME "ufs_msm_phy_qmp_20nm" #define UFS_PHY_NAME "ufs_msm_phy_qmp_20nm" static void ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *phy) static int ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy) { { struct ufs_msm_phy_calibration *tbl; struct ufs_msm_phy_calibration *tbl_A, *tbl_B; int tbl_size; int tbl_size_A, tbl_size_B; int i; int rate = UFS_MSM_LIMIT_HS_RATE; int err; tbl_size = ARRAY_SIZE(phy_cal_table_rate_A); tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A); tbl = phy_cal_table_rate_A; tbl_A = phy_cal_table_rate_A; /* tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); * calibration according phy_cal_table_rate_A happens tbl_B = phy_cal_table_rate_B; * regardless of the rate we intend to work with. * Only in case we would like to work in rate B, we need * to override a subset of registers of phy_cal_table_rate_A * table, with phy_cal_table_rate_B table. */ for (i = 0; i < tbl_size; i++) writel_relaxed(tbl[i].cfg_value, phy->mmio + tbl[i].reg_offset); if (UFS_MSM_LIMIT_HS_RATE == PA_HS_MODE_B) { err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A, tbl = phy_cal_table_rate_B; tbl_B, tbl_size_B, rate); tbl_size = ARRAY_SIZE(phy_cal_table_rate_B); for (i = 0; i < tbl_size; i++) if (err) writel_relaxed(tbl[i].cfg_value, dev_err(ufs_msm_phy->dev, "%s: ufs_msm_phy_calibrate() failed %d\n", phy->mmio + tbl[i].reg_offset); __func__, err); } /* flush buffered writes */ return err; mb(); } } static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy) static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy) Loading Loading @@ -192,7 +183,6 @@ static int ufs_msm_phy_qmp_20nm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device *dev = &pdev->dev; struct phy *generic_phy; struct phy *generic_phy; struct ufs_msm_phy_qmp_20nm *phy; struct ufs_msm_phy_qmp_20nm *phy; struct phy_provider *phy_provider; int err = 0; int err = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); Loading @@ -202,31 +192,16 @@ static int ufs_msm_phy_qmp_20nm_probe(struct platform_device *pdev) goto out; goto out; } } err = ufs_msm_phy_base_init(pdev, &phy->common_cfg); generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg, if (err) { &ufs_msm_phy_qmp_20nm_phy_ops, &phy_20nm_ops); dev_err(dev, "%s: phy base init failed %d\n", __func__, err); goto out; } phy->common_cfg.phy_spec_ops = &phy_20nm_ops; phy->common_cfg.cached_regs = NULL; phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (IS_ERR(phy_provider)) { err = PTR_ERR(phy_provider); dev_err(dev, "%s: failed to register phy %d\n", __func__, err); goto out; } generic_phy = devm_phy_create(dev, &ufs_msm_phy_qmp_20nm_phy_ops, NULL); if (!generic_phy) { if (IS_ERR(generic_phy)) { dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n", devm_of_phy_provider_unregister(dev, phy_provider); __func__); err = PTR_ERR(generic_phy); err = -EIO; dev_err(dev, "%s: failed to create phy %d\n", __func__, err); goto out; goto out; } } phy->common_cfg.dev = dev; phy_set_drvdata(generic_phy, phy); phy_set_drvdata(generic_phy, phy); strlcpy(phy->common_cfg.name, UFS_PHY_NAME, strlcpy(phy->common_cfg.name, UFS_PHY_NAME, Loading
drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c +26 −50 Original line number Original line Diff line number Diff line Loading @@ -97,46 +97,34 @@ out: return err; return err; } } static void ufs_msm_phy_qmp_28nm_calibrate(struct ufs_msm_phy *ufs_msm_phy) static int ufs_msm_phy_qmp_28nm_calibrate(struct ufs_msm_phy *ufs_msm_phy) { { struct ufs_msm_phy_calibration *tbl; struct ufs_msm_phy_calibration *tbl_A, *tbl_B; int tbl_size; int tbl_size_A, tbl_size_B; int i; int rate = UFS_MSM_LIMIT_HS_RATE; u8 major = ufs_msm_phy->host_ctrl_rev_major; u8 major = ufs_msm_phy->host_ctrl_rev_major; u16 minor = ufs_msm_phy->host_ctrl_rev_minor; u16 minor = ufs_msm_phy->host_ctrl_rev_minor; u16 step = ufs_msm_phy->host_ctrl_rev_step; u16 step = ufs_msm_phy->host_ctrl_rev_step; int err; if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) { if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) { tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A); tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A); tbl = phy_cal_table_ctrl_1_1_0_rate_A; tbl_A = phy_cal_table_ctrl_1_1_0_rate_A; } else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { } else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A); tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A); tbl = phy_cal_table_ctrl_1_1_1_rate_A; tbl_A = phy_cal_table_ctrl_1_1_1_rate_A; } } /* tbl_B = phy_cal_table_rate_B; * calibration according phy_cal_table_ctrl_x_x_x_rate_A tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); * happens regardless of the rate we intend to work with. * Only in case we would like to work in rate B, we need * to override a subset of registers of * phy_cal_table_ctrl_x_x_x_rate_A table, with phy_cal_table_rate_B * table. */ for (i = 0; i < tbl_size; i++) writel_relaxed(tbl[i].cfg_value, ufs_msm_phy->mmio + tbl[i].reg_offset); if (UFS_MSM_LIMIT_HS_RATE == PA_HS_MODE_B) { tbl = phy_cal_table_rate_B; tbl_size = ARRAY_SIZE(phy_cal_table_rate_B); for (i = 0; i < tbl_size; i++) err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A, writel_relaxed(tbl[i].cfg_value, tbl_B, tbl_size_B, rate); ufs_msm_phy->mmio + tbl[i].reg_offset); if (err) } dev_err(ufs_msm_phy->dev, "%s: ufs_msm_phy_calibrate() failed %d\n", __func__, err); /* flush buffered writes */ return err; mb(); } } static static Loading Loading @@ -286,7 +274,7 @@ static int ufs_msm_phy_qmp_28nm_resume(struct phy *generic_phy) return err; return err; } } struct phy_ops ufs_msm_phy_ops = { struct phy_ops ufs_msm_phy_qmp_28nm_phy_ops = { .init = ufs_msm_phy_qmp_28nm_init, .init = ufs_msm_phy_qmp_28nm_init, .exit = ufs_msm_phy_exit, .exit = ufs_msm_phy_exit, .power_on = ufs_msm_phy_power_on, .power_on = ufs_msm_phy_power_on, Loading @@ -312,7 +300,6 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device *dev = &pdev->dev; int err = 0; int err = 0; struct phy *generic_phy; struct phy *generic_phy; struct phy_provider *phy_provider; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); if (!phy) { if (!phy) { Loading @@ -321,37 +308,26 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev) goto out; goto out; } } err = ufs_msm_phy_base_init(pdev, &phy->common_cfg); if (err) { dev_err(dev, "%s: phy base init failed %d\n", __func__, err); goto out; } phy->common_cfg.phy_spec_ops = &phy_28nm_ops; phy->common_cfg.cached_regs = phy->common_cfg.cached_regs = (struct ufs_msm_phy_calibration *)cached_phy_regs; (struct ufs_msm_phy_calibration *)cached_phy_regs; phy->common_cfg.cached_regs_table_size = phy->common_cfg.cached_regs_table_size = ARRAY_SIZE(cached_phy_regs); ARRAY_SIZE(cached_phy_regs); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg, if (IS_ERR(phy_provider)) { &ufs_msm_phy_qmp_28nm_phy_ops, &phy_28nm_ops); err = PTR_ERR(phy_provider); dev_err(dev, "%s: failed to register phy %d\n", __func__, err); goto out; } generic_phy = devm_phy_create(dev, &ufs_msm_phy_ops, NULL); if (!generic_phy) { if (IS_ERR(generic_phy)) { dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n", err = PTR_ERR(generic_phy); __func__); dev_err(dev, "%s: failed to create phy %d\n", __func__, err); err = -EIO; goto out; goto out; } } phy->common_cfg.dev = dev; phy_set_drvdata(generic_phy, phy); phy_set_drvdata(generic_phy, phy); strlcpy(phy->common_cfg.name, UFS_PHY_NAME, strlcpy(phy->common_cfg.name, UFS_PHY_NAME, sizeof(phy->common_cfg.name)); sizeof(phy->common_cfg.name)); out: out: return err; return err; } } Loading
drivers/scsi/ufs/ufs-msm-phy.c +85 −2 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,87 @@ #include "ufs-msm.h" #include "ufs-msm.h" #include "ufs-msm-phy.h" #include "ufs-msm-phy.h" int ufs_msm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy, struct ufs_msm_phy_calibration *tbl_A, int tbl_size_A, struct ufs_msm_phy_calibration *tbl_B, int tbl_size_B, int rate) { int i; int ret = 0; if (!tbl_A) { dev_err(ufs_msm_phy->dev, "%s: tbl_A is NULL", __func__); ret = EINVAL; goto out; } for (i = 0; i < tbl_size_A; i++) writel_relaxed(tbl_A[i].cfg_value, ufs_msm_phy->mmio + tbl_A[i].reg_offset); /* * In case we would like to work in rate B, we need * to override a registers that were configured in rate A table * with registers of rate B table. * table. */ if (rate == PA_HS_MODE_B) { if (!tbl_B) { dev_err(ufs_msm_phy->dev, "%s: tbl_B is NULL", __func__); ret = EINVAL; goto out; } for (i = 0; i < tbl_size_B; i++) writel_relaxed(tbl_B[i].cfg_value, ufs_msm_phy->mmio + tbl_B[i].reg_offset); } /* flush buffered writes */ mb(); out: return ret; } struct phy *ufs_msm_phy_generic_probe(struct platform_device *pdev, struct ufs_msm_phy *common_cfg, struct phy_ops *ufs_msm_phy_gen_ops, struct ufs_msm_phy_specific_ops *phy_spec_ops) { int err; struct device *dev = &pdev->dev; struct phy *generic_phy = NULL; struct phy_provider *phy_provider; err = ufs_msm_phy_base_init(pdev, common_cfg); if (err) { dev_err(dev, "%s: phy base init failed %d\n", __func__, err); goto out; } phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (IS_ERR(phy_provider)) { err = PTR_ERR(phy_provider); dev_err(dev, "%s: failed to register phy %d\n", __func__, err); goto out; } generic_phy = devm_phy_create(dev, ufs_msm_phy_gen_ops, NULL); if (IS_ERR(generic_phy)) { err = PTR_ERR(generic_phy); dev_err(dev, "%s: failed to create phy %d\n", __func__, err); goto out; } common_cfg->phy_spec_ops = phy_spec_ops; common_cfg->dev = dev; out: return generic_phy; } /* /* * This assumes the embedded phy structure inside generic_phy is of type * This assumes the embedded phy structure inside generic_phy is of type * struct ufs_msm_phy. In order to function properly it's crucial * struct ufs_msm_phy. In order to function properly it's crucial Loading Loading @@ -447,8 +528,10 @@ int ufs_msm_phy_calibrate_phy(struct phy *generic_phy) __func__); __func__); ret = -ENOTSUPP; ret = -ENOTSUPP; } else { } else { ufs_msm_phy->phy_spec_ops-> ret = ufs_msm_phy->phy_spec_ops-> calibrate_phy(ufs_msm_phy); calibrate_phy(ufs_msm_phy); dev_err(ufs_msm_phy->dev, "%s: calibrate_phy() failed %d\n", __func__, ret); } } return ret; return ret; Loading
drivers/scsi/ufs/ufs-msm-phy.h +9 −1 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,7 @@ struct ufs_msm_phy { * and writes to QSERDES_RX_SIGDET_CNTRL attribute * and writes to QSERDES_RX_SIGDET_CNTRL attribute */ */ struct ufs_msm_phy_specific_ops { struct ufs_msm_phy_specific_ops { void (*calibrate_phy) (struct ufs_msm_phy *phy); int (*calibrate_phy) (struct ufs_msm_phy *phy); void (*start_serdes) (struct ufs_msm_phy *phy); void (*start_serdes) (struct ufs_msm_phy *phy); void (*save_configuration)(struct ufs_msm_phy *phy); void (*save_configuration)(struct ufs_msm_phy *phy); int (*is_physical_coding_sublayer_ready) (struct ufs_msm_phy *phy); int (*is_physical_coding_sublayer_ready) (struct ufs_msm_phy *phy); Loading Loading @@ -173,4 +173,12 @@ int ufs_msm_phy_init_vregulators(struct phy *generic_phy, struct ufs_msm_phy *phy_common); struct ufs_msm_phy *phy_common); int ufs_msm_phy_remove(struct phy *generic_phy, int ufs_msm_phy_remove(struct phy *generic_phy, struct ufs_msm_phy *ufs_msm_phy); struct ufs_msm_phy *ufs_msm_phy); struct phy *ufs_msm_phy_generic_probe(struct platform_device *pdev, struct ufs_msm_phy *common_cfg, struct phy_ops *ufs_msm_phy_gen_ops, struct ufs_msm_phy_specific_ops *phy_spec_ops); int ufs_msm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy, struct ufs_msm_phy_calibration *tbl_A, int tbl_size_A, struct ufs_msm_phy_calibration *tbl_B, int tbl_size_B, int rate); #endif #endif