Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This update includes the usual round of major driver updates (ncr5380, lpfc, hisi_sas, megaraid_sas, ufs, ibmvscsis, mpt3sas). There's also an assortment of minor fixes, mostly in error legs or other not very user visible stuff. The major change is the pci_alloc_irq_vectors replacement for the old pci_msix_.. calls; this effectively makes IRQ mapping generic for the drivers and allows blk_mq to use the information" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (256 commits) scsi: qla4xxx: switch to pci_alloc_irq_vectors scsi: hisi_sas: support deferred probe for v2 hw scsi: megaraid_sas: switch to pci_alloc_irq_vectors scsi: scsi_devinfo: remove synchronous ALUA for NETAPP devices scsi: be2iscsi: set errno on error path scsi: be2iscsi: set errno on error path scsi: hpsa: fallback to use legacy REPORT PHYS command scsi: scsi_dh_alua: Fix RCU annotations scsi: hpsa: use %phN for short hex dumps scsi: hisi_sas: fix free'ing in probe and remove scsi: isci: switch to pci_alloc_irq_vectors scsi: ipr: Fix runaway IRQs when falling back from MSI to LSI scsi: dpt_i2o: double free on error path scsi: cxlflash: Migrate scsi command pointer to AFU command scsi: cxlflash: Migrate IOARRIN specific routines to function pointers scsi: cxlflash: Cleanup queuecommand() scsi: cxlflash: Cleanup send_tmf() scsi: cxlflash: Remove AFU command lock scsi: cxlflash: Wait for active AFU commands to timeout upon tear down scsi: cxlflash: Remove private command pool ...
This commit is contained in:
@@ -141,11 +141,8 @@ struct ufs_qcom_phy_specific_ops {
|
||||
struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy);
|
||||
int ufs_qcom_phy_power_on(struct phy *generic_phy);
|
||||
int ufs_qcom_phy_power_off(struct phy *generic_phy);
|
||||
int ufs_qcom_phy_exit(struct phy *generic_phy);
|
||||
int ufs_qcom_phy_init_clks(struct phy *generic_phy,
|
||||
struct ufs_qcom_phy *phy_common);
|
||||
int ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
|
||||
struct ufs_qcom_phy *phy_common);
|
||||
int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common);
|
||||
int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common);
|
||||
int ufs_qcom_phy_remove(struct phy *generic_phy,
|
||||
struct ufs_qcom_phy *ufs_qcom_phy);
|
||||
struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
|
||||
|
@@ -44,30 +44,12 @@ void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
|
||||
|
||||
static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
|
||||
{
|
||||
struct ufs_qcom_phy_qmp_14nm *phy = phy_get_drvdata(generic_phy);
|
||||
struct ufs_qcom_phy *phy_common = &phy->common_cfg;
|
||||
int err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_clks(generic_phy, phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV;
|
||||
phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV;
|
||||
|
||||
ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common);
|
||||
|
||||
out:
|
||||
return err;
|
||||
static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -117,7 +99,7 @@ static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
|
||||
|
||||
static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
|
||||
.init = ufs_qcom_phy_qmp_14nm_init,
|
||||
.exit = ufs_qcom_phy_exit,
|
||||
.exit = ufs_qcom_phy_qmp_14nm_exit,
|
||||
.power_on = ufs_qcom_phy_power_on,
|
||||
.power_off = ufs_qcom_phy_power_off,
|
||||
.owner = THIS_MODULE,
|
||||
@@ -136,6 +118,7 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct phy *generic_phy;
|
||||
struct ufs_qcom_phy_qmp_14nm *phy;
|
||||
struct ufs_qcom_phy *phy_common;
|
||||
int err = 0;
|
||||
|
||||
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||
@@ -143,8 +126,9 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
phy_common = &phy->common_cfg;
|
||||
|
||||
generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg,
|
||||
generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common,
|
||||
&ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops);
|
||||
|
||||
if (!generic_phy) {
|
||||
@@ -154,39 +138,43 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_clks(phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev,
|
||||
"%s: ufs_qcom_phy_init_clks() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_vregulators(phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev,
|
||||
"%s: ufs_qcom_phy_init_vregulators() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV;
|
||||
phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV;
|
||||
|
||||
ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common);
|
||||
|
||||
phy_set_drvdata(generic_phy, phy);
|
||||
|
||||
strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
|
||||
sizeof(phy->common_cfg.name));
|
||||
strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name));
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct phy *generic_phy = to_phy(dev);
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
|
||||
int err = 0;
|
||||
|
||||
err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy);
|
||||
if (err)
|
||||
dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n",
|
||||
__func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = {
|
||||
{.compatible = "qcom,ufs-phy-qmp-14nm"},
|
||||
{.compatible = "qcom,msm8996-ufs-phy-qmp-14nm"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match);
|
||||
|
||||
static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = {
|
||||
.probe = ufs_qcom_phy_qmp_14nm_probe,
|
||||
.remove = ufs_qcom_phy_qmp_14nm_remove,
|
||||
.driver = {
|
||||
.of_match_table = ufs_qcom_phy_qmp_14nm_of_match,
|
||||
.name = "ufs_qcom_phy_qmp_14nm",
|
||||
|
@@ -63,28 +63,12 @@ void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
|
||||
|
||||
static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy)
|
||||
{
|
||||
struct ufs_qcom_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy);
|
||||
struct ufs_qcom_phy *phy_common = &phy->common_cfg;
|
||||
int err = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_clks(generic_phy, phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common);
|
||||
|
||||
out:
|
||||
return err;
|
||||
static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -173,7 +157,7 @@ static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
|
||||
|
||||
static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
|
||||
.init = ufs_qcom_phy_qmp_20nm_init,
|
||||
.exit = ufs_qcom_phy_exit,
|
||||
.exit = ufs_qcom_phy_qmp_20nm_exit,
|
||||
.power_on = ufs_qcom_phy_power_on,
|
||||
.power_off = ufs_qcom_phy_power_off,
|
||||
.owner = THIS_MODULE,
|
||||
@@ -192,6 +176,7 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct phy *generic_phy;
|
||||
struct ufs_qcom_phy_qmp_20nm *phy;
|
||||
struct ufs_qcom_phy *phy_common;
|
||||
int err = 0;
|
||||
|
||||
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||
@@ -199,8 +184,9 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
phy_common = &phy->common_cfg;
|
||||
|
||||
generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg,
|
||||
generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common,
|
||||
&ufs_qcom_phy_qmp_20nm_phy_ops, &phy_20nm_ops);
|
||||
|
||||
if (!generic_phy) {
|
||||
@@ -210,30 +196,30 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_clks(phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_init_vregulators(phy_common);
|
||||
if (err) {
|
||||
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common);
|
||||
|
||||
phy_set_drvdata(generic_phy, phy);
|
||||
|
||||
strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
|
||||
sizeof(phy->common_cfg.name));
|
||||
strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name));
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufs_qcom_phy_qmp_20nm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct phy *generic_phy = to_phy(dev);
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
|
||||
int err = 0;
|
||||
|
||||
err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy);
|
||||
if (err)
|
||||
dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n",
|
||||
__func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = {
|
||||
{.compatible = "qcom,ufs-phy-qmp-20nm"},
|
||||
{},
|
||||
@@ -242,7 +228,6 @@ MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match);
|
||||
|
||||
static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = {
|
||||
.probe = ufs_qcom_phy_qmp_20nm_probe,
|
||||
.remove = ufs_qcom_phy_qmp_20nm_remove,
|
||||
.driver = {
|
||||
.of_match_table = ufs_qcom_phy_qmp_20nm_of_match,
|
||||
.name = "ufs_qcom_phy_qmp_20nm",
|
||||
|
@@ -22,13 +22,6 @@
|
||||
#define VDDP_REF_CLK_MIN_UV 1200000
|
||||
#define VDDP_REF_CLK_MAX_UV 1200000
|
||||
|
||||
static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *,
|
||||
const char *, bool);
|
||||
static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *,
|
||||
const char *);
|
||||
static int ufs_qcom_phy_base_init(struct platform_device *pdev,
|
||||
struct ufs_qcom_phy *phy_common);
|
||||
|
||||
int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
|
||||
struct ufs_qcom_phy_calibration *tbl_A,
|
||||
int tbl_size_A,
|
||||
@@ -75,45 +68,6 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
|
||||
|
||||
struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
|
||||
struct ufs_qcom_phy *common_cfg,
|
||||
const struct phy_ops *ufs_qcom_phy_gen_ops,
|
||||
struct ufs_qcom_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_qcom_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, NULL, ufs_qcom_phy_gen_ops);
|
||||
if (IS_ERR(generic_phy)) {
|
||||
err = PTR_ERR(generic_phy);
|
||||
dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
|
||||
generic_phy = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
common_cfg->phy_spec_ops = phy_spec_ops;
|
||||
common_cfg->dev = dev;
|
||||
|
||||
out:
|
||||
return generic_phy;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
|
||||
|
||||
/*
|
||||
* This assumes the embedded phy structure inside generic_phy is of type
|
||||
* struct ufs_qcom_phy. In order to function properly it's crucial
|
||||
@@ -154,13 +108,50 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __ufs_qcom_phy_clk_get(struct phy *phy,
|
||||
struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
|
||||
struct ufs_qcom_phy *common_cfg,
|
||||
const struct phy_ops *ufs_qcom_phy_gen_ops,
|
||||
struct ufs_qcom_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_qcom_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, NULL, ufs_qcom_phy_gen_ops);
|
||||
if (IS_ERR(generic_phy)) {
|
||||
err = PTR_ERR(generic_phy);
|
||||
dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
|
||||
generic_phy = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
common_cfg->phy_spec_ops = phy_spec_ops;
|
||||
common_cfg->dev = dev;
|
||||
|
||||
out:
|
||||
return generic_phy;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
|
||||
|
||||
static int __ufs_qcom_phy_clk_get(struct device *dev,
|
||||
const char *name, struct clk **clk_out, bool err_print)
|
||||
{
|
||||
struct clk *clk;
|
||||
int err = 0;
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
|
||||
struct device *dev = ufs_qcom_phy->dev;
|
||||
|
||||
clk = devm_clk_get(dev, name);
|
||||
if (IS_ERR(clk)) {
|
||||
@@ -174,42 +165,44 @@ static int __ufs_qcom_phy_clk_get(struct phy *phy,
|
||||
return err;
|
||||
}
|
||||
|
||||
static
|
||||
int ufs_qcom_phy_clk_get(struct phy *phy,
|
||||
static int ufs_qcom_phy_clk_get(struct device *dev,
|
||||
const char *name, struct clk **clk_out)
|
||||
{
|
||||
return __ufs_qcom_phy_clk_get(phy, name, clk_out, true);
|
||||
return __ufs_qcom_phy_clk_get(dev, name, clk_out, true);
|
||||
}
|
||||
|
||||
int
|
||||
ufs_qcom_phy_init_clks(struct phy *generic_phy,
|
||||
struct ufs_qcom_phy *phy_common)
|
||||
int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ufs_qcom_phy_clk_get(generic_phy, "tx_iface_clk",
|
||||
if (of_device_is_compatible(phy_common->dev->of_node,
|
||||
"qcom,msm8996-ufs-phy-qmp-14nm"))
|
||||
goto skip_txrx_clk;
|
||||
|
||||
err = ufs_qcom_phy_clk_get(phy_common->dev, "tx_iface_clk",
|
||||
&phy_common->tx_iface_clk);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ufs_qcom_phy_clk_get(generic_phy, "rx_iface_clk",
|
||||
err = ufs_qcom_phy_clk_get(phy_common->dev, "rx_iface_clk",
|
||||
&phy_common->rx_iface_clk);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk_src",
|
||||
err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_src",
|
||||
&phy_common->ref_clk_src);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
skip_txrx_clk:
|
||||
/*
|
||||
* "ref_clk_parent" is optional hence don't abort init if it's not
|
||||
* found.
|
||||
*/
|
||||
__ufs_qcom_phy_clk_get(generic_phy, "ref_clk_parent",
|
||||
__ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_parent",
|
||||
&phy_common->ref_clk_parent, false);
|
||||
|
||||
err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk",
|
||||
err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk",
|
||||
&phy_common->ref_clk);
|
||||
|
||||
out:
|
||||
@@ -217,41 +210,14 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
|
||||
|
||||
int
|
||||
ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
|
||||
struct ufs_qcom_phy *phy_common)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_pll,
|
||||
"vdda-pll");
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_phy,
|
||||
"vdda-phy");
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/* vddp-ref-clk-* properties are optional */
|
||||
__ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vddp_ref_clk,
|
||||
"vddp-ref-clk", true);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
|
||||
|
||||
static int __ufs_qcom_phy_init_vreg(struct phy *phy,
|
||||
static int __ufs_qcom_phy_init_vreg(struct device *dev,
|
||||
struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional)
|
||||
{
|
||||
int err = 0;
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
|
||||
struct device *dev = ufs_qcom_phy->dev;
|
||||
|
||||
char prop_name[MAX_PROP_NAME];
|
||||
|
||||
vreg->name = kstrdup(name, GFP_KERNEL);
|
||||
vreg->name = devm_kstrdup(dev, name, GFP_KERNEL);
|
||||
if (!vreg->name) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
@@ -304,14 +270,36 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufs_qcom_phy_init_vreg(struct phy *phy,
|
||||
static int ufs_qcom_phy_init_vreg(struct device *dev,
|
||||
struct ufs_qcom_phy_vreg *vreg, const char *name)
|
||||
{
|
||||
return __ufs_qcom_phy_init_vreg(phy, vreg, name, false);
|
||||
return __ufs_qcom_phy_init_vreg(dev, vreg, name, false);
|
||||
}
|
||||
|
||||
static
|
||||
int ufs_qcom_phy_cfg_vreg(struct phy *phy,
|
||||
int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_pll,
|
||||
"vdda-pll");
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_phy,
|
||||
"vdda-phy");
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/* vddp-ref-clk-* properties are optional */
|
||||
__ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk,
|
||||
"vddp-ref-clk", true);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
|
||||
|
||||
static int ufs_qcom_phy_cfg_vreg(struct device *dev,
|
||||
struct ufs_qcom_phy_vreg *vreg, bool on)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -319,10 +307,6 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy,
|
||||
const char *name = vreg->name;
|
||||
int min_uV;
|
||||
int uA_load;
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
|
||||
struct device *dev = ufs_qcom_phy->dev;
|
||||
|
||||
BUG_ON(!vreg);
|
||||
|
||||
if (regulator_count_voltages(reg) > 0) {
|
||||
min_uV = on ? vreg->min_uV : 0;
|
||||
@@ -350,18 +334,15 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ufs_qcom_phy_enable_vreg(struct phy *phy,
|
||||
static int ufs_qcom_phy_enable_vreg(struct device *dev,
|
||||
struct ufs_qcom_phy_vreg *vreg)
|
||||
{
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
|
||||
struct device *dev = ufs_qcom_phy->dev;
|
||||
int ret = 0;
|
||||
|
||||
if (!vreg || vreg->enabled)
|
||||
goto out;
|
||||
|
||||
ret = ufs_qcom_phy_cfg_vreg(phy, vreg, true);
|
||||
ret = ufs_qcom_phy_cfg_vreg(dev, vreg, true);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: ufs_qcom_phy_cfg_vreg() failed, err=%d\n",
|
||||
__func__, ret);
|
||||
@@ -380,10 +361,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ufs_qcom_phy_enable_ref_clk(struct phy *generic_phy)
|
||||
static int ufs_qcom_phy_enable_ref_clk(struct ufs_qcom_phy *phy)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);
|
||||
|
||||
if (phy->is_ref_clk_enabled)
|
||||
goto out;
|
||||
@@ -430,14 +410,10 @@ out_disable_src:
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk);
|
||||
|
||||
static
|
||||
int ufs_qcom_phy_disable_vreg(struct phy *phy,
|
||||
static int ufs_qcom_phy_disable_vreg(struct device *dev,
|
||||
struct ufs_qcom_phy_vreg *vreg)
|
||||
{
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
|
||||
struct device *dev = ufs_qcom_phy->dev;
|
||||
int ret = 0;
|
||||
|
||||
if (!vreg || !vreg->enabled || vreg->is_always_on)
|
||||
@@ -447,7 +423,7 @@ int ufs_qcom_phy_disable_vreg(struct phy *phy,
|
||||
|
||||
if (!ret) {
|
||||
/* ignore errors on applying disable config */
|
||||
ufs_qcom_phy_cfg_vreg(phy, vreg, false);
|
||||
ufs_qcom_phy_cfg_vreg(dev, vreg, false);
|
||||
vreg->enabled = false;
|
||||
} else {
|
||||
dev_err(dev, "%s: %s disable failed, err=%d\n",
|
||||
@@ -457,10 +433,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy)
|
||||
static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy)
|
||||
{
|
||||
struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);
|
||||
|
||||
if (phy->is_ref_clk_enabled) {
|
||||
clk_disable_unprepare(phy->ref_clk);
|
||||
/*
|
||||
@@ -473,7 +447,6 @@ void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy)
|
||||
phy->is_ref_clk_enabled = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk);
|
||||
|
||||
#define UFS_REF_CLK_EN (1 << 5)
|
||||
|
||||
@@ -526,9 +499,8 @@ void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk);
|
||||
|
||||
/* Turn ON M-PHY RMMI interface clocks */
|
||||
int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy)
|
||||
static int ufs_qcom_phy_enable_iface_clk(struct ufs_qcom_phy *phy)
|
||||
{
|
||||
struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);
|
||||
int ret = 0;
|
||||
|
||||
if (phy->is_iface_clk_enabled)
|
||||
@@ -552,20 +524,16 @@ int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy)
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk);
|
||||
|
||||
/* Turn OFF M-PHY RMMI interface clocks */
|
||||
void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy)
|
||||
void ufs_qcom_phy_disable_iface_clk(struct ufs_qcom_phy *phy)
|
||||
{
|
||||
struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);
|
||||
|
||||
if (phy->is_iface_clk_enabled) {
|
||||
clk_disable_unprepare(phy->tx_iface_clk);
|
||||
clk_disable_unprepare(phy->rx_iface_clk);
|
||||
phy->is_iface_clk_enabled = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk);
|
||||
|
||||
int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
|
||||
{
|
||||
@@ -634,29 +602,6 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
|
||||
|
||||
int ufs_qcom_phy_remove(struct phy *generic_phy,
|
||||
struct ufs_qcom_phy *ufs_qcom_phy)
|
||||
{
|
||||
phy_power_off(generic_phy);
|
||||
|
||||
kfree(ufs_qcom_phy->vdda_pll.name);
|
||||
kfree(ufs_qcom_phy->vdda_phy.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove);
|
||||
|
||||
int ufs_qcom_phy_exit(struct phy *generic_phy)
|
||||
{
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
|
||||
|
||||
if (ufs_qcom_phy->is_powered_on)
|
||||
phy_power_off(generic_phy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit);
|
||||
|
||||
int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
|
||||
{
|
||||
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
|
||||
@@ -678,7 +623,10 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
|
||||
struct device *dev = phy_common->dev;
|
||||
int err;
|
||||
|
||||
err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_phy);
|
||||
if (phy_common->is_powered_on)
|
||||
return 0;
|
||||
|
||||
err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
|
||||
if (err) {
|
||||
dev_err(dev, "%s enable vdda_phy failed, err=%d\n",
|
||||
__func__, err);
|
||||
@@ -688,23 +636,30 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
|
||||
phy_common->phy_spec_ops->power_control(phy_common, true);
|
||||
|
||||
/* vdda_pll also enables ref clock LDOs so enable it first */
|
||||
err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_pll);
|
||||
err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_pll);
|
||||
if (err) {
|
||||
dev_err(dev, "%s enable vdda_pll failed, err=%d\n",
|
||||
__func__, err);
|
||||
goto out_disable_phy;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_enable_ref_clk(generic_phy);
|
||||
err = ufs_qcom_phy_enable_iface_clk(phy_common);
|
||||
if (err) {
|
||||
dev_err(dev, "%s enable phy ref clock failed, err=%d\n",
|
||||
dev_err(dev, "%s enable phy iface clock failed, err=%d\n",
|
||||
__func__, err);
|
||||
goto out_disable_pll;
|
||||
}
|
||||
|
||||
err = ufs_qcom_phy_enable_ref_clk(phy_common);
|
||||
if (err) {
|
||||
dev_err(dev, "%s enable phy ref clock failed, err=%d\n",
|
||||
__func__, err);
|
||||
goto out_disable_iface_clk;
|
||||
}
|
||||
|
||||
/* enable device PHY ref_clk pad rail */
|
||||
if (phy_common->vddp_ref_clk.reg) {
|
||||
err = ufs_qcom_phy_enable_vreg(generic_phy,
|
||||
err = ufs_qcom_phy_enable_vreg(dev,
|
||||
&phy_common->vddp_ref_clk);
|
||||
if (err) {
|
||||
dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n",
|
||||
@@ -717,11 +672,13 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
|
||||
goto out;
|
||||
|
||||
out_disable_ref_clk:
|
||||
ufs_qcom_phy_disable_ref_clk(generic_phy);
|
||||
ufs_qcom_phy_disable_ref_clk(phy_common);
|
||||
out_disable_iface_clk:
|
||||
ufs_qcom_phy_disable_iface_clk(phy_common);
|
||||
out_disable_pll:
|
||||
ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll);
|
||||
ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_pll);
|
||||
out_disable_phy:
|
||||
ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy);
|
||||
ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_phy);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@@ -731,15 +688,19 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
|
||||
{
|
||||
struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
|
||||
|
||||
if (!phy_common->is_powered_on)
|
||||
return 0;
|
||||
|
||||
phy_common->phy_spec_ops->power_control(phy_common, false);
|
||||
|
||||
if (phy_common->vddp_ref_clk.reg)
|
||||
ufs_qcom_phy_disable_vreg(generic_phy,
|
||||
ufs_qcom_phy_disable_vreg(phy_common->dev,
|
||||
&phy_common->vddp_ref_clk);
|
||||
ufs_qcom_phy_disable_ref_clk(generic_phy);
|
||||
ufs_qcom_phy_disable_ref_clk(phy_common);
|
||||
ufs_qcom_phy_disable_iface_clk(phy_common);
|
||||
|
||||
ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll);
|
||||
ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy);
|
||||
ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll);
|
||||
ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy);
|
||||
phy_common->is_powered_on = false;
|
||||
|
||||
return 0;
|
||||
|
Fai riferimento in un nuovo problema
Block a user