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

2015-01-21 Thread Kishon Vijay Abraham I
hi,

On Thursday 15 January 2015 08:02 PM, Yaniv Gardi wrote:
> 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, 

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

2015-01-21 Thread Kishon Vijay Abraham I
hi,

On Thursday 15 January 2015 08:02 PM, Yaniv Gardi wrote:
 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, 

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