Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: qcom: gdsc: Add support to update GDSC transition delay

GDSCs have multiple transition delays which are used for the GDSC FSM
states. Older targets/designs required these values to be updated from
gdsc code to certain default values for the FSM state to work as
expected. But on the newer targets/designs the values updated from the
GDSC driver can hamper the FSM state to not work as expected.

On SC7180 we observe black screens because the gdsc is being
enabled/disabled very rapidly and the GDSC FSM state does not work as
expected. This is due to the fact that the GDSC reset value is being
updated from SW.

Thus add support to update the transition delay from the clock
controller gdscs as required.

Fixes: 45dd0e55317cc ("clk: qcom: Add support for GDSCs)
Signed-off-by: Taniya Das <tdas@codeaurora.org>
Link: https://lore.kernel.org/r/20220223185606.3941-1-tdas@codeaurora.org
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Taniya Das and committed by
Stephen Boyd
4e7c4d36 2f0754f2

+28 -6
+21 -5
drivers/clk/qcom/gdsc.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved. 3 + * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 6 #include <linux/bitops.h> ··· 35 35 #define CFG_GDSCR_OFFSET 0x4 36 36 37 37 /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */ 38 - #define EN_REST_WAIT_VAL (0x2 << 20) 39 - #define EN_FEW_WAIT_VAL (0x8 << 16) 40 - #define CLK_DIS_WAIT_VAL (0x2 << 12) 38 + #define EN_REST_WAIT_VAL 0x2 39 + #define EN_FEW_WAIT_VAL 0x8 40 + #define CLK_DIS_WAIT_VAL 0x2 41 + 42 + /* Transition delay shifts */ 43 + #define EN_REST_WAIT_SHIFT 20 44 + #define EN_FEW_WAIT_SHIFT 16 45 + #define CLK_DIS_WAIT_SHIFT 12 41 46 42 47 #define RETAIN_MEM BIT(14) 43 48 #define RETAIN_PERIPH BIT(13) ··· 385 380 */ 386 381 mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK | 387 382 EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK; 388 - val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL; 383 + 384 + if (!sc->en_rest_wait_val) 385 + sc->en_rest_wait_val = EN_REST_WAIT_VAL; 386 + if (!sc->en_few_wait_val) 387 + sc->en_few_wait_val = EN_FEW_WAIT_VAL; 388 + if (!sc->clk_dis_wait_val) 389 + sc->clk_dis_wait_val = CLK_DIS_WAIT_VAL; 390 + 391 + val = sc->en_rest_wait_val << EN_REST_WAIT_SHIFT | 392 + sc->en_few_wait_val << EN_FEW_WAIT_SHIFT | 393 + sc->clk_dis_wait_val << CLK_DIS_WAIT_SHIFT; 394 + 389 395 ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val); 390 396 if (ret) 391 397 return ret;
+7 -1
drivers/clk/qcom/gdsc.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 2 /* 3 - * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved. 3 + * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 6 #ifndef __QCOM_GDSC_H__ ··· 22 22 * @cxcs: offsets of branch registers to toggle mem/periph bits in 23 23 * @cxc_count: number of @cxcs 24 24 * @pwrsts: Possible powerdomain power states 25 + * @en_rest_wait_val: transition delay value for receiving enr ack signal 26 + * @en_few_wait_val: transition delay value for receiving enf ack signal 27 + * @clk_dis_wait_val: transition delay value for halting clock 25 28 * @resets: ids of resets associated with this gdsc 26 29 * @reset_count: number of @resets 27 30 * @rcdev: reset controller ··· 39 36 unsigned int clamp_io_ctrl; 40 37 unsigned int *cxcs; 41 38 unsigned int cxc_count; 39 + unsigned int en_rest_wait_val; 40 + unsigned int en_few_wait_val; 41 + unsigned int clk_dis_wait_val; 42 42 const u8 pwrsts; 43 43 /* Powerdomain allowable state bitfields */ 44 44 #define PWRSTS_OFF BIT(0)