[PATCH] drm/msm/mdp5: high precision vblank timestamp support

2015-10-26 Thread Archit Taneja
MDP5 has line count and frame count registers for each interface. Enable
these counters and use them to implement the get_vblank_timestamp drm
driver op.

The line counter starts with the value 1 at the beginning of the VSYNC
pulse and ends with value VTOTAL at the end of VFP. This value is used
to determine whether we're in blanking period or not, and an adjusted
value of this counter is used to get vpos as expected by
get_scanout_position. Since there is no way to calculate hpos, we always
set it to 0.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |  18 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 129 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   2 +
 3 files changed, 149 insertions(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index c9e32b0..a019656 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -293,6 +293,24 @@ static const struct drm_encoder_helper_funcs 
mdp5_encoder_helper_funcs = {
.enable = mdp5_encoder_enable,
 };
 
+int mdp5_encoder_get_linecount(struct drm_encoder *encoder)
+{
+   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+   struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   int intf = mdp5_encoder->intf.num;
+
+   return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf));
+}
+
+u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder)
+{
+   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+   struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   int intf = mdp5_encoder->intf.num;
+
+   return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf));
+}
+
 int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
struct drm_encoder *slave_encoder)
 {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index b532faa..e115318 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -468,6 +468,127 @@ static int get_clk(struct platform_device *pdev, struct 
clk **clkp,
return 0;
 }
 
+static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_encoder *encoder;
+
+   drm_for_each_encoder(encoder, dev)
+   if (encoder->crtc == crtc)
+   return encoder;
+
+   return NULL;
+}
+
+static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
+  unsigned int flags, int *vpos, int *hpos,
+  ktime_t *stime, ktime_t *etime,
+  const struct drm_display_mode *mode)
+{
+   struct msm_drm_private *priv = dev->dev_private;
+   struct drm_crtc *crtc;
+   struct drm_encoder *encoder;
+   int line, vsw, vbp, vactive_start, vactive_end, vfp_end;
+   int ret = 0;
+
+   crtc = priv->crtcs[pipe];
+   if (!crtc) {
+   DRM_ERROR("Invalid crtc %d\n", pipe);
+   return 0;
+   }
+
+   encoder = get_encoder_from_crtc(crtc);
+   if (!encoder) {
+   DRM_ERROR("no encoder found for crtc %d\n", pipe);
+   return 0;
+   }
+
+   ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
+
+   vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
+   vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
+
+   /*
+* the line counter is 1 at the start of the VSYNC pulse and VTOTAL at
+* the end of VFP. Translate the porch values relative to the line
+* counter positions.
+*/
+
+   vactive_start = vsw + vbp + 1;
+
+   vactive_end = vactive_start + mode->crtc_vdisplay;
+
+   /* last scan line before VSYNC */
+   vfp_end = mode->crtc_vtotal;
+
+   if (stime)
+   *stime = ktime_get();
+
+   line = mdp5_encoder_get_linecount(encoder);
+
+   if (line < vactive_start) {
+   line -= vactive_start;
+   ret |= DRM_SCANOUTPOS_IN_VBLANK;
+   } else if (line > vactive_end) {
+   line = line - vfp_end - vactive_start;
+   ret |= DRM_SCANOUTPOS_IN_VBLANK;
+   } else {
+   line -= vactive_start;
+   }
+
+   *vpos = line;
+   *hpos = 0;
+
+   if (etime)
+   *etime = ktime_get();
+
+   return ret;
+}
+
+static int mdp5_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
+int *max_error,
+struct timeval *vblank_time,
+unsigned flags)
+{
+   struct msm_drm_private *priv = dev->dev_private;
+   struct drm_crtc *crtc;
+
+   if (pipe < 0 || pipe >= priv->num_crtcs) {
+   DRM_ERROR("Invalid crtc %d\n", pipe);
+   

Re: [PATCH v3 2/8] clk: qcom: msm8916: Set the parent of xo to xo_board

2015-10-26 Thread Stephen Boyd
On 10/20, Georgi Djakov wrote:
> Remove the hard-coded clock rate from the driver and set the XO
> parent to the on-board XO oscillator that is defined in the DT.
> 
> Signed-off-by: Georgi Djakov 
> ---
>  drivers/clk/qcom/gcc-msm8916.c |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
> index d0a0313d6bef..3c0668b12142 100644
> --- a/drivers/clk/qcom/gcc-msm8916.c
> +++ b/drivers/clk/qcom/gcc-msm8916.c
> @@ -3360,7 +3360,7 @@ static int gcc_msm8916_probe(struct platform_device 
> *pdev)
>   struct device *dev = >dev;
>  
>   /* Temporary until RPM clocks supported */
> - clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 1920);
> + clk = clk_register_fixed_factor(dev, "xo", "xo_board", 0, 1, 1);

Sorry, I'd prefer to not take any DT changes through clk tree if
we can avoid it. So we need to write some code to figure out if
the xo_board clock is present, and keep registering this clock as
the root clk if it isn't there.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/3] Remove the need for qcom,{msm-id,board-id,pmic-id}

2015-10-26 Thread Stephen Boyd
This patchset documents a compatible string format that encodes
all the information that was being encoded in qcom specific DT
properties in downstream msm kernels. The goal being to come
up with a format that will allow us to express the information
we want to express without requiring the use of vendor specific
properties. An updated dtbTool will be released after these new
bindings are accepted so that users can work with non-updateable
bootloaders.

This is an attempt to resolve a discussion around March of this year[1]
where the arm-soc maintainers suggested we express this information
through the board's compatible string.

[1] 
http://lkml.kernel.org/g/1425503602-24916-1-git-send-email-ga...@codeaurora.org

Stephen Boyd (3):
  devicetree: bindings: Document qcom board compatible format
  arm64: dts: qcom: Make msm8916-mtp compatible string compliant
  arm: dts: qcom: Update ifc6540 compat for qcom boot format

 Documentation/devicetree/bindings/arm/qcom.txt | 86 ++
 arch/arm/boot/dts/qcom-apq8084-ifc6540.dts |  2 +-
 arch/arm64/boot/dts/qcom/msm8916-mtp.dts   |  2 +-
 3 files changed, 88 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/qcom.txt

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 04/14] devicetree: Add hardware rng entry to qcom-apq8064.dtsi

2015-10-26 Thread Bjorn Andersson
On Fri 18 Sep 05:31 PDT 2015, Srinivas Kandagatla wrote:

> From: John Stultz 
> 
> Add devicetree data to add support for hw_rng support
> to the apq8064 dts.
> 
> Tested on the Nexus7 (2013).
> 
> Cc: Kumar Gala 
> Cc: Stephen Boyd 
> Cc: Srinivas Kandagatla 
> Cc: devicet...@vger.kernel.org

Reviewed-by: Bjorn Andersson 

> Reviewed-by: Stephen Boyd 
> Signed-off-by: John Stultz 

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 17/17] scsi: ufs-qcom: fix compilation warnings

2015-10-26 Thread Stephen Boyd
On 10/26/2015 08:41 AM, Yaniv Gardi wrote:
> Tnis patch fixes the following compilation warnings:
> ...ufs-qcom.c:1201:40:
>   warning: incorrect type in argument 1 (different address spaces)
> ...ufs-qcom.c:1201:40:
>   expected void const *ptr
> ...ufs-qcom.c:1201:40:
>   got void [noderef] *dev_ref_clk_ctrl_mmio
> ...ufs-qcom.c:1207:53:
>   warning: incorrect type in argument 1 (different address spaces)
> ...ufs-qcom.c:1207:53:
>   expected void const *ptr
> ...ufs-qcom.c:1207:53:
>   got void [noderef] *dev_ref_clk_ctrl_mmio
>
> Signed-off-by: Yaniv Gardi 
>
> ---

What version of sparse do you use? You shouldn't need to do this.

>  drivers/scsi/ufs/ufs-qcom.c | 9 +
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 72b0ef7..b57f88a 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1226,11 +1226,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
>   if (res) {
>   host->dev_ref_clk_ctrl_mmio =
>   devm_ioremap_resource(dev, res);
> - if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) {
> - dev_warn(dev,
> - "%s: could not map 
> dev_ref_clk_ctrl_mmio, err %ld\n",
> + if (IS_ERR((__force void const *)
> +host->dev_ref_clk_ctrl_mmio)) {
> + dev_warn(dev, "%s: could not map 
> dev_ref_clk_ctrl_mmio, err %ld\n",
>   __func__,
> - PTR_ERR(host->dev_ref_clk_ctrl_mmio));
> + PTR_ERR((__force void const *)
> +  host->dev_ref_clk_ctrl_mmio));
>   host->dev_ref_clk_ctrl_mmio = NULL;
>   }
>   host->dev_ref_clk_en_mask = BIT(5);


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] clk: qcom: msm8960: Fix dsi1/2 halt bits

2015-10-26 Thread Stephen Boyd
The halt bits for these clocks seem wrong. I get the following
warning while booting on an msm8960-cdp:

WARNING: CPU: 0 PID: 1 at drivers/clk/qcom/clk-branch.c:97 
clk_branch_toggle+0xd0/0x138()
dsi1_clk status stuck at 'on'
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.3.0-rc3-00113-g5532cfb567fe #110
Hardware name: Qualcomm (Flattened Device Tree)
[] (unwind_backtrace) from [] (show_stack+0x10/0x14)
[] (show_stack) from [] (dump_stack+0x70/0xbc)
[] (dump_stack) from [] (warn_slowpath_common+0x78/0xb4)
[] (warn_slowpath_common) from [] 
(warn_slowpath_fmt+0x30/0x40)
[] (warn_slowpath_fmt) from [] 
(clk_branch_toggle+0xd0/0x138)
[] (clk_branch_toggle) from [] 
(clk_disable_unused_subtree+0x98/0x1b0)
[] (clk_disable_unused_subtree) from [] 
(clk_disable_unused_subtree+0x20/0x1b0)
[] (clk_disable_unused_subtree) from [] 
(clk_disable_unused+0x58/0xd8)
[] (clk_disable_unused) from [] (do_one_initcall+0xac/0x1ec)
[] (do_one_initcall) from [] 
(kernel_init_freeable+0x11c/0x1e8)
[] (kernel_init_freeable) from [] (kernel_init+0x8/0xec)
[] (kernel_init) from [] (ret_from_fork+0x14/0x3c)

Fix the status bits and the errors go away.

Fixes: 5532cfb567fe ("clk: qcom: mmcc-8960: Add DSI related clocks")
Cc: Archit Taneja 
Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/mmcc-msm8960.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index 397f5df6422a..00e36192a1de 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -2104,7 +2104,7 @@ static struct clk_rcg dsi1_src = {
 
 static struct clk_branch dsi1_clk = {
.halt_reg = 0x01d0,
-   .halt_bit = 1,
+   .halt_bit = 2,
.clkr = {
.enable_reg = 0x004c,
.enable_mask = BIT(0),
@@ -2152,7 +2152,7 @@ static struct clk_rcg dsi2_src = {
 
 static struct clk_branch dsi2_clk = {
.halt_reg = 0x01d0,
-   .halt_bit = 2,
+   .halt_bit = 20,
.clkr = {
.enable_reg = 0x003c,
.enable_mask = BIT(0),
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] arm: dts: qcom: Update ifc6540 compat for qcom boot format

2015-10-26 Thread Stephen Boyd
The ifc6540 is an sbc (single board computer) board, so update
the compatible field accordingly.

Signed-off-by: Stephen Boyd 
---
 arch/arm/boot/dts/qcom-apq8084-ifc6540.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom-apq8084-ifc6540.dts 
b/arch/arm/boot/dts/qcom-apq8084-ifc6540.dts
index c9c2b769554f..32aaa9d45228 100644
--- a/arch/arm/boot/dts/qcom-apq8084-ifc6540.dts
+++ b/arch/arm/boot/dts/qcom-apq8084-ifc6540.dts
@@ -3,7 +3,7 @@
 
 / {
model = "Qualcomm APQ8084/IFC6540";
-   compatible = "qcom,apq8084-ifc6540", "qcom,apq8084";
+   compatible = "qcom,apq8084-sbc", "qcom,apq8084";
 
aliases {
serial0 = _uart2;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] devicetree: bindings: Document qcom board compatible format

2015-10-26 Thread Stephen Boyd
Some qcom based bootloaders identify the dtb blob based on a set
of device properties like SoC, platform, PMIC, and revisions of
those components. In downstream kernels, these values are added
to the different component dtsi files (i.e. pmic dtsi file, SoC
dtsi file, board dtsi file, etc.) via qcom specific DT
properties. The dtb files are parsed by a program called dtbTool
that picks out these properties and creates a table of contents
binary blob with the property information and some offsets into
the concatenation of all the dtbs (termed a QCDT image).

The suggestion is to do this via the board compatible string
instead, because these qcom specific properties are never used by
the kernel. Add a document describing the format of the
compatible string that encodes all this information that's
currently encoded in the qcom,{msm-id,board-id,pmic-id}
properties in downstream devicetrees. Future bootloaders may be
updated to look at the compatible field instead of looking for
the table of contents image. For non-updateable bootloaders, a
new dtbTool program will parse the compatible string and generate
a QCDT image from it.

Signed-off-by: Stephen Boyd 
---
 Documentation/devicetree/bindings/arm/qcom.txt | 86 ++
 1 file changed, 86 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/qcom.txt

diff --git a/Documentation/devicetree/bindings/arm/qcom.txt 
b/Documentation/devicetree/bindings/arm/qcom.txt
new file mode 100644
index ..ed084367182d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/qcom.txt
@@ -0,0 +1,86 @@
+QCOM device tree bindings
+-
+
+Some qcom based bootloaders identify the dtb blob based on a set of
+device properties like SoC, platform, PMIC, and revisions of those components.
+To support this scheme, we encode this information into the board compatible
+string.
+
+Each board must specify a top-level board compatible string with the following
+format:
+
+   compatible = 
"qcom,(-)(-)-(/)(-)(-MB)(--panel)(-boot-)(-(-v)){0-4}"
+
+where elements in parentheses "()" are optional and elements in brackets "<>"
+are names of elements. Meaning only the 'SoC' and 'plat_type' elements are
+required.
+
+The 'SoC' element must be one of the following strings:
+
+   apq8016
+   apq8074
+   apq8084
+   apq8096
+   msm8916
+   msm8974
+   msm8996
+
+The 'plat_type' element must be one of the following strings:
+
+   cdp
+   liquid
+   dragonboard
+   mtp sbc
+
+
+The 'soc_version', 'plat_version' and 'pmic_version' elements take the form of
+v. where the minor number may be omitted when it's zero, i.e.
+v1.0 is the same as v1. If all versions of the 'plat_version' element's match,
+then a wildcard '*' should be used, e.g. 'v*'.
+
+The 'foundry_id', 'subtype', and 'mb' elements are one or more digits from 0
+to 9.
+
+The 'panel' element must be one of the following strings:
+
+   720p
+   fWVGA
+   hd
+   qHD
+
+The 'boot' element must be one of the following strings:
+
+   emmc_sdc1
+   ufs
+
+The 'pmic' element must be one of the following strings:
+
+   pm8841
+   pm8019
+   pm8110
+   pma8084
+   pmi8962
+   pmd9635
+   pm8994
+   pmi8994
+   pm8916
+   pm8004
+   pm8909
+
+The 'pmic' element is specified in order of ascending USID. The PMIC in USID0
+goes first, and then USID2, USID4, and finally USID6. Up to four PMICs may be
+specified and no holes in the USID number space are allowed.
+
+Examples:
+
+   "qcom,msm8916-v1-cdp-pm8916-v2.1"
+
+A CDP board with an msm8916 SoC, version 1 paired with a pm8916 PMIC of version
+2.1.
+
+   
"qcom,apq8074-v2.0-2-dragonboard/1-v0.1-512MB-panel-qHD-boot-emmc_sdc1-pm8941-v0.2-pm8909-v2.2-pma8084-v3-pm8110-v1"
+
+A dragonboard board v0.1 of subtype 1 with an apq8074 SoC version 2, made in
+foundry 2 with 512MB of memory and a qHD panel booting from emmc_sdc1, paired
+with a pm8941 PMIC version 0.2 at USID0, pm8909 PMIC version 2.2 at USID2,
+pma8084 version 3 at USID4 and a pm8110 version 1 at USID6.
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 3/8] clk: qcom: msm8916: Ignore sleep_clk_src registration errors

2015-10-26 Thread Stephen Boyd
On 10/20, Georgi Djakov wrote:
> We are moving the sleep clock to the DT. While all patches
> are merged, we will ignore sleep_clk_src registration errors.
> By ignoring this error, the msm8916 boards will continue booting
> during this transition period, otherwise the clock controller
> initialization will fail.
> 
> Signed-off-by: Georgi Djakov 
> ---
>  drivers/clk/qcom/gcc-msm8916.c |6 ++
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
> index 3c0668b12142..4bb7d8415ba7 100644
> --- a/drivers/clk/qcom/gcc-msm8916.c
> +++ b/drivers/clk/qcom/gcc-msm8916.c
> @@ -3364,10 +3364,8 @@ static int gcc_msm8916_probe(struct platform_device 
> *pdev)
>   if (IS_ERR(clk))
>   return PTR_ERR(clk);
>  
> - clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
> -   CLK_IS_ROOT, 32768);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> + clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
> + CLK_IS_ROOT, 32768);
>  

And we might as well do the same check here too. We can remove
the code in a year or something.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] drm/msm/mdp5: high precision vblank timestamp support

2015-10-26 Thread Rob Clark
On Mon, Oct 26, 2015 at 5:54 AM, Archit Taneja  wrote:
> MDP5 has line count and frame count registers for each interface. Enable
> these counters and use them to implement the get_vblank_timestamp drm
> driver op.
>
> The line counter starts with the value 1 at the beginning of the VSYNC
> pulse and ends with value VTOTAL at the end of VFP. This value is used
> to determine whether we're in blanking period or not, and an adjusted
> value of this counter is used to get vpos as expected by
> get_scanout_position. Since there is no way to calculate hpos, we always
> set it to 0.

What are the odds that mdp(n!=5) could support the same?  If/when that
ever happens I could see making some of this helpers to duplicate a
bit less in mdpN backend.. but I guess also fine to cross that bridge
when we come to it.  Other than that, lgtm, thanks

BR,
-R

> Signed-off-by: Archit Taneja 
> ---
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |  18 
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 129 
> 
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   2 +
>  3 files changed, 149 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
> b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
> index c9e32b0..a019656 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
> @@ -293,6 +293,24 @@ static const struct drm_encoder_helper_funcs 
> mdp5_encoder_helper_funcs = {
> .enable = mdp5_encoder_enable,
>  };
>
> +int mdp5_encoder_get_linecount(struct drm_encoder *encoder)
> +{
> +   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
> +   struct mdp5_kms *mdp5_kms = get_kms(encoder);
> +   int intf = mdp5_encoder->intf.num;
> +
> +   return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf));
> +}
> +
> +u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder)
> +{
> +   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
> +   struct mdp5_kms *mdp5_kms = get_kms(encoder);
> +   int intf = mdp5_encoder->intf.num;
> +
> +   return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf));
> +}
> +
>  int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
> struct drm_encoder *slave_encoder)
>  {
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
> b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
> index b532faa..e115318 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
> @@ -468,6 +468,127 @@ static int get_clk(struct platform_device *pdev, struct 
> clk **clkp,
> return 0;
>  }
>
> +static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
> +{
> +   struct drm_device *dev = crtc->dev;
> +   struct drm_encoder *encoder;
> +
> +   drm_for_each_encoder(encoder, dev)
> +   if (encoder->crtc == crtc)
> +   return encoder;
> +
> +   return NULL;
> +}
> +
> +static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
> +  unsigned int flags, int *vpos, int *hpos,
> +  ktime_t *stime, ktime_t *etime,
> +  const struct drm_display_mode *mode)
> +{
> +   struct msm_drm_private *priv = dev->dev_private;
> +   struct drm_crtc *crtc;
> +   struct drm_encoder *encoder;
> +   int line, vsw, vbp, vactive_start, vactive_end, vfp_end;
> +   int ret = 0;
> +
> +   crtc = priv->crtcs[pipe];
> +   if (!crtc) {
> +   DRM_ERROR("Invalid crtc %d\n", pipe);
> +   return 0;
> +   }
> +
> +   encoder = get_encoder_from_crtc(crtc);
> +   if (!encoder) {
> +   DRM_ERROR("no encoder found for crtc %d\n", pipe);
> +   return 0;
> +   }
> +
> +   ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
> +
> +   vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
> +   vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
> +
> +   /*
> +* the line counter is 1 at the start of the VSYNC pulse and VTOTAL at
> +* the end of VFP. Translate the porch values relative to the line
> +* counter positions.
> +*/
> +
> +   vactive_start = vsw + vbp + 1;
> +
> +   vactive_end = vactive_start + mode->crtc_vdisplay;
> +
> +   /* last scan line before VSYNC */
> +   vfp_end = mode->crtc_vtotal;
> +
> +   if (stime)
> +   *stime = ktime_get();
> +
> +   line = mdp5_encoder_get_linecount(encoder);
> +
> +   if (line < vactive_start) {
> +   line -= vactive_start;
> +   ret |= DRM_SCANOUTPOS_IN_VBLANK;
> +   } else if (line > vactive_end) {
> +   line = line - vfp_end - vactive_start;
> +   ret |= DRM_SCANOUTPOS_IN_VBLANK;
> +   } else {
> +   line -= vactive_start;

[PATCH] arm: dts: qcom: Add board clocks

2015-10-26 Thread Stephen Boyd
These clocks are fixed rate board sources that should be in DT.
Add them.

Cc: Georgi Djakov 
Signed-off-by: Stephen Boyd 
---
 arch/arm/boot/dts/qcom-msm8960.dtsi | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi 
b/arch/arm/boot/dts/qcom-msm8960.dtsi
index 134cd91d68ec..51a40d84145c 100644
--- a/arch/arm/boot/dts/qcom-msm8960.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi
@@ -49,6 +49,29 @@
qcom,no-pc-write;
};
 
+   clocks {
+   cxo_board {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <1920>;
+   clock-output-names = "cxo_board";
+   };
+
+   pxo_board {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <2700>;
+   clock-output-names = "pxo_board";
+   };
+
+   sleep_clk {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <32768>;
+   clock-output-names = "sleep_clk";
+   };
+   };
+
soc: soc {
#address-cells = <1>;
#size-cells = <1>;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] clk: qcom: common: Add API to register board clocks backwards compatibly

2015-10-26 Thread Stephen Boyd
We want to put the XO board clocks into the dt files. Add an API
to do this generically. This also makes a place for us to handle
the case where the RPM driver is enabled or disabled.

Cc: Georgi Djakov 
Signed-off-by: Stephen Boyd 
---

I'm also thinking that maybe we should register the board clock if it
isn't there in DT and then we'll either register the pass through or
we'll skip it depending on if the RPM driver is enabled. That
way the RPM driver doesn't need to know anything, just register the
clock with parent as the board clock.

 drivers/clk/qcom/common.c | 47 +++
 drivers/clk/qcom/common.h |  3 +++
 2 files changed, 50 insertions(+)

diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 8fa477293ae0..84d4d6fc0dec 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -88,6 +88,53 @@ static void qcom_cc_gdsc_unregister(void *data)
gdsc_unregister(data);
 }
 
+int qcom_cc_register_board_clk(struct device *dev, const char *path,
+  const char *name, unsigned long rate)
+{
+   struct device_node *node = NULL;
+   struct device_node *clocks_node;
+   struct clk_fixed_factor *factor;
+   struct clk_fixed_rate *fixed;
+   struct clk_hw *hw;
+   struct clk_init_data init_data = { .name = name };
+
+   clocks_node = of_find_node_by_path("/clocks");
+   if (clocks_node)
+   node = of_find_node_by_name(clocks_node, path);
+   of_node_put(clocks_node);
+
+   if (node) {
+   factor = devm_kzalloc(dev, sizeof(*factor), GFP_KERNEL);
+   if (!factor)
+   return -EINVAL;
+
+   factor->mult = factor->div = 1;
+   factor->hw.init = _data;
+
+   init_data.parent_names = 
+   init_data.num_parents = 1;
+   init_data.ops = _fixed_factor_ops;
+
+   hw = >hw;
+   } else {
+   fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
+   if (!fixed)
+   return -EINVAL;
+
+   fixed->fixed_rate = rate;
+   fixed->hw.init = _data;
+
+   init_data.flags = CLK_IS_ROOT;
+   init_data.ops = _fixed_rate_ops;
+
+   hw = >hw;
+   }
+   of_node_put(node);
+
+   return PTR_ERR_OR_ZERO(devm_clk_register(dev, hw));
+}
+EXPORT_SYMBOL(qcom_cc_register_board_clk);
+
 int qcom_cc_really_probe(struct platform_device *pdev,
 const struct qcom_cc_desc *desc, struct regmap *regmap)
 {
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 7c1fba3ebc03..70e68a8d82a7 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -37,6 +37,9 @@ extern const struct freq_tbl *qcom_find_freq(const struct 
freq_tbl *f,
 extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
   u8 src);
 
+extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
+ const char *name, unsigned long rate);
+
 extern struct regmap *qcom_cc_map(struct platform_device *pdev,
  const struct qcom_cc_desc *desc);
 extern int qcom_cc_really_probe(struct platform_device *pdev,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] drm/msm/mdp5: high precision vblank timestamp support

2015-10-26 Thread Archit Taneja



On 10/27/2015 05:33 AM, Rob Clark wrote:

On Mon, Oct 26, 2015 at 5:54 AM, Archit Taneja  wrote:

MDP5 has line count and frame count registers for each interface. Enable
these counters and use them to implement the get_vblank_timestamp drm
driver op.

The line counter starts with the value 1 at the beginning of the VSYNC
pulse and ends with value VTOTAL at the end of VFP. This value is used
to determine whether we're in blanking period or not, and an adjusted
value of this counter is used to get vpos as expected by
get_scanout_position. Since there is no way to calculate hpos, we always
set it to 0.


What are the odds that mdp(n!=5) could support the same?  If/when that
ever happens I could see making some of this helpers to duplicate a
bit less in mdpN backend.. but I guess also fine to cross that bridge
when we come to it.  Other than that, lgtm, thanks


The MDP4 line counter only loops within the active region, making it 
sort of ineffective. That's the main reason why I didn't attempt to 
implement it for mdp4.


There seems to be a 12 bit frame counter available to implement a
vblank counter, but without the line counter, I'm not sure if that'll
be any better than using the software vblank counter.

Archit



BR,
-R


Signed-off-by: Archit Taneja 
---
  drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |  18 
  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 129 
  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   2 +
  3 files changed, 149 insertions(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index c9e32b0..a019656 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -293,6 +293,24 @@ static const struct drm_encoder_helper_funcs 
mdp5_encoder_helper_funcs = {
 .enable = mdp5_encoder_enable,
  };

+int mdp5_encoder_get_linecount(struct drm_encoder *encoder)
+{
+   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+   struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   int intf = mdp5_encoder->intf.num;
+
+   return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf));
+}
+
+u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder)
+{
+   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+   struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   int intf = mdp5_encoder->intf.num;
+
+   return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf));
+}
+
  int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
 struct drm_encoder *slave_encoder)
  {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index b532faa..e115318 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -468,6 +468,127 @@ static int get_clk(struct platform_device *pdev, struct 
clk **clkp,
 return 0;
  }

+static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct drm_encoder *encoder;
+
+   drm_for_each_encoder(encoder, dev)
+   if (encoder->crtc == crtc)
+   return encoder;
+
+   return NULL;
+}
+
+static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
+  unsigned int flags, int *vpos, int *hpos,
+  ktime_t *stime, ktime_t *etime,
+  const struct drm_display_mode *mode)
+{
+   struct msm_drm_private *priv = dev->dev_private;
+   struct drm_crtc *crtc;
+   struct drm_encoder *encoder;
+   int line, vsw, vbp, vactive_start, vactive_end, vfp_end;
+   int ret = 0;
+
+   crtc = priv->crtcs[pipe];
+   if (!crtc) {
+   DRM_ERROR("Invalid crtc %d\n", pipe);
+   return 0;
+   }
+
+   encoder = get_encoder_from_crtc(crtc);
+   if (!encoder) {
+   DRM_ERROR("no encoder found for crtc %d\n", pipe);
+   return 0;
+   }
+
+   ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
+
+   vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
+   vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
+
+   /*
+* the line counter is 1 at the start of the VSYNC pulse and VTOTAL at
+* the end of VFP. Translate the porch values relative to the line
+* counter positions.
+*/
+
+   vactive_start = vsw + vbp + 1;
+
+   vactive_end = vactive_start + mode->crtc_vdisplay;
+
+   /* last scan line before VSYNC */
+   vfp_end = mode->crtc_vtotal;
+
+   if (stime)
+   *stime = ktime_get();
+
+   line = mdp5_encoder_get_linecount(encoder);
+
+   if (line < vactive_start) {
+   line -= vactive_start;
+   ret |= DRM_SCANOUTPOS_IN_VBLANK;
+   } else if (line 

Re: [PATCH] sched: fix incorrect wait time and wait count statistics

2015-10-26 Thread Joonwoo Park
On 10/25/2015 03:26 AM, Peter Zijlstra wrote:
> On Sat, Oct 24, 2015 at 10:23:14PM -0700, Joonwoo Park wrote:
>> @@ -1069,7 +1069,7 @@ static struct rq *move_queued_task(struct rq *rq, 
>> struct task_struct *p, int new
>>  {
>>  lockdep_assert_held(>lock);
>>  
>> -dequeue_task(rq, p, 0);
>> +dequeue_task(rq, p, DEQUEUE_MIGRATING);
>>  p->on_rq = TASK_ON_RQ_MIGRATING;
>>  set_task_cpu(p, new_cpu);
>>  raw_spin_unlock(>lock);
> 
>> @@ -5656,7 +5671,7 @@ static void detach_task(struct task_struct *p, struct 
>> lb_env *env)
>>  {
>>  lockdep_assert_held(>src_rq->lock);
>>  
>> -deactivate_task(env->src_rq, p, 0);
>> +deactivate_task(env->src_rq, p, DEQUEUE_MIGRATING);
>>  p->on_rq = TASK_ON_RQ_MIGRATING;
>>  set_task_cpu(p, env->dst_cpu);
>>  }
> 
> Also note that on both sites we also set TASK_ON_RQ_MIGRATING -- albeit
> late. Can't you simply set that earlier (and back to QUEUED later) and
> test for task_on_rq_migrating() instead of blowing up the fastpath like
> you did?
> 

Yes it's doable.  I also find it's much simpler.
Please find patch v2.  I verified v2 does same job as v1 by comparing 
sched_stat_wait time with sched_switch - sched_wakeup timestamp.

Thanks,
Joonwoo
>From 98d615d46211a90482a0f9b7204265c54bba8520 Mon Sep 17 00:00:00 2001
From: Joonwoo Park 
Date: Mon, 26 Oct 2015 16:37:47 -0700
Subject: [PATCH v2] sched: fix incorrect wait time and wait count statistics

At present scheduler resets task's wait start timestamp when the task
migrates to another rq.  This misleads scheduler itself into reporting
less wait time than actual by omitting time spent for waiting prior to
migration and also more wait count than actual by counting migration as
wait end event which can be seen by trace or /proc//sched with
CONFIG_SCHEDSTATS=y.

Carry forward migrating task's wait time prior to migration and
don't count migration as a wait end event to fix such statistics error.

In order to determine whether task is migrating mark task->on_rq with
TASK_ON_RQ_MIGRATING while dequeuing and enqueuing due to migration.

To: Ingo Molnar 
To: Peter Zijlstra 
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Joonwoo Park 
---
Changes in v2: 
 * Set p->on_rq = TASK_ON_RQ_MIGRATING while doing migration dequeue/enqueue
   and check whether task's migrating with task_on_rq_migrating().

 kernel/sched/core.c |  4 ++--
 kernel/sched/fair.c | 17 ++---
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index bcd214e..d9e4ad5 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1069,8 +1069,8 @@ static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int new
 {
 	lockdep_assert_held(>lock);
 
-	dequeue_task(rq, p, 0);
 	p->on_rq = TASK_ON_RQ_MIGRATING;
+	dequeue_task(rq, p, 0);
 	set_task_cpu(p, new_cpu);
 	raw_spin_unlock(>lock);
 
@@ -1078,8 +1078,8 @@ static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int new
 
 	raw_spin_lock(>lock);
 	BUG_ON(task_cpu(p) != new_cpu);
-	p->on_rq = TASK_ON_RQ_QUEUED;
 	enqueue_task(rq, p, 0);
+	p->on_rq = TASK_ON_RQ_QUEUED;
 	check_preempt_curr(rq, p, 0);
 
 	return rq;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 9a5e60f..7609576 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -740,7 +740,11 @@ static void update_curr_fair(struct rq *rq)
 static inline void
 update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
-	schedstat_set(se->statistics.wait_start, rq_clock(rq_of(cfs_rq)));
+	schedstat_set(se->statistics.wait_start,
+		task_on_rq_migrating(task_of(se)) &&
+		likely(rq_clock(rq_of(cfs_rq)) > se->statistics.wait_start) ?
+		rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start :
+		rq_clock(rq_of(cfs_rq)));
 }
 
 /*
@@ -759,6 +763,13 @@ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
 static void
 update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
+	if (task_on_rq_migrating(task_of(se))) {
+		schedstat_set(se->statistics.wait_start,
+			  rq_clock(rq_of(cfs_rq)) -
+			  se->statistics.wait_start);
+		return;
+	}
+
 	schedstat_set(se->statistics.wait_max, max(se->statistics.wait_max,
 			rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start));
 	schedstat_set(se->statistics.wait_count, se->statistics.wait_count + 1);
@@ -5656,8 +5667,8 @@ static void detach_task(struct task_struct *p, struct lb_env *env)
 {
 	lockdep_assert_held(>src_rq->lock);
 
-	deactivate_task(env->src_rq, p, 0);
 	p->on_rq = TASK_ON_RQ_MIGRATING;
+	deactivate_task(env->src_rq, p, 0);
 	set_task_cpu(p, env->dst_cpu);
 }
 
@@ -5790,8 +5801,8 @@ static void attach_task(struct rq *rq, struct task_struct *p)
 	lockdep_assert_held(>lock);
 
 	BUG_ON(task_rq(p) != rq);
-	p->on_rq = TASK_ON_RQ_QUEUED;
 	activate_task(rq, p, 0);
+	p->on_rq = TASK_ON_RQ_QUEUED;
 	

Re: [PATCH] clk: qcom: msm8960: Fix dsi1/2 halt bits

2015-10-26 Thread Archit Taneja



On 10/27/2015 06:53 AM, Stephen Boyd wrote:

The halt bits for these clocks seem wrong. I get the following
warning while booting on an msm8960-cdp:

WARNING: CPU: 0 PID: 1 at drivers/clk/qcom/clk-branch.c:97 
clk_branch_toggle+0xd0/0x138()
dsi1_clk status stuck at 'on'
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.3.0-rc3-00113-g5532cfb567fe #110
Hardware name: Qualcomm (Flattened Device Tree)
[] (unwind_backtrace) from [] (show_stack+0x10/0x14)
[] (show_stack) from [] (dump_stack+0x70/0xbc)
[] (dump_stack) from [] (warn_slowpath_common+0x78/0xb4)
[] (warn_slowpath_common) from [] 
(warn_slowpath_fmt+0x30/0x40)
[] (warn_slowpath_fmt) from [] 
(clk_branch_toggle+0xd0/0x138)
[] (clk_branch_toggle) from [] 
(clk_disable_unused_subtree+0x98/0x1b0)
[] (clk_disable_unused_subtree) from [] 
(clk_disable_unused_subtree+0x20/0x1b0)
[] (clk_disable_unused_subtree) from [] 
(clk_disable_unused+0x58/0xd8)
[] (clk_disable_unused) from [] (do_one_initcall+0xac/0x1ec)
[] (do_one_initcall) from [] 
(kernel_init_freeable+0x11c/0x1e8)
[] (kernel_init_freeable) from [] (kernel_init+0x8/0xec)
[] (kernel_init) from [] (ret_from_fork+0x14/0x3c)

Fix the status bits and the errors go away.

Fixes: 5532cfb567fe ("clk: qcom: mmcc-8960: Add DSI related clocks")
Cc: Archit Taneja 
Signed-off-by: Stephen Boyd 
---


Acked-by: Archit Taneja 

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum, hosted by The Linux Foundation

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 14/17] scsi: ufs: tune UniPro parameters to optimize hibern8 exit time

2015-10-26 Thread ygardi
> 2015-09-13 23:52 GMT+09:00 Yaniv Gardi :
>> Optimal values of local UniPro parameters like PA_Hibern8Time &
>> PA_TActivate can help reduce the hibern8 exit latency. If both host and
>> device supports UniPro ver1.6 or later, these parameters will be
>> automatically tuned during link startup itself. But if either host or
>> device doesn't support UniPro ver 1.6 or later, we have to manually
>> tune them. But to keep manual tuning logic simple, we will only do
>> manual tuning if local unipro version doesn't support ver1.6 or later.
>>
>> Signed-off-by: Subhash Jadavani 
>> Signed-off-by: Yaniv Gardi 
>>
>> ---
>>  drivers/scsi/ufs/ufshcd.c | 121
>> ++
>>  drivers/scsi/ufs/ufshcd.h |   1 +
>>  drivers/scsi/ufs/ufshci.h |   2 +
>>  drivers/scsi/ufs/unipro.h |  21 
>>  4 files changed, 145 insertions(+)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index a8659a9..0938d6c 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -596,6 +596,34 @@ static inline int ufshcd_is_hba_active(struct
>> ufs_hba *hba)
>> return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
>>  }
>>
>> +u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba)
>> +{
>> +   /* HCI version 1.0 and 1.1 supports UniPro 1.41 */
>> +   if ((hba->ufs_version == UFSHCI_VERSION_10) ||
>> +   (hba->ufs_version == UFSHCI_VERSION_11))
>> +   return UFS_UNIPRO_VER_1_41;
>> +   else
>> +   return UFS_UNIPRO_VER_1_6;
>> +}
>> +EXPORT_SYMBOL(ufshcd_get_local_unipro_ver);
>> +
>> +static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba)
>> +{
>> +   /*
>> +* If both host and device support UniPro ver1.6 or later, PA
>> layer
>> +* parameters tuning happens during link startup itself.
>> +*
>> +* We can manually tune PA layer parameters if either host or
>> device
>> +* doesn't support UniPro ver 1.6 or later. But to keep manual
>> tuning
>> +* logic simple, we will only do manual tuning if local unipro
>> version
>> +* doesn't support ver1.6 or later.
>> +*/
>> +   if (ufshcd_get_local_unipro_ver(hba) < UFS_UNIPRO_VER_1_6)
>> +   return true;
>> +   else
>> +   return false;
>> +}
>> +
>>  static void ufshcd_ungate_work(struct work_struct *work)
>>  {
>> int ret;
>> @@ -4826,6 +4854,98 @@ out:
>>  }
>>
>>  /**
>> + * ufshcd_tune_pa_tactivate - Tunes PA_TActivate of local UniPro
>> + * @hba: per-adapter instance
>> + *
>> + * PA_TActivate parameter can be tuned manually if UniPro version is
>> less than
>> + * 1.61. PA_TActivate needs to be greater than or equal to peerM-PHY's
>> + * RX_MIN_ACTIVATETIME_CAPABILITY attribute. This optimal value can
>> help reduce
>> + * the hibern8 exit latency.
>> + *
>> + * Returns zero on success, non-zero error value on failure.
>> + */
>> +static int ufshcd_tune_pa_tactivate(struct ufs_hba *hba)
>> +{
>> +   int ret = 0;
>> +   u32 peer_rx_min_activatetime = 0, tuned_pa_tactivate;
>> +
>> +   if (!ufshcd_is_unipro_pa_params_tuning_req(hba))
>> +   return 0;
>
> This ufshcd_tune_pa_tactivate() is called only when
> ufshcd_is_unipro_pa_params_tuning_req() returns true.  Is this
> second check needed?
>


i could think of having this second check for any future call to
ufshcd_tune_pa_tactivate() which is not protected with a wrapping check
like in this case.
but i guess every call to ufshcd_tune_pa_tactivate()
will use ufshcd_tune_unipro_params() so we are good.
i will remove the 2nd check






--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 06/17] scsi :ufs: verify hba controller hce reg value

2015-10-26 Thread ygardi
> 2015-09-13 23:52 GMT+09:00 Yaniv Gardi :
>> Sometimes due to hw issues it takes some time to the
>> host controller register to update. In order to verify the register
>> has updated, a polling is done until its value is set.
>>
>> In addition the functions ufshcd_hba_stop() and
>> ufshcd_wait_for_register() was updated with an additional input
>> parameter, indicating the timeout between reads will
>> be done by sleeping or spinning the cpu.
>>
>> Signed-off-by: Raviv Shvili 
>> Signed-off-by: Yaniv Gardi 
>>
>> ---
>>  drivers/scsi/ufs/ufshcd.c | 54
>> ---
>>  drivers/scsi/ufs/ufshcd.h | 12 +++
>>  2 files changed, 35 insertions(+), 31 deletions(-)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 6171da8..e5a876c 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -267,11 +267,12 @@ static inline void ufshcd_disable_irq(struct
>> ufs_hba *hba)
>>   * @val - wait condition
>>   * @interval_us - polling interval in microsecs
>>   * @timeout_ms - timeout in millisecs
>> - *
>> + * @can_sleep - perform sleep or just spin
>>   * Returns -ETIMEDOUT on error, zero on success
>>   */
>
> We usually put a blank line between @argument description and
> return value description.
>

will be fixed in v2.
thanks


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 07/17] scsi: ufs: separate device and host quirks

2015-10-26 Thread ygardi
> 2015-09-13 23:52 GMT+09:00 Yaniv Gardi :
>
>> diff --git a/drivers/scsi/ufs/ufs_quirks.c
>> b/drivers/scsi/ufs/ufs_quirks.c
>> new file mode 100644
>> index 000..b649bbf
>> --- /dev/null
>> +++ b/drivers/scsi/ufs/ufs_quirks.c
>> @@ -0,0 +1,101 @@
>> +/*
>> + * Copyright (c) 2013-2015, The 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 "ufshcd.h"
>> +#include "ufs_quirks.h"
>> +
>> +
>
> Single blank line is enough.

done

>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index e5a876c..0803a89 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -39,9 +39,10 @@
>>
>>  #include 
>>  #include 
>> -
>> +#include 
>>  #include 
>>  #include "ufshcd.h"
>> +#include "ufs_quirks.h"
>>  #include "unipro.h"
>>  #define UFSHCD_REQ_SENSE_SIZE  18
>>
>> @@ -259,6 +260,16 @@ static inline void ufshcd_disable_irq(struct
>> ufs_hba *hba)
>> }
>>  }
>>
>> +/* replace non-printable or non-ASCII characters with spaces */
>> +static inline void ufshcd_remove_non_printable(char *val)
>> +{
>> +   if (!val)
>> +   return;
>> +
>> +   if (*val < 0x20 || *val > 0x7e)
>> +   *val = ' ';
>> +}
>> +
>>  /*
>>   * ufshcd_wait_for_register - wait for register value to change
>>   * @hba - per-adapter interface
>> @@ -2052,6 +2063,82 @@ static inline int ufshcd_read_power_desc(struct
>> ufs_hba *hba,
>> return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf,
>> size);
>>  }
>>
>> +int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
>> +{
>> +   return ufshcd_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, buf,
>> size);
>> +}
>> +EXPORT_SYMBOL(ufshcd_read_device_desc);
>> +
>> +/**
>> + * ufshcd_read_string_desc - read string descriptor
>> + * @hba: pointer to adapter instance
>> + * @desc_index: descriptor index
>> + * @buf: pointer to buffer where descriptor would be read
>> + * @size: size of buf
>> + * @ascii: if true convert from unicode to ascii characters
>> + *
>> + * Return 0 in case of success, non-zero otherwise
>> + */
>> +int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8
>> *buf,
>> +   u32 size, bool ascii)
>> +{
>> +   int err = 0;
>> +
>> +   err = ufshcd_read_desc(hba,
>> +   QUERY_DESC_IDN_STRING, desc_index, buf,
>> size);
>> +
>> +   if (err) {
>> +   dev_err(hba->dev, "%s: reading String Desc failed after
>> %d retries. err = %d\n",
>> +   __func__, QUERY_REQ_RETRIES, err);
>> +   goto out;
>> +   }
>
> I actually tried this patch and ufshcd_read_desc() always returns
> -EINVAL due to the following check in the end of ufshcd_read_desc().
>
> if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) ||
> (desc_buf[QUERY_DESC_LENGTH_OFFSET] !=
>  ufs_query_desc_max_size[desc_id])
> || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) {
> ...
> if (!ret)
> ret = -EINVAL;
>
> Could you also include a fix fir ufshcd_read_desc()?

i'm not sure i understand what should be fixed.
if the check you mentioned implies that something is wrong,
we shouldn't ignore the error. otherwise we might exceed the buf
boundaries for example.
can you elaborate what is that you think we should fix ?





> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 05/15] scsi: ufs: increase fDeviceInit query response timeout

2015-10-26 Thread Akinobu Mita
2015-10-25 22:38 GMT+09:00  :
>> 2015-09-02 19:13 GMT+09:00 Yaniv Gardi :
>>> fDeviceInit query response time for some devices is too long that
>>> default
>>> query request timeout of 100ms may not be enough. Experiments show that
>>> fDeviceInit response sometimes takes 500ms so to be on safer side this
>>> change sets the timeout to 600ms. Without this change, we might
>>> unnecessarily have to retry fDeviceInit query requests multiple times
>>> and
>>> each query request timeout prints one error message.
>>>
>>> Signed-off-by: Subhash Jadavani 
>>> Signed-off-by: Yaniv Gardi 
>>>
>>> ---
>>>  drivers/scsi/ufs/ufshcd.c | 12 +++-
>>>  1 file changed, 11 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>>> index e0b8755..573a8cb 100644
>>> --- a/drivers/scsi/ufs/ufshcd.c
>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>> @@ -58,6 +58,12 @@
>>>  #define QUERY_REQ_RETRIES 10
>>>  /* Query request timeout */
>>>  #define QUERY_REQ_TIMEOUT 30 /* msec */
>>> +/*
>>> + * Query request timeout for fDeviceInit flag
>>> + * fDeviceInit query response time for some devices is too large that
>>> default
>>> + * QUERY_REQ_TIMEOUT may not be enough for such devices.
>>> + */
>>> +#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */
>>
>> How about just increasing QUERY_REQ_TIMEOUT from 30ms to 600ms
>> instead of conditionally setting timeout depending on ufs flag?
>
> Your suggestion obviously could work (increasing the QUERY_REQ_TIMEOUT to
> 600ms), but in that case we bring extra delay of 570ms to error handling
> of query timeout, and in such a case, instead of handling the error after
> 30ms we handle it after 600ms, which make the SW hang.
> does it make sense ?

Compared to default scsi disk timeout (30s), 600ms does not look very
long.  I was just worried that the code gets complicated if we need to
add yet another QUERY_XYZ_REQ_TIMEOUT macros when it turns out that
30ms timeout is not enough for other query requests under specific
conditions.  But I don't too much care about it for now.

>>
>>>
>>>  /* Task management command timeout */
>>>  #define TM_CMD_TIMEOUT 100 /* msecs */
>>> @@ -1651,6 +1657,7 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
>>> enum query_opcode opcode,
>>> struct ufs_query_req *request = NULL;
>>> struct ufs_query_res *response = NULL;
>>> int err, index = 0, selector = 0;
>>> +   int timeout = QUERY_REQ_TIMEOUT;
>>>
>>> BUG_ON(!hba);
>>>
>>> @@ -1683,7 +1690,10 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
>>> enum query_opcode opcode,
>>> goto out_unlock;
>>> }
>>>
>>> -   err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
>>> QUERY_REQ_TIMEOUT);
>>> +   if (idn == QUERY_FLAG_IDN_FDEVICEINIT)
>>> +   timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT;
>>> +
>>> +   err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
>>>
>>> if (err) {
>>> dev_err(hba->dev,
>>> --
>>> 1.8.5.2
>>>
>>> --
>>> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a
>>> member of Code Aurora Forum, hosted by The Linux Foundation
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>>> the body of a message to majord...@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 02/17] scsi: ufs: add option to change default UFS power management level

2015-10-26 Thread ygardi
> 2015-09-13 23:52 GMT+09:00 Yaniv Gardi :
>> UFS device and link can be put in multiple different low power modes
>> hence UFS driver supports multiple different low power modes.
>> By default UFS driver selects the default (optimal) low power mode
>> (which gives moderate power savings and have relatively less enter
>> and exit latencies) but we might have to tune this default power
>> mode for different chipset platforms to meet the low power
>> requirements/goals. Hence this patch adds option to change default
>> UFS low power mode (level).
>>
>> Signed-off-by: Subhash Jadavani 
>> Signed-off-by: Yaniv Gardi 
>
> ...
>
>> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
>> index 3196197..1d26e49 100644
>> --- a/drivers/scsi/ufs/ufs-qcom.c
>> +++ b/drivers/scsi/ufs/ufs-qcom.c
>> @@ -1195,11 +1195,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
>> if (res) {
>> host->dev_ref_clk_ctrl_mmio =
>> devm_ioremap_resource(dev, res);
>> -   if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) {
>> -   dev_warn(dev,
>> -   "%s: could not map
>> dev_ref_clk_ctrl_mmio, err %ld\n",
>> +   if (IS_ERR((__force void const *)
>> +  host->dev_ref_clk_ctrl_mmio)) {
>> +   dev_warn(dev, "%s: could not map
>> dev_ref_clk_ctrl_mmio, err %ld\n",
>> __func__,
>> -
>> PTR_ERR(host->dev_ref_clk_ctrl_mmio));
>> +   PTR_ERR((__force void const *)
>> +
>> host->dev_ref_clk_ctrl_mmio));
>> host->dev_ref_clk_ctrl_mmio = NULL;
>> }
>> host->dev_ref_clk_en_mask = BIT(5);
>
> This change looks unrelated.  Should this be belong to other patch?
>

correct, it's minor change,
but i will separate it to a different patch.



--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 13/15] scsi: ufs: add missing memory barriers

2015-10-26 Thread Akinobu Mita
2015-10-25 23:40 GMT+09:00  :
>> 2015-09-02 19:13 GMT+09:00 Yaniv Gardi :
>>> Performing several writes to UFS host controller registers has
>>> no gurrantee of ordering, so we must make sure register writes
>>> to setup request list base address etc. are performed before the
>>> run/stop register is enabled.
>>> In addition, when setting up a task request, we must make sure
>>> the updating of descriptors takes places before ringing the
>>> doorbell, similarly to setting up a transfer request.
>>>
>>> Signed-off-by: Gilad Broner 
>>> Signed-off-by: Yaniv Gardi 
>>>
>>> ---
>>>  drivers/scsi/ufs/ufshcd.c | 21 +++--
>>>  1 file changed, 15 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>>> index fc2a52d..298511a 100644
>>> --- a/drivers/scsi/ufs/ufshcd.c
>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>> @@ -401,11 +401,9 @@ static inline int ufshcd_get_lists_status(u32 reg)
>>>  *  1   UTRLRDY
>>>  *  2   UTMRLRDY
>>>  *  3   UCRDY
>>> -*  4   HEI
>>> -*  5   DEI
>>> -* 6-7  reserved
>>> +* 4-7  reserved
>>>  */
>>> -   return (((reg) & (0xFF)) >> 1) ^ (0x07);
>>> +   return ((reg & 0xFF) >> 1) ^ 0x07;
>>>  }
>>>
>>>  /**
>>> @@ -2726,7 +2724,7 @@ out:
>>>   * To bring UFS host controller to operational state,
>>>   * 1. Enable required interrupts
>>>   * 2. Configure interrupt aggregation
>>> - * 3. Program UTRL and UTMRL base addres
>>> + * 3. Program UTRL and UTMRL base address
>>>   * 4. Configure run-stop-registers
>>>   *
>>>   * Returns 0 on success, non-zero value on failure
>>> @@ -2756,8 +2754,13 @@ static int ufshcd_make_hba_operational(struct
>>> ufs_hba *hba)
>>> REG_UTP_TASK_REQ_LIST_BASE_H);
>>>
>>> /*
>>> +* Make sure base address and interrupt setup are updated before
>>> +* enabling the run/stop registers below.
>>> +*/
>>> +   wmb();
>>> +
>>> +   /*
>>>  * UCRDY, UTMRLDY and UTRLRDY bits must be 1
>>> -* DEI, HEI bits must be 0
>>>  */
>>> reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
>>> if (!(ufshcd_get_lists_status(reg))) {
>>> @@ -3920,7 +3923,13 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba
>>> *hba, int lun_id, int task_id,
>>>
>>> /* send command to the controller */
>>> __set_bit(free_slot, >outstanding_tasks);
>>> +
>>> +   /* Make sure descriptors are ready before ringing the task
>>> doorbell */
>>> +   wmb();
>>> +
>>> ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
>>> +   /* Make sure that doorbell is committed immediately */
>>> +   wmb();
>>
>> Is this wmb() after ringing tm doorbell is needed?
>
> Well, Mita, in the case of DB register (Request DB and TASK DB), every
> write operation to the DB should be barrier, as if not, out of order
> writing to this register might cause inconsistency in its value, and thus,
> un-handled requests/tasks.

I couldn't fully understand why out of order writing to TASK DB
register causes inconsistency.
In the TASK request completion (ufshcd_tmc_handler), TASK DB register
is read before handling finished requests, so it ensures that all
write operations for TASK DB have been performed.

>>
>>>
>>> spin_unlock_irqrestore(host->host_lock, flags);
>>>
>>> --
>>> 1.8.5.2
>>>
>>> --
>>> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a
>>> member of Code Aurora Forum, hosted by The Linux Foundation
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>>> the body of a message to majord...@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 08/17] scsi: ufs: split broken LCC quirk

2015-10-26 Thread ygardi
> 2015-09-13 23:52 GMT+09:00 Yaniv Gardi :
>> Currently when UFSHCD_BROKEN_LCC quirk is defined, LCC is getting
>> disabled on both host and device side but there could be a need
>> where we don't want to disable the LCC on both side hence this change
>> splits the quirk in 2 parts one for host and one for device.
>>
>> Signed-off-by: Subhash Jadavani 
>> Signed-off-by: Yaniv Gardi 
>>
>> ---
>>  drivers/scsi/ufs/ufshcd.c | 11 +++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 0803a89..411ec17 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -3048,6 +3048,11 @@ static int ufshcd_disable_tx_lcc(struct ufs_hba
>> *hba, bool peer)
>> return err;
>>  }
>>
>> +static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba)
>> +{
>> +   return ufshcd_disable_tx_lcc(hba, false);
>> +}
>> +
>>  static inline int ufshcd_disable_device_tx_lcc(struct ufs_hba *hba)
>>  {
>> return ufshcd_disable_tx_lcc(hba, true);
>> @@ -3095,6 +3100,12 @@ static int ufshcd_link_startup(struct ufs_hba
>> *hba)
>> goto out;
>> }
>>
>> +   if (hba->dev_quirks & UFS_DEVICE_QUIRK_BROKEN_LCC) {
>> +   ret = ufshcd_disable_host_tx_lcc(hba);
>> +   if (ret)
>> +   goto out;
>> +   }
>> +
>
> This dev_quirks is checked just after link startup.  But dev_quirk is
> determined after ufshcd_complete_dev_init().  Is this quirk correctly
> be applied?

good comment :)
since there is no need in this quirk anymore (it is never set),
luckily we can totally remove the quirk.
i will remove this patch totally in v2



>
>> /* Include any host controller configuration via UIC commands */
>> ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
>> if (ret)
>> --
>> 1.8.5.2
>>
>> --
>> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a
>> member of Code Aurora Forum, hosted by The Linux Foundation
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 12/17] scsi: ufs: add retry for query descriptors

2015-10-26 Thread ygardi
> 2015-09-13 23:52 GMT+09:00 Yaniv Gardi :
>> Query commands have 100ms timeout and it may timeout if they are
>> issued in parallel to ongoing read/write SCSI commands, this change
>> adds the retry (max: 10) in case command timeouts.
>>
>> Signed-off-by: Subhash Jadavani 
>> Signed-off-by: Yaniv Gardi 
>>
>> ---
>>  drivers/scsi/ufs/ufshcd.c | 48
>> ---
>>  1 file changed, 33 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index a649250..528e46e 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -1906,21 +1906,7 @@ static int ufshcd_query_attr_retry(struct ufs_hba
>> *hba,
>> return ret;
>>  }
>>
>> -/**
>> - * ufshcd_query_descriptor - API function for sending descriptor
>> requests
>> - * hba: per-adapter instance
>> - * opcode: attribute opcode
>> - * idn: attribute idn to access
>> - * index: index field
>> - * selector: selector field
>> - * desc_buf: the buffer that contains the descriptor
>> - * buf_len: length parameter passed to the device
>> - *
>> - * Returns 0 for success, non-zero in case of failure.
>> - * The buf_len parameter will contain, on return, the length parameter
>> - * received on the response.
>> - */
>> -static int ufshcd_query_descriptor(struct ufs_hba *hba,
>> +static int __ufshcd_query_descriptor(struct ufs_hba *hba,
>> enum query_opcode opcode, enum desc_idn idn, u8
>> index,
>> u8 selector, u8 *desc_buf, int *buf_len)
>>  {
>> @@ -1985,6 +1971,38 @@ out:
>>  }
>>
>>  /**
>> + * ufshcd_query_descriptor - API function for sending descriptor
>> requests
>> + * hba: per-adapter instance
>> + * opcode: attribute opcode
>> + * idn: attribute idn to access
>> + * index: index field
>> + * selector: selector field
>> + * desc_buf: the buffer that contains the descriptor
>> + * buf_len: length parameter passed to the device
>> + *
>> + * Returns 0 for success, non-zero in case of failure.
>> + * The buf_len parameter will contain, on return, the length parameter
>> + * received on the response.
>> + */
>> +int ufshcd_query_descriptor(struct ufs_hba *hba,
>> +   enum query_opcode opcode, enum desc_idn idn, u8
>> index,
>> +   u8 selector, u8 *desc_buf, int *buf_len)
>> +{
>> +   int err;
>> +   int retries;
>> +
>> +   for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
>> +   err = __ufshcd_query_descriptor(hba, opcode, idn, index,
>> +   selector, desc_buf,
>> buf_len);
>> +   if (!err || err == -EINVAL)
>> +   break;
>> +   }
>> +
>> +   return err;
>> +}
>> +EXPORT_SYMBOL(ufshcd_query_descriptor);
>
> You introduced query flag and attribute APIs for retry version with
> '_retry' suffix.
> This function retries but doesn't have '_retry' suffix.
> Should we have consistent function names for these query APIs?
>

sure. will fix this in v2

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 17/17] scsi: ufs-qcom: fix compilation warnings

2015-10-26 Thread Yaniv Gardi
Tnis patch fixes the following compilation warnings:
...ufs-qcom.c:1201:40:
warning: incorrect type in argument 1 (different address spaces)
...ufs-qcom.c:1201:40:
expected void const *ptr
...ufs-qcom.c:1201:40:
got void [noderef] *dev_ref_clk_ctrl_mmio
...ufs-qcom.c:1207:53:
warning: incorrect type in argument 1 (different address spaces)
...ufs-qcom.c:1207:53:
expected void const *ptr
...ufs-qcom.c:1207:53:
got void [noderef] *dev_ref_clk_ctrl_mmio

Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufs-qcom.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 72b0ef7..b57f88a 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1226,11 +1226,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
if (res) {
host->dev_ref_clk_ctrl_mmio =
devm_ioremap_resource(dev, res);
-   if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) {
-   dev_warn(dev,
-   "%s: could not map 
dev_ref_clk_ctrl_mmio, err %ld\n",
+   if (IS_ERR((__force void const *)
+  host->dev_ref_clk_ctrl_mmio)) {
+   dev_warn(dev, "%s: could not map 
dev_ref_clk_ctrl_mmio, err %ld\n",
__func__,
-   PTR_ERR(host->dev_ref_clk_ctrl_mmio));
+   PTR_ERR((__force void const *)
+host->dev_ref_clk_ctrl_mmio));
host->dev_ref_clk_ctrl_mmio = NULL;
}
host->dev_ref_clk_en_mask = BIT(5);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 16/17] scsi: ufs-qcom: set PA_Local_TX_LCC_Enable before link startup

2015-10-26 Thread Yaniv Gardi
Some UFS devices (and may be host) have issues if LCC is
enabled. So we are setting PA_Local_TX_LCC_Enable to 0
before link startup which will make sure that both host
and device TX LCC are disabled once link startup is
completed.

This change also:
- enables the device ref clock before changing to HS mode
  and disables it if entered to PWM mode
- adds printouts of testbus debug registers

Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufs-qcom.c | 116 +---
 drivers/scsi/ufs/ufs-qcom.h |   9 
 drivers/scsi/ufs/ufshcd.h   |   9 
 drivers/scsi/ufs/unipro.h   |   1 +
 4 files changed, 128 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index c470c40..72b0ef7 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -16,8 +16,8 @@
 #include 
 #include 
 #include 
-
 #include 
+
 #include "ufshcd.h"
 #include "ufshcd-pltfrm.h"
 #include "unipro.h"
@@ -58,6 +58,12 @@ static void ufs_qcom_dump_regs(struct ufs_hba *hba, int 
offset, int len,
len * 4, false);
 }
 
+static void ufs_qcom_dump_regs_wrapper(struct ufs_hba *hba, int offset, int 
len,
+   char *prefix, void *priv)
+{
+   ufs_qcom_dump_regs(hba, offset, len, prefix);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -106,9 +112,11 @@ static void ufs_qcom_disable_lane_clks(struct 
ufs_qcom_host *host)
if (!host->is_lane_clks_enabled)
return;
 
-   clk_disable_unprepare(host->tx_l1_sync_clk);
+   if (host->hba->lanes_per_direction > 1)
+   clk_disable_unprepare(host->tx_l1_sync_clk);
clk_disable_unprepare(host->tx_l0_sync_clk);
-   clk_disable_unprepare(host->rx_l1_sync_clk);
+   if (host->hba->lanes_per_direction > 1)
+   clk_disable_unprepare(host->rx_l1_sync_clk);
clk_disable_unprepare(host->rx_l0_sync_clk);
 
host->is_lane_clks_enabled = false;
@@ -271,9 +279,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
 
if (ret) {
-   dev_err(hba->dev,
-   "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
-   __func__, ret);
+   dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret 
= %d\n",
+   __func__, ret);
goto out;
}
 
@@ -523,6 +530,18 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba 
*hba,
err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba,
  150);
 
+   /*
+* Some UFS devices (and may be host) have issues if LCC is
+* enabled. So we are setting PA_Local_TX_LCC_Enable to 0
+* before link startup which will make sure that both host
+* and device TX LCC are disabled once link startup is
+* completed.
+*/
+   if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41)
+   err = ufshcd_dme_set(hba,
+   UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE),
+   0);
+
break;
case POST_CHANGE:
ufs_qcom_link_startup_post_change(hba);
@@ -966,6 +985,10 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
goto out;
}
 
+   /* enable the device ref clock before changing to HS mode */
+   if (!ufshcd_is_hs_mode(>pwr_info) &&
+   ufshcd_is_hs_mode(dev_req_params))
+   ufs_qcom_dev_ref_clk_ctrl(host, true);
break;
case POST_CHANGE:
if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
@@ -993,6 +1016,11 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
memcpy(>dev_req_params,
dev_req_params, sizeof(*dev_req_params));
ufs_qcom_update_bus_bw_vote(host);
+
+   /* disable the device ref clock if entered PWM mode */
+   if (ufshcd_is_hs_mode(>pwr_info) &&
+   !ufshcd_is_hs_mode(dev_req_params))
+   ufs_qcom_dev_ref_clk_ctrl(host, false);
break;
default:
ret = -EINVAL;
@@ -1094,6 +1122,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, 
bool on)
ufs_qcom_phy_disable_iface_clk(host->generic_phy);
goto out;
}
+   /* enable the device ref clock for HS mode*/
+   if (ufshcd_is_hs_mode(>pwr_info))
+   ufs_qcom_dev_ref_clk_ctrl(host, true);
vote = 

[PATCH v2 04/17] scsi: ufs: avoid spurious UFS host controller interrupts

2015-10-26 Thread Yaniv Gardi
When control reaches to Linux UFS driver during UFS boot mode, UFS host
controller interrupt status/enable registers may have left over
settings.
In order to avoid any spurious interrupts due to these left overs,
it's important to clear these interrupt status/enable registers before
enabling UFS interrupt handling.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 00964f9..a0aac38 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5864,6 +5864,21 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
init_waitqueue_head(>dev_cmd.tag_wq);
 
ufshcd_init_clk_gating(hba);
+
+   /*
+* In order to avoid any spurious interrupt immediately after
+* registering UFS controller interrupt handler, clear any pending UFS
+* interrupt status and disable all the UFS interrupts.
+*/
+   ufshcd_writel(hba, ufshcd_readl(hba, REG_INTERRUPT_STATUS),
+ REG_INTERRUPT_STATUS);
+   ufshcd_writel(hba, 0, REG_INTERRUPT_ENABLE);
+   /*
+* Make sure that UFS interrupts are disabled and any pending interrupt
+* status is cleared before registering UFS interrupt handler.
+*/
+   mb();
+
/* IRQ registration */
err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
if (err) {
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/17] scsi: ufs: add option to change default UFS power management level

2015-10-26 Thread Yaniv Gardi
UFS device and link can be put in multiple different low power modes
hence UFS driver supports multiple different low power modes.
By default UFS driver selects the default (optimal) low power mode
(which gives moderate power savings and have relatively less enter
and exit latencies) but we might have to tune this default power
mode for different chipset platforms to meet the low power
requirements/goals. Hence this patch adds option to change default
UFS low power mode (level).

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  |  8 +
 drivers/scsi/ufs/ufshcd-pltfrm.c   | 17 +-
 drivers/scsi/ufs/ufshcd.c  | 39 ++
 drivers/scsi/ufs/ufshcd.h  |  4 +--
 4 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt 
b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
index 9fea0de..b7db1c9 100644
--- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
+++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
@@ -38,6 +38,14 @@ Optional properties:
  defined or a value in the array is "0" then it is 
assumed
  that the frequency is set by the parent clock or a
  fixed rate clock source.
+- rpm-level: UFS Runtime power management level. Following PM 
levels are supported:
+ 0 - Both UFS device and Link in active state (Highest 
power consumption)
+ 1 - UFS device in active state but Link in Hibern8 
state
+ 2 - UFS device in Sleep state but Link in active state
+ 3 - UFS device in Sleep state and Link in hibern8 
state (default PM level)
+ 4 - UFS device in Power-down state and Link in 
Hibern8 state
+ 5 - UFS device in Power-down state and Link in OFF 
state (Lowest power consumption)
+- spm-level: UFS System power management level. Allowed PM levels 
are same as rpm-level.
 - lanes-per-direction: number of lanes available per direction - either 1 or 2.
Note that it is assume same number of lanes is used 
both directions at once.
If not specified, default is 2 lanes per direction.
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 5be0c91..1130dd9 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -226,7 +226,20 @@ out:
return err;
 }
 
-#ifdef CONFIG_PM
+static void ufshcd_parse_pm_levels(struct ufs_hba *hba)
+{
+   struct device *dev = hba->dev;
+   struct device_node *np = dev->of_node;
+
+   if (np) {
+   if (of_property_read_u32(np, "rpm-level", >rpm_lvl))
+   hba->rpm_lvl = -1;
+   if (of_property_read_u32(np, "spm-level", >spm_lvl))
+   hba->spm_lvl = -1;
+   }
+}
+
+#ifdef CONFIG_SMP
 /**
  * ufshcd_pltfrm_suspend - suspend power management function
  * @dev: pointer to device handle
@@ -345,6 +358,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
goto dealloc_host;
}
 
+   ufshcd_parse_pm_levels(hba);
+
pm_runtime_set_active(>dev);
pm_runtime_enable(>dev);
 
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8d16aca..20c5b5d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -187,6 +187,30 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl)
return ufs_pm_lvl_states[lvl].link_state;
 }
 
+static inline enum ufs_pm_level
+ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
+   enum uic_link_state link_state)
+{
+   enum ufs_pm_level lvl;
+
+   for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) {
+   if ((ufs_pm_lvl_states[lvl].dev_state == dev_state) &&
+   (ufs_pm_lvl_states[lvl].link_state == link_state))
+   return lvl;
+   }
+
+   /* if no match found, return the level 0 */
+   return UFS_PM_LVL_0;
+}
+
+static inline bool ufshcd_is_valid_pm_lvl(int lvl)
+{
+   if (lvl >= 0 && lvl < ARRAY_SIZE(ufs_pm_lvl_states))
+   return true;
+   else
+   return false;
+}
+
 static void ufshcd_tmc_handler(struct ufs_hba *hba);
 static void ufshcd_async_scan(void *data, async_cookie_t cookie);
 static int ufshcd_reset_and_restore(struct ufs_hba *hba);
@@ -5885,6 +5909,21 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
hba->clk_scaling.window_start_t = 0;
}
 
+   /*
+* If rpm_lvl and and spm_lvl are not already set to valid levels,
+* set 

[PATCH v2 06/17] scsi :ufs: verify hba controller hce reg value

2015-10-26 Thread Yaniv Gardi
Sometimes due to hw issues it takes some time to the
host controller register to update. In order to verify the register
has updated, a polling is done until its value is set.

In addition the functions ufshcd_hba_stop() and
ufshcd_wait_for_register() was updated with an additional input
parameter, indicating the timeout between reads will
be done by sleeping or spinning the cpu.

Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 53 ---
 drivers/scsi/ufs/ufshcd.h | 12 +++
 2 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3aea64b..e8e7530 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -266,11 +266,13 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
  * @val - wait condition
  * @interval_us - polling interval in microsecs
  * @timeout_ms - timeout in millisecs
+ * @can_sleep - perform sleep or just spin
  *
  * Returns -ETIMEDOUT on error, zero on success
  */
-static int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
-   u32 val, unsigned long interval_us, unsigned long timeout_ms)
+int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
+   u32 val, unsigned long interval_us,
+   unsigned long timeout_ms, bool can_sleep)
 {
int err = 0;
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
@@ -279,9 +281,10 @@ static int ufshcd_wait_for_register(struct ufs_hba *hba, 
u32 reg, u32 mask,
val = val & mask;
 
while ((ufshcd_readl(hba, reg) & mask) != val) {
-   /* wakeup within 50us of expiry */
-   usleep_range(interval_us, interval_us + 50);
-
+   if (can_sleep)
+   usleep_range(interval_us, interval_us + 50);
+   else
+   udelay(interval_us);
if (time_after(jiffies, timeout)) {
if ((ufshcd_readl(hba, reg) & mask) != val)
err = -ETIMEDOUT;
@@ -1486,7 +1489,7 @@ ufshcd_clear_cmd(struct ufs_hba *hba, int tag)
 */
err = ufshcd_wait_for_register(hba,
REG_UTP_TRANSFER_REQ_DOOR_BELL,
-   mask, ~mask, 1000, 1000);
+   mask, ~mask, 1000, 1000, true);
 
return err;
 }
@@ -2842,6 +2845,23 @@ out:
 }
 
 /**
+ * ufshcd_hba_stop - Send controller to reset state
+ * @hba: per adapter instance
+ * @can_sleep: perform sleep or just spin
+ */
+static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep)
+{
+   int err;
+
+   ufshcd_writel(hba, CONTROLLER_DISABLE,  REG_CONTROLLER_ENABLE);
+   err = ufshcd_wait_for_register(hba, REG_CONTROLLER_ENABLE,
+   CONTROLLER_ENABLE, CONTROLLER_DISABLE,
+   10, 1, can_sleep);
+   if (err)
+   dev_err(hba->dev, "%s: Controller disable failed\n", __func__);
+}
+
+/**
  * ufshcd_hba_enable - initialize the controller
  * @hba: per adapter instance
  *
@@ -2861,18 +2881,9 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
 * development and testing of this driver. msleep can be changed to
 * mdelay and retry count can be reduced based on the controller.
 */
-   if (!ufshcd_is_hba_active(hba)) {
-
+   if (!ufshcd_is_hba_active(hba))
/* change controller state to "reset state" */
-   ufshcd_hba_stop(hba);
-
-   /*
-* This delay is based on the testing done with UFS host
-* controller FPGA. The delay can be changed based on the
-* host controller used.
-*/
-   msleep(5);
-   }
+   ufshcd_hba_stop(hba, true);
 
/* UniPro link is disabled at this point */
ufshcd_set_link_off(hba);
@@ -3925,7 +3936,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
/* poll for max. 1 sec to clear door bell register by h/w */
err = ufshcd_wait_for_register(hba,
REG_UTP_TASK_REQ_DOOR_BELL,
-   mask, 0, 1000, 1000);
+   mask, 0, 1000, 1000, true);
 out:
return err;
 }
@@ -4209,7 +4220,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba 
*hba)
 
/* Reset the host controller */
spin_lock_irqsave(hba->host->host_lock, flags);
-   ufshcd_hba_stop(hba);
+   ufshcd_hba_stop(hba, false);
spin_unlock_irqrestore(hba->host->host_lock, flags);
 
err = ufshcd_hba_enable(hba);
@@ -5163,7 +5174,7 @@ static int ufshcd_link_state_transition(struct ufs_hba 
*hba,
 * Change controller state to "reset state" which
 * should also 

[PATCH v2 01/17] scsi: ufs-qcom: add number of lanes per direction

2015-10-26 Thread Yaniv Gardi
Different platform may have different number of lanes
for the UFS link.
Add parameter to device tree specifying how many lanes
should be configured for the UFS link.

Signed-off-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  |  3 ++
 drivers/scsi/ufs/ufs-qcom.c| 38 --
 drivers/scsi/ufs/ufshcd-pltfrm.c   | 19 +++
 drivers/scsi/ufs/ufshcd.c  |  1 +
 drivers/scsi/ufs/ufshcd.h  |  2 ++
 5 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt 
b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
index 03c0e98..9fea0de 100644
--- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
+++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
@@ -38,6 +38,9 @@ Optional properties:
  defined or a value in the array is "0" then it is 
assumed
  that the frequency is set by the parent clock or a
  fixed rate clock source.
+- lanes-per-direction: number of lanes available per direction - either 1 or 2.
+   Note that it is assume same number of lanes is used 
both directions at once.
+   If not specified, default is 2 lanes per direction.
 
 Note: If above properties are not defined it can be assumed that the supply
 regulators or clocks are always on.
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 4f38d00..c470c40 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -132,21 +132,23 @@ static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host 
*host)
if (err)
goto disable_rx_l0;
 
-   err = ufs_qcom_host_clk_enable(dev, "rx_lane1_sync_clk",
-   host->rx_l1_sync_clk);
-   if (err)
-   goto disable_tx_l0;
-
-   err = ufs_qcom_host_clk_enable(dev, "tx_lane1_sync_clk",
-   host->tx_l1_sync_clk);
-   if (err)
-   goto disable_rx_l1;
+   if (host->hba->lanes_per_direction > 1) {
+   err = ufs_qcom_host_clk_enable(dev, "rx_lane1_sync_clk",
+   host->rx_l1_sync_clk);
+   if (err)
+   goto disable_tx_l0;
 
+   err = ufs_qcom_host_clk_enable(dev, "tx_lane1_sync_clk",
+   host->tx_l1_sync_clk);
+   if (err)
+   goto disable_rx_l1;
+   }
host->is_lane_clks_enabled = true;
goto out;
 
 disable_rx_l1:
-   clk_disable_unprepare(host->rx_l1_sync_clk);
+   if (host->hba->lanes_per_direction > 1)
+   clk_disable_unprepare(host->rx_l1_sync_clk);
 disable_tx_l0:
clk_disable_unprepare(host->tx_l0_sync_clk);
 disable_rx_l0:
@@ -170,14 +172,16 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host 
*host)
if (err)
goto out;
 
-   err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk",
-   >rx_l1_sync_clk);
-   if (err)
-   goto out;
-
-   err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
-   >tx_l1_sync_clk);
+   /* In case of single lane per direction, don't read lane1 clocks */
+   if (host->hba->lanes_per_direction > 1) {
+   err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk",
+   >rx_l1_sync_clk);
+   if (err)
+   goto out;
 
+   err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
+   >tx_l1_sync_clk);
+   }
 out:
return err;
 }
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 9714f2a..5be0c91 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -40,6 +40,8 @@
 #include "ufshcd.h"
 #include "ufshcd-pltfrm.h"
 
+#define UFSHCD_DEFAULT_LANES_PER_DIRECTION 2
+
 static int ufshcd_parse_clock_info(struct ufs_hba *hba)
 {
int ret = 0;
@@ -277,6 +279,21 @@ void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown);
 
+static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba)
+{
+   struct device *dev = hba->dev;
+   int ret;
+
+   ret = of_property_read_u32(dev->of_node, "lanes-per-direction",
+   >lanes_per_direction);
+   if (ret) {
+   dev_dbg(hba->dev,
+   "%s: failed to read lanes-per-direction, ret=%d\n",
+   __func__, ret);
+   hba->lanes_per_direction = UFSHCD_DEFAULT_LANES_PER_DIRECTION;
+   }
+}
+
 /**
  * ufshcd_pltfrm_init - probe routine of the driver
  * @pdev: pointer to Platform device handle
@@ -331,6 +348,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,

[PATCH v2 03/17] scsi: ufs: optimize system suspend handling

2015-10-26 Thread Yaniv Gardi
Consider following sequence of events:
1. UFS is runtime suspended, link_state = Hibern8, device_state = sleep
2. System goes into system suspend, ufshcd_system_suspend() brings both
   link and device to active state and then puts the device in
   Power_Down state and link in OFF state.
3. System resumes at some later point in time, ufshcd_system_resume()
   doesn't do anything as UFS state is runtime suspended. Note that
   link is still on OFF state and device is in Power_Down state.
4. Now system again goes into suspend without any UFS accesses
   before it.
   ufshcd_system_suspend() again brings both link and device to active
   state and then puts the device in Power_Down state and link if OFF
   state. But it's unnecessary to bring the link & device in active
   state as both link and device are already in desired low power
   states. This change fixes this issue by adding proper state checks
   in ufshcd_system_suspend().

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 20c5b5d..00964f9 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5459,16 +5459,13 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
if (!hba || !hba->is_powered)
return 0;
 
-   if (pm_runtime_suspended(hba->dev)) {
-   if (hba->rpm_lvl == hba->spm_lvl)
-   /*
-* There is possibility that device may still be in
-* active state during the runtime suspend.
-*/
-   if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
-   hba->curr_dev_pwr_mode) && !hba->auto_bkops_enabled)
-   goto out;
+   if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
+hba->curr_dev_pwr_mode) &&
+   (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
+hba->uic_link_state))
+   goto out;
 
+   if (pm_runtime_suspended(hba->dev)) {
/*
 * UFS device and/or UFS link low power states during runtime
 * suspend seems to be different than what is expected during
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/17] scsi: ufs: implement scsi host timeout handler

2015-10-26 Thread Yaniv Gardi
A race condition exists between request requeueing and scsi layer
error handling:
When UFS driver queuecommand returns a busy status for a request,
it will be requeued and its tag will be freed and set to -1.
At the same time it is possible that the request will timeout and
scsi layer will start error handling for it. The scsi layer reuses
the request and its tag to send error related commands to the device,
however its tag is no longer valid.
As this request was never really sent to the device, there is no
point to start error handling with the device.
Implement the scsi error handling timeout callback and bypass SCSI
error handling for request that were not actually sent to the device.
For such requests simply reset the block layer timer. Otherwise, let
SCSI layer perform the usual error handling.

Signed-off-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a0aac38..3aea64b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4597,6 +4597,41 @@ static void ufshcd_async_scan(void *data, async_cookie_t 
cookie)
ufshcd_probe_hba(hba);
 }
 
+static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
+{
+   unsigned long flags;
+   struct Scsi_Host *host;
+   struct ufs_hba *hba;
+   int index;
+   bool found = false;
+
+   if (!scmd || !scmd->device || !scmd->device->host)
+   return BLK_EH_NOT_HANDLED;
+
+   host = scmd->device->host;
+   hba = shost_priv(host);
+   if (!hba)
+   return BLK_EH_NOT_HANDLED;
+
+   spin_lock_irqsave(host->host_lock, flags);
+
+   for_each_set_bit(index, >outstanding_reqs, hba->nutrs) {
+   if (hba->lrb[index].cmd == scmd) {
+   found = true;
+   break;
+   }
+   }
+
+   spin_unlock_irqrestore(host->host_lock, flags);
+
+   /*
+* Bypass SCSI error handling and reset the block layer timer if this
+* SCSI command was not actually dispatched to UFS driver, otherwise
+* let SCSI layer handle the error as usual.
+*/
+   return found ? BLK_EH_NOT_HANDLED : BLK_EH_RESET_TIMER;
+}
+
 static struct scsi_host_template ufshcd_driver_template = {
.module = THIS_MODULE,
.name   = UFSHCD,
@@ -4609,6 +4644,7 @@ static struct scsi_host_template ufshcd_driver_template = 
{
.eh_abort_handler   = ufshcd_abort,
.eh_device_reset_handler = ufshcd_eh_device_reset_handler,
.eh_host_reset_handler   = ufshcd_eh_host_reset_handler,
+   .eh_timed_out   = ufshcd_eh_timed_out,
.this_id= -1,
.sg_tablesize   = SG_ALL,
.cmd_per_lun= UFSHCD_CMD_PER_LUN,
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 08/17] scsi: ufs: disable vccq if it's not needed by UFS device

2015-10-26 Thread Yaniv Gardi
Some UFS devices don't require VCCQ rail for device operations hence
this change adds support to recognize such devices and remove vote for
the unused VCCQ rail.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufs.h|  1 +
 drivers/scsi/ufs/ufshcd.c | 60 +++
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 85c46b9..05e0f23 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -500,6 +500,7 @@ struct ufs_vreg {
struct regulator *reg;
const char *name;
bool enabled;
+   bool unused;
int min_uV;
int max_uV;
int min_uA;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 21e0792..ff57eb8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -221,6 +221,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba);
 static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
 bool skip_ref_clk);
 static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on);
+static int ufshcd_set_vccq_rail_unused(struct ufs_hba *hba, bool unused);
 static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
 static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
 static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba);
@@ -4622,6 +4623,12 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
goto out;
 
ufs_advertise_fixup_device(hba);
+
+   ret = ufshcd_set_vccq_rail_unused(hba,
+   (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false);
+   if (ret)
+   goto out;
+
/* UFS device is also active now */
ufshcd_set_ufs_dev_active(hba);
ufshcd_force_reset_auto_bkops(hba);
@@ -4773,13 +4780,24 @@ static int ufshcd_config_vreg_load(struct device *dev, 
struct ufs_vreg *vreg,
 static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
 struct ufs_vreg *vreg)
 {
-   return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA);
+   if (!vreg)
+   return 0;
+   else if (vreg->unused)
+   return 0;
+   else
+   return ufshcd_config_vreg_load(hba->dev, vreg,
+  UFS_VREG_LPM_LOAD_UA);
 }
 
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
 struct ufs_vreg *vreg)
 {
-   return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
+   if (!vreg)
+   return 0;
+   else if (vreg->unused)
+   return 0;
+   else
+   return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
 }
 
 static int ufshcd_config_vreg(struct device *dev,
@@ -4814,7 +4832,9 @@ static int ufshcd_enable_vreg(struct device *dev, struct 
ufs_vreg *vreg)
 {
int ret = 0;
 
-   if (!vreg || vreg->enabled)
+   if (!vreg)
+   goto out;
+   else if (vreg->enabled || vreg->unused)
goto out;
 
ret = ufshcd_config_vreg(dev, vreg, true);
@@ -4834,7 +4854,9 @@ static int ufshcd_disable_vreg(struct device *dev, struct 
ufs_vreg *vreg)
 {
int ret = 0;
 
-   if (!vreg || !vreg->enabled)
+   if (!vreg)
+   goto out;
+   else if (!vreg->enabled || vreg->unused)
goto out;
 
ret = regulator_disable(vreg->reg);
@@ -4940,6 +4962,36 @@ static int ufshcd_init_hba_vreg(struct ufs_hba *hba)
return 0;
 }
 
+static int ufshcd_set_vccq_rail_unused(struct ufs_hba *hba, bool unused)
+{
+   int ret = 0;
+   struct ufs_vreg_info *info = >vreg_info;
+
+   if (!info)
+   goto out;
+   else if (!info->vccq)
+   goto out;
+
+   if (unused) {
+   /* shut off the rail here */
+   ret = ufshcd_toggle_vreg(hba->dev, info->vccq, false);
+   /*
+* Mark this rail as no longer used, so it doesn't get enabled
+* later by mistake
+*/
+   if (!ret)
+   info->vccq->unused = true;
+   } else {
+   /*
+* rail should have been already enabled hence just make sure
+* that unused flag is cleared.
+*/
+   info->vccq->unused = false;
+   }
+out:
+   return ret;
+}
+
 static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
bool skip_ref_clk)
 {
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

[PATCH v2 12/17] scsi: ufs: handle non spec compliant bkops behaviour by device

2015-10-26 Thread Yaniv Gardi
We are seeing that some devices are raising the urgent bkops exception
events even when BKOPS status doesn't indicate performace impacted or
critical. Handle these device by determining their urgent bkops status
at runtime.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 53 ---
 drivers/scsi/ufs/ufshcd.h |  6 ++
 2 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3c5b82a..95d5d6b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3790,7 +3790,7 @@ out:
  */
 static int ufshcd_urgent_bkops(struct ufs_hba *hba)
 {
-   return ufshcd_bkops_ctrl(hba, BKOPS_STATUS_PERF_IMPACT);
+   return ufshcd_bkops_ctrl(hba, hba->urgent_bkops_lvl);
 }
 
 static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
@@ -3799,6 +3799,43 @@ static inline int ufshcd_get_ee_status(struct ufs_hba 
*hba, u32 *status)
QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
 }
 
+static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
+{
+   int err;
+   u32 curr_status = 0;
+
+   if (hba->is_urgent_bkops_lvl_checked)
+   goto enable_auto_bkops;
+
+   err = ufshcd_get_bkops_status(hba, _status);
+   if (err) {
+   dev_err(hba->dev, "%s: failed to get BKOPS status %d\n",
+   __func__, err);
+   goto out;
+   }
+
+   /*
+* We are seeing that some devices are raising the urgent bkops
+* exception events even when BKOPS status doesn't indicate performace
+* impacted or critical. Handle these device by determining their urgent
+* bkops status at runtime.
+*/
+   if (curr_status < BKOPS_STATUS_PERF_IMPACT) {
+   dev_err(hba->dev, "%s: device raised urgent BKOPS exception for 
bkops status %d\n",
+   __func__, curr_status);
+   /* update the current status as the urgent bkops level */
+   hba->urgent_bkops_lvl = curr_status;
+   hba->is_urgent_bkops_lvl_checked = true;
+   }
+
+enable_auto_bkops:
+   err = ufshcd_enable_auto_bkops(hba);
+out:
+   if (err < 0)
+   dev_err(hba->dev, "%s: failed to handle urgent bkops %d\n",
+   __func__, err);
+}
+
 /**
  * ufshcd_exception_event_handler - handle exceptions raised by device
  * @work: pointer to work data
@@ -3822,12 +3859,10 @@ static void ufshcd_exception_event_handler(struct 
work_struct *work)
}
 
status &= hba->ee_ctrl_mask;
-   if (status & MASK_EE_URGENT_BKOPS) {
-   err = ufshcd_urgent_bkops(hba);
-   if (err < 0)
-   dev_err(hba->dev, "%s: failed to handle urgent bkops 
%d\n",
-   __func__, err);
-   }
+
+   if (status & MASK_EE_URGENT_BKOPS)
+   ufshcd_bkops_exception_event_handler(hba);
+
 out:
pm_runtime_put_sync(hba->dev);
return;
@@ -4792,6 +4827,10 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 
ufshcd_init_pwr_info(hba);
 
+   /* set the default level for urgent bkops */
+   hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT;
+   hba->is_urgent_bkops_lvl_checked = false;
+
/* UniPro link is active now */
ufshcd_set_link_active(hba);
 
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 463f0d5..5c489483 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -383,6 +383,9 @@ struct ufs_init_prefetch {
  * @clk_list_head: UFS host controller clocks list node head
  * @pwr_info: holds current power mode
  * @max_pwr_info: keeps the device max valid pwm
+ * @urgent_bkops_lvl: keeps track of urgent bkops level for device
+ * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
+ *  device is known or not.
  */
 struct ufs_hba {
void __iomem *mmio_base;
@@ -538,6 +541,9 @@ struct ufs_hba {
struct devfreq *devfreq;
struct ufs_clk_scaling clk_scaling;
bool is_sys_suspended;
+
+   enum bkops_status urgent_bkops_lvl;
+   bool is_urgent_bkops_lvl_checked;
 };
 
 /* Returns true if clocks can be gated. Otherwise false */
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 15/17] scsi: ufs: add device quirk delay before putting UFS rails in LPM

2015-10-26 Thread Yaniv Gardi
We put the UFS device in sleep state & UFS link in hibern8 state during
runtime suspaned. After this we put all the UFS rails in low power
modes immediately but it seems some devices may still draw more than
sleep current from UFS rails (especially from VCCQ rail) atleast for
500us.
To avoid this situation, this change adds 2ms delay before putting
these UFS rails in LPM mode.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufs_quirks.c |  4 
 drivers/scsi/ufs/ufs_quirks.h | 10 +-
 drivers/scsi/ufs/ufshcd.c | 10 ++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c
index 3e3b6fc..ba31905 100644
--- a/drivers/scsi/ufs/ufs_quirks.c
+++ b/drivers/scsi/ufs/ufs_quirks.c
@@ -16,11 +16,15 @@
 
 static struct ufs_dev_fix ufs_fixups[] = {
/* UFS cards deviations table */
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+   UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
UFS_DEVICE_NO_FASTAUTO),
+   UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
+   UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
UFS_DEVICE_QUIRK_PA_TACTIVATE),
UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 7c2817e..ade9b86 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -17,7 +17,7 @@
 /* return true if s1 is a prefix of s2 */
 #define STR_PRFX_EQUAL(s1, s2) !strncmp(s1, s2, strlen(s1))
 
-#define UFS_ANY_VENDOR -1
+#define UFS_ANY_VENDOR 0x
 #define UFS_ANY_MODEL  "ANY_MODEL"
 
 #define MAX_MODEL_LEN 16
@@ -118,6 +118,14 @@ struct ufs_dev_fix {
  */
 #define UFS_DEVICE_NO_FASTAUTO (1 << 5)
 
+/*
+ * It seems some UFS devices may keep drawing more than sleep current
+ * (atleast for 500us) from UFS rails (especially from VCCQ rail).
+ * To avoid this situation, add 2ms delay before putting these UFS
+ * rails in LPM mode.
+ */
+#define UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM  (1 << 6)
+
 struct ufs_hba;
 void ufs_advertise_fixup_device(struct ufs_hba *hba);
 #endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f85cd66..2c8decd 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5677,6 +5677,16 @@ out:
 static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
 {
/*
+* It seems some UFS devices may keep drawing more than sleep current
+* (atleast for 500us) from UFS rails (especially from VCCQ rail).
+* To avoid this situation, add 2ms delay before putting these UFS
+* rails in LPM mode.
+*/
+   if (!ufshcd_is_link_active(hba) &&
+   hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM)
+   usleep_range(2000, 2100);
+
+   /*
 * If UFS device is either in UFS_Sleep turn off VCC rail to save some
 * power.
 *
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 09/17] scsi: ufs: make error handling bit faster

2015-10-26 Thread Yaniv Gardi
UFS driver's error handler forcefully tries to clear all the pending
requests. For each pending request in the queue, it waits 1 sec for it
to get cleared. If we have multiple requests in the queue then it's
possible that we might end up waiting for those many seconds before
resetting the host. But note that resetting host would any way clear
all the pending requests from the hardware. Hence this change skips
the forceful clear of the pending requests if we are anyway going to
reset the host (for fatal errors).

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 155 +-
 1 file changed, 112 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ff57eb8..3bf557b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -135,9 +135,11 @@ enum {
 /* UFSHCD UIC layer error flags */
 enum {
UFSHCD_UIC_DL_PA_INIT_ERROR = (1 << 0), /* Data link layer error */
-   UFSHCD_UIC_NL_ERROR = (1 << 1), /* Network layer error */
-   UFSHCD_UIC_TL_ERROR = (1 << 2), /* Transport Layer error */
-   UFSHCD_UIC_DME_ERROR = (1 << 3), /* DME error */
+   UFSHCD_UIC_DL_NAC_RECEIVED_ERROR = (1 << 1), /* Data link layer error */
+   UFSHCD_UIC_DL_TCx_REPLAY_ERROR = (1 << 2), /* Data link layer error */
+   UFSHCD_UIC_NL_ERROR = (1 << 3), /* Network layer error */
+   UFSHCD_UIC_TL_ERROR = (1 << 4), /* Transport Layer error */
+   UFSHCD_UIC_DME_ERROR = (1 << 5), /* DME error */
 };
 
 /* Interrupt configuration options */
@@ -3492,31 +3494,18 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, 
u32 intr_status)
 }
 
 /**
- * ufshcd_transfer_req_compl - handle SCSI and query command completion
+ * __ufshcd_transfer_req_compl - handle SCSI and query command completion
  * @hba: per adapter instance
+ * @completed_reqs: requests to complete
  */
-static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
+static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
+   unsigned long completed_reqs)
 {
struct ufshcd_lrb *lrbp;
struct scsi_cmnd *cmd;
-   unsigned long completed_reqs;
-   u32 tr_doorbell;
int result;
int index;
 
-   /* Resetting interrupt aggregation counters first and reading the
-* DOOR_BELL afterward allows us to handle all the completed requests.
-* In order to prevent other interrupts starvation the DB is read once
-* after reset. The down side of this solution is the possibility of
-* false interrupt if device completes another request after resetting
-* aggregation and before reading the DB.
-*/
-   if (ufshcd_is_intr_aggr_allowed(hba))
-   ufshcd_reset_intr_aggr(hba);
-
-   tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
-   completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
-
for_each_set_bit(index, _reqs, hba->nutrs) {
lrbp = >lrb[index];
cmd = lrbp->cmd;
@@ -3546,6 +3535,31 @@ static void ufshcd_transfer_req_compl(struct ufs_hba 
*hba)
 }
 
 /**
+ * ufshcd_transfer_req_compl - handle SCSI and query command completion
+ * @hba: per adapter instance
+ */
+static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
+{
+   unsigned long completed_reqs;
+   u32 tr_doorbell;
+
+   /* Resetting interrupt aggregation counters first and reading the
+* DOOR_BELL afterward allows us to handle all the completed requests.
+* In order to prevent other interrupts starvation the DB is read once
+* after reset. The down side of this solution is the possibility of
+* false interrupt if device completes another request after resetting
+* aggregation and before reading the DB.
+*/
+   if (ufshcd_is_intr_aggr_allowed(hba))
+   ufshcd_reset_intr_aggr(hba);
+
+   tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+   completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
+
+   __ufshcd_transfer_req_compl(hba, completed_reqs);
+}
+
+/**
  * ufshcd_disable_ee - disable exception event
  * @hba: per-adapter instance
  * @mask: exception event to disable
@@ -3800,6 +3814,13 @@ out:
return;
 }
 
+/* Complete requests that have door-bell cleared */
+static void ufshcd_complete_requests(struct ufs_hba *hba)
+{
+   ufshcd_transfer_req_compl(hba);
+   ufshcd_tmc_handler(hba);
+}
+
 /**
  * ufshcd_err_handler - handle UFS errors that require s/w attention
  * @work: pointer to work structure
@@ -3812,6 +3833,7 @@ static void ufshcd_err_handler(struct work_struct *work)
u32 err_tm = 0;
int err = 0;
int tag;
+   bool needs_reset = false;
 
hba = container_of(work, struct ufs_hba, eh_work);
 
@@ -3819,40 +3841,75 @@ static void 

[PATCH v2 13/17] scsi: ufs: tune UniPro parameters to optimize hibern8 exit time

2015-10-26 Thread Yaniv Gardi
Optimal values of local UniPro parameters like PA_Hibern8Time &
PA_TActivate can help reduce the hibern8 exit latency. If both host and
device supports UniPro ver1.6 or later, these parameters will be
automatically tuned during link startup itself. But if either host or
device doesn't support UniPro ver 1.6 or later, we have to manually
tune them. But to keep manual tuning logic simple, we will only do
manual tuning if local unipro version doesn't support ver1.6 or later.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 118 ++
 drivers/scsi/ufs/ufshcd.h |   1 +
 drivers/scsi/ufs/ufshci.h |   2 +
 drivers/scsi/ufs/unipro.h |  21 +
 4 files changed, 142 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 95d5d6b..822692e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -596,6 +596,34 @@ static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
 }
 
+u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba)
+{
+   /* HCI version 1.0 and 1.1 supports UniPro 1.41 */
+   if ((hba->ufs_version == UFSHCI_VERSION_10) ||
+   (hba->ufs_version == UFSHCI_VERSION_11))
+   return UFS_UNIPRO_VER_1_41;
+   else
+   return UFS_UNIPRO_VER_1_6;
+}
+EXPORT_SYMBOL(ufshcd_get_local_unipro_ver);
+
+static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba)
+{
+   /*
+* If both host and device support UniPro ver1.6 or later, PA layer
+* parameters tuning happens during link startup itself.
+*
+* We can manually tune PA layer parameters if either host or device
+* doesn't support UniPro ver 1.6 or later. But to keep manual tuning
+* logic simple, we will only do manual tuning if local unipro version
+* doesn't support ver1.6 or later.
+*/
+   if (ufshcd_get_local_unipro_ver(hba) < UFS_UNIPRO_VER_1_6)
+   return true;
+   else
+   return false;
+}
+
 static void ufshcd_ungate_work(struct work_struct *work)
 {
int ret;
@@ -4812,6 +4840,95 @@ out:
 }
 
 /**
+ * ufshcd_tune_pa_tactivate - Tunes PA_TActivate of local UniPro
+ * @hba: per-adapter instance
+ *
+ * PA_TActivate parameter can be tuned manually if UniPro version is less than
+ * 1.61. PA_TActivate needs to be greater than or equal to peerM-PHY's
+ * RX_MIN_ACTIVATETIME_CAPABILITY attribute. This optimal value can help reduce
+ * the hibern8 exit latency.
+ *
+ * Returns zero on success, non-zero error value on failure.
+ */
+static int ufshcd_tune_pa_tactivate(struct ufs_hba *hba)
+{
+   int ret = 0;
+   u32 peer_rx_min_activatetime = 0, tuned_pa_tactivate;
+
+   ret = ufshcd_dme_peer_get(hba,
+ UIC_ARG_MIB_SEL(
+   RX_MIN_ACTIVATETIME_CAPABILITY,
+   UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
+ _rx_min_activatetime);
+   if (ret)
+   goto out;
+
+   /* make sure proper unit conversion is applied */
+   tuned_pa_tactivate =
+   ((peer_rx_min_activatetime * RX_MIN_ACTIVATETIME_UNIT_US)
+/ PA_TACTIVATE_TIME_UNIT_US);
+   ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE),
+tuned_pa_tactivate);
+
+out:
+   return ret;
+}
+
+/**
+ * ufshcd_tune_pa_hibern8time - Tunes PA_Hibern8Time of local UniPro
+ * @hba: per-adapter instance
+ *
+ * PA_Hibern8Time parameter can be tuned manually if UniPro version is less 
than
+ * 1.61. PA_Hibern8Time needs to be maximum of local M-PHY's
+ * TX_HIBERN8TIME_CAPABILITY & peer M-PHY's RX_HIBERN8TIME_CAPABILITY.
+ * This optimal value can help reduce the hibern8 exit latency.
+ *
+ * Returns zero on success, non-zero error value on failure.
+ */
+static int ufshcd_tune_pa_hibern8time(struct ufs_hba *hba)
+{
+   int ret = 0;
+   u32 local_tx_hibern8_time_cap = 0, peer_rx_hibern8_time_cap = 0;
+   u32 max_hibern8_time, tuned_pa_hibern8time;
+
+   ret = ufshcd_dme_get(hba,
+UIC_ARG_MIB_SEL(TX_HIBERN8TIME_CAPABILITY,
+   UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+ _tx_hibern8_time_cap);
+   if (ret)
+   goto out;
+
+   ret = ufshcd_dme_peer_get(hba,
+ UIC_ARG_MIB_SEL(RX_HIBERN8TIME_CAPABILITY,
+   UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
+ _rx_hibern8_time_cap);
+   if (ret)
+   goto out;
+
+   max_hibern8_time = max(local_tx_hibern8_time_cap,
+  peer_rx_hibern8_time_cap);
+   /* make sure proper unit conversion is applied 

[PATCH v2 14/17] scsi: ufs: fix leakage during link off state

2015-10-26 Thread Yaniv Gardi
Currently when we try to put the link in off/disabled state during
suspend, it seems link is not being kept in low power mode.
This patch fixes the issue by putting the link in hibern8 first
(so device also puts the link in low power mode) and then stop the
host controller.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 822692e..f85cd66 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5649,6 +5649,16 @@ static int ufshcd_link_state_transition(struct ufs_hba 
*hba,
   (!check_for_bkops || (check_for_bkops &&
!hba->auto_bkops_enabled))) {
/*
+* Let's make sure that link is in low power mode, we are doing
+* this currently by putting the link in Hibern8. Otherway to
+* put the link in low power mode is to send the DME end point
+* to device and then send the DME reset command to local
+* unipro. But putting the link in hibern8 is much faster.
+*/
+   ret = ufshcd_uic_hibern8_enter(hba);
+   if (ret)
+   goto out;
+   /*
 * Change controller state to "reset state" which
 * should also put the link in off/reset state
 */
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/17] scsi: ufs: add error recovery after DL NAC error

2015-10-26 Thread Yaniv Gardi
Some vendor's UFS device sends back to back NACs for the DL data frames
causing the host controller to raise the DFES error status. Sometimes
such UFS devices send back to back NAC without waiting for new
retransmitted DL frame from the host and in such cases it might be
possible the Host UniPro goes into bad state without raising the DFES
error interrupt. If this happens then all the pending commands would
timeout only after respective SW command (which is generally too
large).

This change workarounds such device behaviour like this:
- As soon as SW sees the DL NAC error, it would schedule the error
  handler
- Error handler would sleep for 50ms to see if there any fatal errors
  raised by UFS controller.
   - If there are fatal errors then SW does normal error recovery.
   - If there are no fatal errors then SW sends the NOP command to
 device to check if link is alive.
   - If NOP command times out, SW does normal error recovery
   - If NOP command succeed, skip the error handling.

If DL NAC error is seen multiple times with some vendor's UFS devices
then enable this quirk to initiate quick error recovery and also
silence related error logs to reduce spamming of kernel logs.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 93 +++
 drivers/scsi/ufs/ufshci.h |  2 +
 2 files changed, 95 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3bf557b..7558047 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3822,6 +3822,79 @@ static void ufshcd_complete_requests(struct ufs_hba *hba)
 }
 
 /**
+ * ufshcd_quirk_dl_nac_errors - This function checks if error handling is
+ * to recover from the DL NAC errors or not.
+ * @hba: per-adapter instance
+ *
+ * Returns true if error handling is required, false otherwise
+ */
+static bool ufshcd_quirk_dl_nac_errors(struct ufs_hba *hba)
+{
+   unsigned long flags;
+   bool err_handling = true;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   /*
+* UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS only workaround the
+* device fatal error and/or DL NAC & REPLAY timeout errors.
+*/
+   if (hba->saved_err & (CONTROLLER_FATAL_ERROR | SYSTEM_BUS_FATAL_ERROR))
+   goto out;
+
+   if ((hba->saved_err & DEVICE_FATAL_ERROR) ||
+   ((hba->saved_err & UIC_ERROR) &&
+(hba->saved_uic_err & UFSHCD_UIC_DL_TCx_REPLAY_ERROR)))
+   goto out;
+
+   if ((hba->saved_err & UIC_ERROR) &&
+   (hba->saved_uic_err & UFSHCD_UIC_DL_NAC_RECEIVED_ERROR)) {
+   int err;
+   /*
+* wait for 50ms to see if we can get any other errors or not.
+*/
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+   msleep(50);
+   spin_lock_irqsave(hba->host->host_lock, flags);
+
+   /*
+* now check if we have got any other severe errors other than
+* DL NAC error?
+*/
+   if ((hba->saved_err & INT_FATAL_ERRORS) ||
+   ((hba->saved_err & UIC_ERROR) &&
+   (hba->saved_uic_err & ~UFSHCD_UIC_DL_NAC_RECEIVED_ERROR)))
+   goto out;
+
+   /*
+* As DL NAC is the only error received so far, send out NOP
+* command to confirm if link is still active or not.
+*   - If we don't get any response then do error recovery.
+*   - If we get response then clear the DL NAC error bit.
+*/
+
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+   err = ufshcd_verify_dev_init(hba);
+   spin_lock_irqsave(hba->host->host_lock, flags);
+
+   if (err)
+   goto out;
+
+   /* Link seems to be alive hence ignore the DL NAC errors */
+   if (hba->saved_uic_err == UFSHCD_UIC_DL_NAC_RECEIVED_ERROR)
+   hba->saved_err &= ~UIC_ERROR;
+   /* clear NAC error */
+   hba->saved_uic_err &= ~UFSHCD_UIC_DL_NAC_RECEIVED_ERROR;
+   if (!hba->saved_uic_err) {
+   err_handling = false;
+   goto out;
+   }
+   }
+out:
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+   return err_handling;
+}
+
+/**
  * ufshcd_err_handler - handle UFS errors that require s/w attention
  * @work: pointer to work structure
  */
@@ -3849,6 +3922,17 @@ static void ufshcd_err_handler(struct work_struct *work)
 
/* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba);
+
+   if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
+   bool 

[RESEND PATCH v2] backlight: pm8941-wled: Add default-brightness property

2015-10-26 Thread Bjorn Andersson
Default the brightness to 2048 and add possibility to override this in
device tree.

Suggested-by: Rob Clark 
Signed-off-by: Bjorn Andersson 
---

Resend of v2, with updated backlight dt binding location.

 Documentation/devicetree/bindings/leds/backlight/pm8941-wled.txt | 2 ++
 drivers/video/backlight/pm8941-wled.c| 8 
 2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/leds/backlight/pm8941-wled.txt 
b/Documentation/devicetree/bindings/leds/backlight/pm8941-wled.txt
index 424f8444a6cd..e5b294dafc58 100644
--- a/Documentation/devicetree/bindings/leds/backlight/pm8941-wled.txt
+++ b/Documentation/devicetree/bindings/leds/backlight/pm8941-wled.txt
@@ -5,6 +5,8 @@ Required properties:
 - reg: slave address
 
 Optional properties:
+- default-brightness: brightness value on boot, value from: 0-4095
+   default: 2048
 - label: The name of the backlight device
 - qcom,cs-out: bool; enable current sink output
 - qcom,cabc: bool; enable content adaptive backlight control
diff --git a/drivers/video/backlight/pm8941-wled.c 
b/drivers/video/backlight/pm8941-wled.c
index c704c3236034..e1298147bcbb 100644
--- a/drivers/video/backlight/pm8941-wled.c
+++ b/drivers/video/backlight/pm8941-wled.c
@@ -17,6 +17,9 @@
 #include 
 #include 
 
+/* From DT binding */
+#define PM8941_WLED_DEFAULT_BRIGHTNESS 2048
+
 #define PM8941_WLED_REG_VAL_BASE   0x40
 #define  PM8941_WLED_REG_VAL_MAX   0xFFF
 
@@ -373,6 +376,7 @@ static int pm8941_wled_probe(struct platform_device *pdev)
struct backlight_device *bl;
struct pm8941_wled *wled;
struct regmap *regmap;
+   u32 val;
int rc;
 
regmap = dev_get_regmap(pdev->dev.parent, NULL);
@@ -395,8 +399,12 @@ static int pm8941_wled_probe(struct platform_device *pdev)
if (rc)
return rc;
 
+   val = PM8941_WLED_DEFAULT_BRIGHTNESS;
+   of_property_read_u32(pdev->dev.of_node, "default-brightness", );
+
memset(, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
+   props.brightness = val;
props.max_brightness = PM8941_WLED_REG_VAL_MAX;
bl = devm_backlight_device_register(>dev, wled->name,
>dev, wled,
-- 
2.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html