Re: [PATCH v7 2/5] phy: qcom-ufs: add support for 20nm phy

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick 

> This change adds a support for a 20nm qcom-ufs phy that is required in
> platforms that use ufs-qcom controller.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/phy/Makefile|   1 +
>  drivers/phy/phy-qcom-ufs-i.h|  43 +-
>  drivers/phy/phy-qcom-ufs-qmp-20nm.c | 257
> 
>  drivers/phy/phy-qcom-ufs-qmp-20nm.h | 235
> +
>  include/linux/phy/phy-qcom-ufs.h|  59 +
>  5 files changed, 594 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.c
>  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.h
>  create mode 100644 include/linux/phy/phy-qcom-ufs.h
>
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 335965d..781b2fa 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -35,3 +35,4 @@ obj-$(CONFIG_PHY_XGENE) +=
> phy-xgene.o
>  obj-$(CONFIG_PHY_STIH407_USB)+= phy-stih407-usb.o
>  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
>  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
> +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-20nm.o
> diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
> index dac200f..591a391 100644
> --- a/drivers/phy/phy-qcom-ufs-i.h
> +++ b/drivers/phy/phy-qcom-ufs-i.h
> @@ -15,15 +15,56 @@
>  #ifndef UFS_QCOM_PHY_I_H_
>  #define UFS_QCOM_PHY_I_H_
>
> +#include 
>  #include 
> +#include 
>  #include 
> -#include 
> +#include 
>  #include 
>  #include 
>  #include 
>
> +#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
> +({ \
> + ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
> + might_sleep_if(timeout_us); \
> + for (;;) { \
> + (val) = readl(addr); \
> + if (cond) \
> + break; \
> + if (timeout_us && ktime_compare(ktime_get(), timeout) > 0)
> { \
> + (val) = readl(addr); \
> + break; \
> + } \
> + if (sleep_us) \
> + usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us);
> \
> + } \
> + (cond) ? 0 : -ETIMEDOUT; \
> +})
> +
> +#define UFS_QCOM_PHY_CAL_ENTRY(reg, val) \
> + {   \
> + .reg_offset = reg,  \
> + .cfg_value = val,   \
> + }
> +
>  #define UFS_QCOM_PHY_NAME_LEN30
>
> +enum {
> + MASK_SERDES_START   = 0x1,
> + MASK_PCS_READY  = 0x1,
> +};
> +
> +enum {
> + OFFSET_SERDES_START = 0x0,
> +};
> +
> +struct ufs_qcom_phy_stored_attributes {
> + u32 att;
> + u32 value;
> +};
> +
> +
>  struct ufs_qcom_phy_calibration {
>   u32 reg_offset;
>   u32 cfg_value;
> diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c
> b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
> new file mode 100644
> index 000..8332f96
> --- /dev/null
> +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
> @@ -0,0 +1,257 @@
> +/*
> + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include "phy-qcom-ufs-qmp-20nm.h"
> +
> +#define UFS_PHY_NAME "ufs_phy_qmp_20nm"
> +
> +static
> +int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy
> *ufs_qcom_phy,
> + bool is_rate_B)
> +{
> + struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
> + int tbl_size_A, tbl_size_B;
> + u8 major = ufs_qcom_phy->host_ctrl_rev_major;
> + u16 minor = ufs_qcom_phy->host_ctrl_rev_minor;
> + u16 step = ufs_qcom_phy->host_ctrl_rev_step;
> + int err;
> +
> + if ((major == 0x1) && (minor == 0x002) && (step == 0x)) {
> + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0);
> + tbl_A = phy_cal_table_rate_A_1_2_0;
> + } else if ((major == 0x1) && (minor == 0x003) && (step == 0x))
> {
> + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0);
> + tbl_A = phy_cal_table_rate_A_1_3_0;
> + } else {
> + dev_err(ufs_qcom_phy->dev, "%s: Unknown UFS-PHY version,
> no calibration values\n",
> + __func__);
> + err = -ENODEV;
> + goto out;
> + }
> +
> + tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
> + tbl_B = phy_cal_table_rate_B;
> +
> + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
> + tbl_B, tbl_size_B,
> is_rate_B);
> +
> + 

Re: [PATCH v7 4/5] phy: qcom-ufs: add support for 14nm phy

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick 

> This change adds a support for a 14nm qcom-ufs phy that is
> required in platforms that use ufs-qcom controller.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/phy/Makefile|   1 +
>  drivers/phy/phy-qcom-ufs-qmp-14nm.c | 201
> 
>  drivers/phy/phy-qcom-ufs-qmp-14nm.h | 177 +++
>  3 files changed, 379 insertions(+)
>  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-14nm.c
>  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-14nm.h
>
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 781b2fa..cfbb720 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -36,3 +36,4 @@ obj-$(CONFIG_PHY_STIH407_USB)   +=
> phy-stih407-usb.o
>  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
>  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
>  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-20nm.o
> +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-14nm.o
> diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c
> b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
> new file mode 100644
> index 000..f5fc50a
> --- /dev/null
> +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
> @@ -0,0 +1,201 @@
> +/*
> + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include "phy-qcom-ufs-qmp-14nm.h"
> +
> +#define UFS_PHY_NAME "ufs_phy_qmp_14nm"
> +#define UFS_PHY_VDDA_PHY_UV  (925000)
> +
> +static
> +int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy
> *ufs_qcom_phy,
> + bool is_rate_B)
> +{
> + int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
> + int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
> + int err;
> +
> + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A,
> + tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B);
> +
> + if (err)
> + dev_err(ufs_qcom_phy->dev,
> + "%s: ufs_qcom_phy_calibrate() failed %d\n",
> + __func__, err);
> + return err;
> +}
> +
> +static
> +void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy
> *phy_common)
> +{
> + phy_common->quirks =
> + UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
> +}
> +
> +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 = >common_cfg;
> + int err;
> +
> + 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
> +void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool
> val)
> +{
> + writel_relaxed(val ? 0x1 : 0x0, phy->mmio +
> UFS_PHY_POWER_DOWN_CONTROL);
> + /*
> +  * Before any transactions involving PHY, ensure PHY knows
> +  * that it's analog rail is powered ON (or OFF).
> +  */
> + mb();
> +}
> +
> +static inline
> +void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy,
> u32 val)
> +{
> + /*
> +  * 14nm PHY does not have TX_LANE_ENABLE register.
> +  * Implement this function so as not to propagate error to caller.
> +  */
> +}
> +
> +static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy
> *phy)
> +{
> + u32 tmp;
> +
> + tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START);
> + tmp &= ~MASK_SERDES_START;
> + tmp |= (1 << OFFSET_SERDES_START);
> + writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START);
> + /* Ensure register value is committed */
> + mb();
> +}
> +
> +static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy
> *phy_common)
> +{
> + int err = 0;
> + u32 val;
> +
> + err = readl_poll_timeout(phy_common->mmio +
> UFS_PHY_PCS_READY_STATUS,
> + val, (val & 

Re: [PATCH v7 2/5] phy: qcom-ufs: add support for 20nm phy

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick 

> This change adds a support for a 20nm qcom-ufs phy that is required in
> platforms that use ufs-qcom controller.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/phy/Makefile|   1 +
>  drivers/phy/phy-qcom-ufs-i.h|  43 +-
>  drivers/phy/phy-qcom-ufs-qmp-20nm.c | 257
> 
>  drivers/phy/phy-qcom-ufs-qmp-20nm.h | 235
> +
>  include/linux/phy/phy-qcom-ufs.h|  59 +
>  5 files changed, 594 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.c
>  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.h
>  create mode 100644 include/linux/phy/phy-qcom-ufs.h
>
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 335965d..781b2fa 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -35,3 +35,4 @@ obj-$(CONFIG_PHY_XGENE) +=
> phy-xgene.o
>  obj-$(CONFIG_PHY_STIH407_USB)+= phy-stih407-usb.o
>  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
>  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
> +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-20nm.o
> diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
> index dac200f..591a391 100644
> --- a/drivers/phy/phy-qcom-ufs-i.h
> +++ b/drivers/phy/phy-qcom-ufs-i.h
> @@ -15,15 +15,56 @@
>  #ifndef UFS_QCOM_PHY_I_H_
>  #define UFS_QCOM_PHY_I_H_
>
> +#include 
>  #include 
> +#include 
>  #include 
> -#include 
> +#include 
>  #include 
>  #include 
>  #include 
>
> +#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
> +({ \
> + ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
> + might_sleep_if(timeout_us); \
> + for (;;) { \
> + (val) = readl(addr); \
> + if (cond) \
> + break; \
> + if (timeout_us && ktime_compare(ktime_get(), timeout) > 0)
> { \
> + (val) = readl(addr); \
> + break; \
> + } \
> + if (sleep_us) \
> + usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us);
> \
> + } \
> + (cond) ? 0 : -ETIMEDOUT; \
> +})
> +
> +#define UFS_QCOM_PHY_CAL_ENTRY(reg, val) \
> + {   \
> + .reg_offset = reg,  \
> + .cfg_value = val,   \
> + }
> +
>  #define UFS_QCOM_PHY_NAME_LEN30
>
> +enum {
> + MASK_SERDES_START   = 0x1,
> + MASK_PCS_READY  = 0x1,
> +};
> +
> +enum {
> + OFFSET_SERDES_START = 0x0,
> +};
> +
> +struct ufs_qcom_phy_stored_attributes {
> + u32 att;
> + u32 value;
> +};
> +
> +
>  struct ufs_qcom_phy_calibration {
>   u32 reg_offset;
>   u32 cfg_value;
> diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c
> b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
> new file mode 100644
> index 000..8332f96
> --- /dev/null
> +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
> @@ -0,0 +1,257 @@
> +/*
> + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include "phy-qcom-ufs-qmp-20nm.h"
> +
> +#define UFS_PHY_NAME "ufs_phy_qmp_20nm"
> +
> +static
> +int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy
> *ufs_qcom_phy,
> + bool is_rate_B)
> +{
> + struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
> + int tbl_size_A, tbl_size_B;
> + u8 major = ufs_qcom_phy->host_ctrl_rev_major;
> + u16 minor = ufs_qcom_phy->host_ctrl_rev_minor;
> + u16 step = ufs_qcom_phy->host_ctrl_rev_step;
> + int err;
> +
> + if ((major == 0x1) && (minor == 0x002) && (step == 0x)) {
> + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0);
> + tbl_A = phy_cal_table_rate_A_1_2_0;
> + } else if ((major == 0x1) && (minor == 0x003) && (step == 0x))
> {
> + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0);
> + tbl_A = phy_cal_table_rate_A_1_3_0;
> + } else {
> + dev_err(ufs_qcom_phy->dev, "%s: Unknown UFS-PHY version,
> no calibration values\n",
> + __func__);
> + err = -ENODEV;
> + goto out;
> + }
> +
> + tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
> + tbl_B = phy_cal_table_rate_B;
> +
> + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
> + tbl_B, tbl_size_B,
> is_rate_B);
> +
> + 

Re: [PATCH v7 1/5] phy: qcom-ufs: add support for QUALCOMM Technologies UFS PHY drivers

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick 

> This change adds a generic and common API support for ufs phy QUALCOMM
> Technologies. This support provides common code and also points
> to specific phy callbacks to differentiate between different behaviors
> of frequent use-cases (like power on, power off, phy calibration etc).
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/phy/Kconfig  |   7 +
>  drivers/phy/Makefile |   1 +
>  drivers/phy/phy-qcom-ufs-i.h | 118 +++
>  drivers/phy/phy-qcom-ufs.c   | 745
> +++
>  4 files changed, 871 insertions(+)
>  create mode 100644 drivers/phy/phy-qcom-ufs-i.h
>  create mode 100644 drivers/phy/phy-qcom-ufs.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index ccad880..26a7623 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -277,4 +277,11 @@ config PHY_STIH41X_USB
> Enable this to support the USB transceiver that is part of
> STMicroelectronics STiH41x SoC series.
>
> +config PHY_QCOM_UFS
> + tristate "Qualcomm UFS PHY driver"
> + depends on OF && ARCH_MSM
> + select GENERIC_PHY
> + help
> +   Support for UFS PHY on QCOM chipsets.
> +
>  endmenu
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index aa74f96..335965d 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -34,3 +34,4 @@ obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)+=
> phy-spear1340-miphy.o
>  obj-$(CONFIG_PHY_XGENE)  += phy-xgene.o
>  obj-$(CONFIG_PHY_STIH407_USB)+= phy-stih407-usb.o
>  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
> +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
> diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
> new file mode 100644
> index 000..dac200f
> --- /dev/null
> +++ b/drivers/phy/phy-qcom-ufs-i.h
> @@ -0,0 +1,118 @@
> +/*
> + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef UFS_QCOM_PHY_I_H_
> +#define UFS_QCOM_PHY_I_H_
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define UFS_QCOM_PHY_NAME_LEN30
> +
> +struct ufs_qcom_phy_calibration {
> + u32 reg_offset;
> + u32 cfg_value;
> +};
> +
> +struct ufs_qcom_phy_vreg {
> + const char *name;
> + struct regulator *reg;
> + int max_uA;
> + int min_uV;
> + int max_uV;
> + bool enabled;
> + bool is_always_on;
> +};
> +
> +struct ufs_qcom_phy {
> + struct list_head list;
> + struct device *dev;
> + void __iomem *mmio;
> + void __iomem *dev_ref_clk_ctrl_mmio;
> + struct clk *tx_iface_clk;
> + struct clk *rx_iface_clk;
> + bool is_iface_clk_enabled;
> + struct clk *ref_clk_src;
> + struct clk *ref_clk_parent;
> + struct clk *ref_clk;
> + bool is_ref_clk_enabled;
> + bool is_dev_ref_clk_enabled;
> + struct ufs_qcom_phy_vreg vdda_pll;
> + struct ufs_qcom_phy_vreg vdda_phy;
> + struct ufs_qcom_phy_vreg vddp_ref_clk;
> + unsigned int quirks;
> +
> + /*
> + * If UFS link is put into Hibern8 and if UFS PHY analog hardware
> is
> + * power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL),
> Hibern8
> + * exit might fail even after powering on UFS PHY analog hardware.
> + * Enabling this quirk will help to solve above issue by doing
> + * custom PHY settings just before PHY analog power collapse.
> + */
> + #define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE
> BIT(0)
> +
> + u8 host_ctrl_rev_major;
> + u16 host_ctrl_rev_minor;
> + u16 host_ctrl_rev_step;
> +
> + char name[UFS_QCOM_PHY_NAME_LEN];
> + struct ufs_qcom_phy_calibration *cached_regs;
> + int cached_regs_table_size;
> + bool is_powered_on;
> + struct ufs_qcom_phy_specific_ops *phy_spec_ops;
> +};
> +
> +/**
> + * struct ufs_qcom_phy_specific_ops - set of pointers to functions which
> have a
> + * specific implementation per phy. Each UFS phy, should implement
> + * those functions according to its spec and requirements
> + * @calibrate_phy: pointer to a function that calibrate the phy
> + * @start_serdes: pointer to a function that starts the serdes
> + * @is_physical_coding_sublayer_ready: pointer to a function that
> + * checks pcs readiness. returns 0 for success and non-zero for error.
> + * @set_tx_lane_enable: pointer to a function that enable tx lanes
> + * @power_control: pointer to a function that controls 

Re: [PATCH v7 2/5] phy: qcom-ufs: add support for 20nm phy

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick d...@codeaurora.org

 This change adds a support for a 20nm qcom-ufs phy that is required in
 platforms that use ufs-qcom controller.

 Signed-off-by: Yaniv Gardi yga...@codeaurora.org

 ---
  drivers/phy/Makefile|   1 +
  drivers/phy/phy-qcom-ufs-i.h|  43 +-
  drivers/phy/phy-qcom-ufs-qmp-20nm.c | 257
 
  drivers/phy/phy-qcom-ufs-qmp-20nm.h | 235
 +
  include/linux/phy/phy-qcom-ufs.h|  59 +
  5 files changed, 594 insertions(+), 1 deletion(-)
  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.c
  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.h
  create mode 100644 include/linux/phy/phy-qcom-ufs.h

 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
 index 335965d..781b2fa 100644
 --- a/drivers/phy/Makefile
 +++ b/drivers/phy/Makefile
 @@ -35,3 +35,4 @@ obj-$(CONFIG_PHY_XGENE) +=
 phy-xgene.o
  obj-$(CONFIG_PHY_STIH407_USB)+= phy-stih407-usb.o
  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
 +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-20nm.o
 diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
 index dac200f..591a391 100644
 --- a/drivers/phy/phy-qcom-ufs-i.h
 +++ b/drivers/phy/phy-qcom-ufs-i.h
 @@ -15,15 +15,56 @@
  #ifndef UFS_QCOM_PHY_I_H_
  #define UFS_QCOM_PHY_I_H_

 +#include linux/module.h
  #include linux/clk.h
 +#include linux/regulator/consumer.h
  #include linux/slab.h
 -#include linux/phy/phy.h
 +#include linux/phy/phy-qcom-ufs.h
  #include linux/platform_device.h
  #include linux/io.h
  #include linux/delay.h

 +#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
 +({ \
 + ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
 + might_sleep_if(timeout_us); \
 + for (;;) { \
 + (val) = readl(addr); \
 + if (cond) \
 + break; \
 + if (timeout_us  ktime_compare(ktime_get(), timeout)  0)
 { \
 + (val) = readl(addr); \
 + break; \
 + } \
 + if (sleep_us) \
 + usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us);
 \
 + } \
 + (cond) ? 0 : -ETIMEDOUT; \
 +})
 +
 +#define UFS_QCOM_PHY_CAL_ENTRY(reg, val) \
 + {   \
 + .reg_offset = reg,  \
 + .cfg_value = val,   \
 + }
 +
  #define UFS_QCOM_PHY_NAME_LEN30

 +enum {
 + MASK_SERDES_START   = 0x1,
 + MASK_PCS_READY  = 0x1,
 +};
 +
 +enum {
 + OFFSET_SERDES_START = 0x0,
 +};
 +
 +struct ufs_qcom_phy_stored_attributes {
 + u32 att;
 + u32 value;
 +};
 +
 +
  struct ufs_qcom_phy_calibration {
   u32 reg_offset;
   u32 cfg_value;
 diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c
 b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
 new file mode 100644
 index 000..8332f96
 --- /dev/null
 +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
 @@ -0,0 +1,257 @@
 +/*
 + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 and
 + * only version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + */
 +
 +#include phy-qcom-ufs-qmp-20nm.h
 +
 +#define UFS_PHY_NAME ufs_phy_qmp_20nm
 +
 +static
 +int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy
 *ufs_qcom_phy,
 + bool is_rate_B)
 +{
 + struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
 + int tbl_size_A, tbl_size_B;
 + u8 major = ufs_qcom_phy-host_ctrl_rev_major;
 + u16 minor = ufs_qcom_phy-host_ctrl_rev_minor;
 + u16 step = ufs_qcom_phy-host_ctrl_rev_step;
 + int err;
 +
 + if ((major == 0x1)  (minor == 0x002)  (step == 0x)) {
 + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0);
 + tbl_A = phy_cal_table_rate_A_1_2_0;
 + } else if ((major == 0x1)  (minor == 0x003)  (step == 0x))
 {
 + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0);
 + tbl_A = phy_cal_table_rate_A_1_3_0;
 + } else {
 + dev_err(ufs_qcom_phy-dev, %s: Unknown UFS-PHY version,
 no calibration values\n,
 + __func__);
 + err = -ENODEV;
 + goto out;
 + }
 +
 + tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
 + tbl_B = phy_cal_table_rate_B;
 +
 + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
 + tbl_B, tbl_size_B,
 

Re: [PATCH v7 4/5] phy: qcom-ufs: add support for 14nm phy

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick d...@codeaurora.org

 This change adds a support for a 14nm qcom-ufs phy that is
 required in platforms that use ufs-qcom controller.

 Signed-off-by: Yaniv Gardi yga...@codeaurora.org

 ---
  drivers/phy/Makefile|   1 +
  drivers/phy/phy-qcom-ufs-qmp-14nm.c | 201
 
  drivers/phy/phy-qcom-ufs-qmp-14nm.h | 177 +++
  3 files changed, 379 insertions(+)
  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-14nm.c
  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-14nm.h

 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
 index 781b2fa..cfbb720 100644
 --- a/drivers/phy/Makefile
 +++ b/drivers/phy/Makefile
 @@ -36,3 +36,4 @@ obj-$(CONFIG_PHY_STIH407_USB)   +=
 phy-stih407-usb.o
  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-20nm.o
 +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-14nm.o
 diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c
 b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
 new file mode 100644
 index 000..f5fc50a
 --- /dev/null
 +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
 @@ -0,0 +1,201 @@
 +/*
 + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 and
 + * only version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + */
 +
 +#include phy-qcom-ufs-qmp-14nm.h
 +
 +#define UFS_PHY_NAME ufs_phy_qmp_14nm
 +#define UFS_PHY_VDDA_PHY_UV  (925000)
 +
 +static
 +int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy
 *ufs_qcom_phy,
 + bool is_rate_B)
 +{
 + int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
 + int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
 + int err;
 +
 + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A,
 + tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B);
 +
 + if (err)
 + dev_err(ufs_qcom_phy-dev,
 + %s: ufs_qcom_phy_calibrate() failed %d\n,
 + __func__, err);
 + return err;
 +}
 +
 +static
 +void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy
 *phy_common)
 +{
 + phy_common-quirks =
 + UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
 +}
 +
 +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;
 +
 + 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
 +void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool
 val)
 +{
 + writel_relaxed(val ? 0x1 : 0x0, phy-mmio +
 UFS_PHY_POWER_DOWN_CONTROL);
 + /*
 +  * Before any transactions involving PHY, ensure PHY knows
 +  * that it's analog rail is powered ON (or OFF).
 +  */
 + mb();
 +}
 +
 +static inline
 +void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy,
 u32 val)
 +{
 + /*
 +  * 14nm PHY does not have TX_LANE_ENABLE register.
 +  * Implement this function so as not to propagate error to caller.
 +  */
 +}
 +
 +static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy
 *phy)
 +{
 + u32 tmp;
 +
 + tmp = readl_relaxed(phy-mmio + UFS_PHY_PHY_START);
 + tmp = ~MASK_SERDES_START;
 + tmp |= (1  OFFSET_SERDES_START);
 + writel_relaxed(tmp, phy-mmio + UFS_PHY_PHY_START);
 + /* Ensure register value is committed */
 + mb();
 +}
 +
 +static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy
 *phy_common)
 +{
 + int err = 0;
 + u32 val;
 +
 + err = readl_poll_timeout(phy_common-mmio +
 UFS_PHY_PCS_READY_STATUS,
 + val, (val  MASK_PCS_READY), 10, 100);
 + if (err)
 + dev_err(phy_common-dev, %s: poll for pcs failed err =
 %d\n,
 + 

Re: [PATCH v7 2/5] phy: qcom-ufs: add support for 20nm phy

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick d...@codeaurora.org

 This change adds a support for a 20nm qcom-ufs phy that is required in
 platforms that use ufs-qcom controller.

 Signed-off-by: Yaniv Gardi yga...@codeaurora.org

 ---
  drivers/phy/Makefile|   1 +
  drivers/phy/phy-qcom-ufs-i.h|  43 +-
  drivers/phy/phy-qcom-ufs-qmp-20nm.c | 257
 
  drivers/phy/phy-qcom-ufs-qmp-20nm.h | 235
 +
  include/linux/phy/phy-qcom-ufs.h|  59 +
  5 files changed, 594 insertions(+), 1 deletion(-)
  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.c
  create mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.h
  create mode 100644 include/linux/phy/phy-qcom-ufs.h

 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
 index 335965d..781b2fa 100644
 --- a/drivers/phy/Makefile
 +++ b/drivers/phy/Makefile
 @@ -35,3 +35,4 @@ obj-$(CONFIG_PHY_XGENE) +=
 phy-xgene.o
  obj-$(CONFIG_PHY_STIH407_USB)+= phy-stih407-usb.o
  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
  obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
 +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs-qmp-20nm.o
 diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
 index dac200f..591a391 100644
 --- a/drivers/phy/phy-qcom-ufs-i.h
 +++ b/drivers/phy/phy-qcom-ufs-i.h
 @@ -15,15 +15,56 @@
  #ifndef UFS_QCOM_PHY_I_H_
  #define UFS_QCOM_PHY_I_H_

 +#include linux/module.h
  #include linux/clk.h
 +#include linux/regulator/consumer.h
  #include linux/slab.h
 -#include linux/phy/phy.h
 +#include linux/phy/phy-qcom-ufs.h
  #include linux/platform_device.h
  #include linux/io.h
  #include linux/delay.h

 +#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
 +({ \
 + ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
 + might_sleep_if(timeout_us); \
 + for (;;) { \
 + (val) = readl(addr); \
 + if (cond) \
 + break; \
 + if (timeout_us  ktime_compare(ktime_get(), timeout)  0)
 { \
 + (val) = readl(addr); \
 + break; \
 + } \
 + if (sleep_us) \
 + usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us);
 \
 + } \
 + (cond) ? 0 : -ETIMEDOUT; \
 +})
 +
 +#define UFS_QCOM_PHY_CAL_ENTRY(reg, val) \
 + {   \
 + .reg_offset = reg,  \
 + .cfg_value = val,   \
 + }
 +
  #define UFS_QCOM_PHY_NAME_LEN30

 +enum {
 + MASK_SERDES_START   = 0x1,
 + MASK_PCS_READY  = 0x1,
 +};
 +
 +enum {
 + OFFSET_SERDES_START = 0x0,
 +};
 +
 +struct ufs_qcom_phy_stored_attributes {
 + u32 att;
 + u32 value;
 +};
 +
 +
  struct ufs_qcom_phy_calibration {
   u32 reg_offset;
   u32 cfg_value;
 diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c
 b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
 new file mode 100644
 index 000..8332f96
 --- /dev/null
 +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
 @@ -0,0 +1,257 @@
 +/*
 + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 and
 + * only version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + */
 +
 +#include phy-qcom-ufs-qmp-20nm.h
 +
 +#define UFS_PHY_NAME ufs_phy_qmp_20nm
 +
 +static
 +int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy
 *ufs_qcom_phy,
 + bool is_rate_B)
 +{
 + struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
 + int tbl_size_A, tbl_size_B;
 + u8 major = ufs_qcom_phy-host_ctrl_rev_major;
 + u16 minor = ufs_qcom_phy-host_ctrl_rev_minor;
 + u16 step = ufs_qcom_phy-host_ctrl_rev_step;
 + int err;
 +
 + if ((major == 0x1)  (minor == 0x002)  (step == 0x)) {
 + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0);
 + tbl_A = phy_cal_table_rate_A_1_2_0;
 + } else if ((major == 0x1)  (minor == 0x003)  (step == 0x))
 {
 + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0);
 + tbl_A = phy_cal_table_rate_A_1_3_0;
 + } else {
 + dev_err(ufs_qcom_phy-dev, %s: Unknown UFS-PHY version,
 no calibration values\n,
 + __func__);
 + err = -ENODEV;
 + goto out;
 + }
 +
 + tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
 + tbl_B = phy_cal_table_rate_B;
 +
 + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
 + tbl_B, tbl_size_B,
 

Re: [PATCH v7 1/5] phy: qcom-ufs: add support for QUALCOMM Technologies UFS PHY drivers

2015-01-15 Thread dovl
Reviewed-by: Dov Levenglick d...@codeaurora.org

 This change adds a generic and common API support for ufs phy QUALCOMM
 Technologies. This support provides common code and also points
 to specific phy callbacks to differentiate between different behaviors
 of frequent use-cases (like power on, power off, phy calibration etc).

 Signed-off-by: Yaniv Gardi yga...@codeaurora.org

 ---
  drivers/phy/Kconfig  |   7 +
  drivers/phy/Makefile |   1 +
  drivers/phy/phy-qcom-ufs-i.h | 118 +++
  drivers/phy/phy-qcom-ufs.c   | 745
 +++
  4 files changed, 871 insertions(+)
  create mode 100644 drivers/phy/phy-qcom-ufs-i.h
  create mode 100644 drivers/phy/phy-qcom-ufs.c

 diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
 index ccad880..26a7623 100644
 --- a/drivers/phy/Kconfig
 +++ b/drivers/phy/Kconfig
 @@ -277,4 +277,11 @@ config PHY_STIH41X_USB
 Enable this to support the USB transceiver that is part of
 STMicroelectronics STiH41x SoC series.

 +config PHY_QCOM_UFS
 + tristate Qualcomm UFS PHY driver
 + depends on OF  ARCH_MSM
 + select GENERIC_PHY
 + help
 +   Support for UFS PHY on QCOM chipsets.
 +
  endmenu
 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
 index aa74f96..335965d 100644
 --- a/drivers/phy/Makefile
 +++ b/drivers/phy/Makefile
 @@ -34,3 +34,4 @@ obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)+=
 phy-spear1340-miphy.o
  obj-$(CONFIG_PHY_XGENE)  += phy-xgene.o
  obj-$(CONFIG_PHY_STIH407_USB)+= phy-stih407-usb.o
  obj-$(CONFIG_PHY_STIH41X_USB)+= phy-stih41x-usb.o
 +obj-$(CONFIG_PHY_QCOM_UFS)   += phy-qcom-ufs.o
 diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
 new file mode 100644
 index 000..dac200f
 --- /dev/null
 +++ b/drivers/phy/phy-qcom-ufs-i.h
 @@ -0,0 +1,118 @@
 +/*
 + * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 and
 + * only version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + */
 +
 +#ifndef UFS_QCOM_PHY_I_H_
 +#define UFS_QCOM_PHY_I_H_
 +
 +#include linux/clk.h
 +#include linux/slab.h
 +#include linux/phy/phy.h
 +#include linux/platform_device.h
 +#include linux/io.h
 +#include linux/delay.h
 +
 +#define UFS_QCOM_PHY_NAME_LEN30
 +
 +struct ufs_qcom_phy_calibration {
 + u32 reg_offset;
 + u32 cfg_value;
 +};
 +
 +struct ufs_qcom_phy_vreg {
 + const char *name;
 + struct regulator *reg;
 + int max_uA;
 + int min_uV;
 + int max_uV;
 + bool enabled;
 + bool is_always_on;
 +};
 +
 +struct ufs_qcom_phy {
 + struct list_head list;
 + struct device *dev;
 + void __iomem *mmio;
 + void __iomem *dev_ref_clk_ctrl_mmio;
 + struct clk *tx_iface_clk;
 + struct clk *rx_iface_clk;
 + bool is_iface_clk_enabled;
 + struct clk *ref_clk_src;
 + struct clk *ref_clk_parent;
 + struct clk *ref_clk;
 + bool is_ref_clk_enabled;
 + bool is_dev_ref_clk_enabled;
 + struct ufs_qcom_phy_vreg vdda_pll;
 + struct ufs_qcom_phy_vreg vdda_phy;
 + struct ufs_qcom_phy_vreg vddp_ref_clk;
 + unsigned int quirks;
 +
 + /*
 + * If UFS link is put into Hibern8 and if UFS PHY analog hardware
 is
 + * power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL),
 Hibern8
 + * exit might fail even after powering on UFS PHY analog hardware.
 + * Enabling this quirk will help to solve above issue by doing
 + * custom PHY settings just before PHY analog power collapse.
 + */
 + #define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE
 BIT(0)
 +
 + u8 host_ctrl_rev_major;
 + u16 host_ctrl_rev_minor;
 + u16 host_ctrl_rev_step;
 +
 + char name[UFS_QCOM_PHY_NAME_LEN];
 + struct ufs_qcom_phy_calibration *cached_regs;
 + int cached_regs_table_size;
 + bool is_powered_on;
 + struct ufs_qcom_phy_specific_ops *phy_spec_ops;
 +};
 +
 +/**
 + * struct ufs_qcom_phy_specific_ops - set of pointers to functions which
 have a
 + * specific implementation per phy. Each UFS phy, should implement
 + * those functions according to its spec and requirements
 + * @calibrate_phy: pointer to a function that calibrate the phy
 + * @start_serdes: pointer to a function that starts the serdes
 + * @is_physical_coding_sublayer_ready: pointer to a function that
 + * checks pcs readiness. returns 0 for success and non-zero for error.
 + * @set_tx_lane_enable: pointer to a function that enable tx lanes
 + * @power_control: pointer to a function that controls analog rail of phy
 +