clk/qcom: add gdsc_enable helper

GDSCs are per-domain switches which are used to toggle power and clocks
to an entire subsystem. They live under the GCC block and might need to
be enabled before certain clocks, so handle them as part of the clock
driver.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c
index 22ecd18..c880df2 100644
--- a/drivers/clk/qcom/clock-qcom.c
+++ b/drivers/clk/qcom/clock-qcom.c
@@ -39,6 +39,18 @@
 		;
 }
 
+void gdsc_enable(phys_addr_t gdscr)
+{
+	uint32_t count;
+	clrbits_le32(gdscr, GDSC_SW_COLLAPSE);
+	for (count = 0; count < 1500; count++) {
+		if (readl(gdscr) & GDSC_PWR_ON)
+			break;
+		udelay(1);
+	}
+	WARN(count == 1500, "WARNING: GDSC @ %#llx stuck at off\n", gdscr);
+}
+
 void clk_enable_gpll0(phys_addr_t base, const struct pll_vote_clk *gpll0)
 {
 	if (readl(base + gpll0->status) & gpll0->status_bit)
diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h
index 7eb2636..af8f9ff 100644
--- a/drivers/clk/qcom/clock-qcom.h
+++ b/drivers/clk/qcom/clock-qcom.h
@@ -12,6 +12,9 @@
 #define CFG_CLK_SRC_GPLL0_EVEN (6 << 8)
 #define CFG_CLK_SRC_MASK  (7 << 8)
 
+#define GDSC_PWR_ON		BIT(31)
+#define GDSC_SW_COLLAPSE	BIT(0)
+
 #define RCG_CFG_REG		0x4
 #define RCG_M_REG		0x8
 #define RCG_N_REG		0xc