[PATCH 05/13] clk/qcom: add gdsc_enable helper
Caleb Connolly
caleb.connolly at linaro.org
Wed Jan 31 16:16:57 CET 2024
Global Distributed Switch Controllers 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.
Linux models these as power domains, however this additional complexity
doesn't offer much benefit to us in U-Boot. For now they can be turned
on as-needed when a relevant clock is enabled.
In the future, we can add a power-domain driver to model these properly.
Signed-off-by: Caleb Connolly <caleb.connolly at linaro.org>
---
drivers/clk/qcom/clock-qcom.c | 18 ++++++++++++++++++
drivers/clk/qcom/clock-qcom.h | 4 ++++
2 files changed, 22 insertions(+)
diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c
index d912b673d0d8..0e89e7fe429e 100644
--- a/drivers/clk/qcom/clock-qcom.c
+++ b/drivers/clk/qcom/clock-qcom.c
@@ -39,6 +39,24 @@ void clk_enable_cbc(phys_addr_t cbcr)
;
}
+/* Global Distributed Switch Controller - these are
+ * breaker switches for entire peripherals like USB,
+ * they control power and clocks and must be turned on
+ * before configuring clocks or accessing the peripheral.
+ */
+void gdsc_enable(phys_addr_t gdscr)
+{
+ u32 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 7eb26369cd8f..2e074d0401c4 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
@@ -78,6 +81,7 @@ int qcom_cc_bind(struct udevice *parent);
void clk_enable_gpll0(phys_addr_t base, const struct pll_vote_clk *gpll0);
void clk_bcr_update(phys_addr_t apps_cmd_rgcr);
void clk_enable_cbc(phys_addr_t cbcr);
+void gdsc_enable(phys_addr_t gdscr);
void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk);
const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate);
void clk_rcg_set_rate_mnd(phys_addr_t base, uint32_t cmd_rcgr,
--
2.43.0
More information about the U-Boot
mailing list