clk: qcom: gdsc-regulator: Add support to skip GDSC disable

Add check to skip gdsc disable when disable call comes before
the gdsc enable. In case if the gdsc is enabled by entity external
to HLOS then skip disable call.

Change-Id: I14ba8a24fb4403a1805cba23967bb22a82ac6e7f
Signed-off-by: Naveen Yadav <naveenky@codeaurora.org>
Signed-off-by: Taniya Das <tdas@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 4ef8d7a..a6b0cdd 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -72,7 +72,9 @@
  - qcom,en-rest-wait-val: Input value for EN_REST_WAIT controls state transition
 			  delay after receiving ack signal (gds_enr_ack) from the
 			  longest en_rest power switch chain.
-
+ - qcom,skip-disable-before-sw-enable: Presence denotes a hardware requirement
+					to leave the GDSC on that has been
+					enabled by an entity external to HLOS.
 Example:
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
 		compatible = "qcom,gdsc";
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index 15a93cd..1ffb341 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020, 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
@@ -92,6 +92,7 @@
 	int			root_clk_idx;
 	u32			gds_timeout;
 	u32			flags;
+	bool			skip_disable_before_enable;
 };
 
 enum gdscr_status {
@@ -379,6 +380,7 @@
 		clk_disable_unprepare(sc->clocks[sc->root_clk_idx]);
 
 	sc->is_gdsc_enabled = true;
+	sc->skip_disable_before_enable = false;
 
 	mutex_unlock(&gdsc_seq_lock);
 
@@ -391,6 +393,16 @@
 	uint32_t regval;
 	int i, ret = 0;
 
+	/*
+	 * Protect GDSC against late_init disabling when the GDSC is enabled
+	 * by an entity outside external to HLOS.
+	 */
+	if (sc->skip_disable_before_enable) {
+		dev_dbg(&rdev->dev, "Skip Disabling: %s\n", sc->rdesc.name);
+		sc->skip_disable_before_enable = false;
+		return 0;
+	}
+
 	mutex_lock(&gdsc_seq_lock);
 
 	if (sc->force_root_en)
@@ -827,6 +839,9 @@
 			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
 	}
 
+	sc->skip_disable_before_enable = of_property_read_bool(
+		pdev->dev.of_node, "qcom,skip-disable-before-sw-enable");
+
 	reg_config.dev = &pdev->dev;
 	reg_config.init_data = init_data;
 	reg_config.driver_data = sc;