From 39024b050cec44147eb2fef1453870b44373348e Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 7 Nov 2016 10:01:38 +0530 Subject: [PATCH] clk: qcom: Add additional clock debugfs support Update QCOM clock debugfs to support the below functionalities. - Display the register contents of all the clocks which support this operation. - Display the frequency to voltage mapping of a clock. - Display the list of clock frequencies supported by the root clocks. - Display the clk_rate_max associated with enabled clocks list. Also add the clock list_rate_vdd_level operation, which is required for the "clk_enabled_list" and "trace_clocks" debugfs nodes to print the current voltage. Change-Id: I3b4cf83e776750d993d53331142223109bf0862e Signed-off-by: Taniya Das Signed-off-by: Deepak Katragadda Signed-off-by: David Dai Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-alpha-pll.c | 428 ++++++++++++++++++++++++++++++- drivers/clk/qcom/clk-alpha-pll.h | 6 +- drivers/clk/qcom/clk-branch.c | 72 +++++- drivers/clk/qcom/clk-dummy.c | 4 +- drivers/clk/qcom/clk-rcg2.c | 91 +++++++ drivers/clk/qcom/clk-regmap.c | 3 + drivers/clk/qcom/clk-regmap.h | 8 +- 7 files changed, 607 insertions(+), 5 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 8c1b79830632..4c1a9b69f1ee 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ #include #include "clk-alpha-pll.h" +#include "clk-debug.h" #include "common.h" #define PLL_MODE(p) ((p)->offset + 0x0) @@ -115,6 +116,9 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_STATUS] = 0x30, [PLL_OFF_OPMODE] = 0x38, [PLL_OFF_ALPHA_VAL] = 0x40, + [PLL_OFF_SSC_DELTA_ALPHA] = 0x48, + [PLL_OFF_SSC_NUM_STEPS] = 0x4C, + [PLL_OFF_SSC_UPDATE_RATE] = 0x50, }, [CLK_ALPHA_PLL_TYPE_AGERA] = { [PLL_OFF_L_VAL] = 0x04, @@ -904,6 +908,55 @@ clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); } +static void clk_alpha_pll_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", 0x0}, + {"PLL_L_VAL", 0x4}, + {"PLL_ALPHA_VAL", 0x8}, + {"PLL_ALPHA_VAL_U", 0xC}, + {"PLL_USER_CTL", 0x10}, + {"PLL_CONFIG_CTL", 0x18}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + data[i].offset, + &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + data[0].offset, &val); + + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); + } +} + +static struct clk_regmap_ops clk_alpha_pll_regmap_ops = { + .list_registers = clk_alpha_pll_list_registers, +}; + +static int clk_alpha_pll_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_alpha_pll_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_fixed_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -913,6 +966,8 @@ const struct clk_ops clk_alpha_pll_fixed_ops = { .disable = clk_alpha_pll_disable, .is_enabled = clk_alpha_pll_is_enabled, .recalc_rate = clk_alpha_pll_recalc_rate, + .init = clk_alpha_pll_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_ops); @@ -927,9 +982,68 @@ const struct clk_ops clk_alpha_pll_ops = { .recalc_rate = clk_alpha_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = clk_alpha_pll_set_rate, + .init = clk_alpha_pll_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_ops); +static void clk_alpha_pll_huayra_list_registers(struct seq_file *f, + struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, + {"PLL_CONFIG_CTL_U1", PLL_OFF_CONFIG_CTL_U1}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_TEST_CTL_U1", PLL_OFF_TEST_CTL_U1}, + {"PLL_OPMODE", PLL_OFF_OPMODE}, + {"PLL_STATUS", PLL_OFF_STATUS}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], + &val); + + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); + } +} + +static struct clk_regmap_ops clk_alpha_pll_huayra_regmap_ops = { + .list_registers = clk_alpha_pll_huayra_list_registers, +}; + +static int clk_alpha_pll_huayra_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_alpha_pll_huayra_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_huayra_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -941,6 +1055,8 @@ const struct clk_ops clk_alpha_pll_huayra_ops = { .recalc_rate = alpha_pll_huayra_recalc_rate, .round_rate = alpha_pll_huayra_round_rate, .set_rate = alpha_pll_huayra_set_rate, + .init = clk_alpha_pll_huayra_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_huayra_ops); @@ -955,9 +1071,70 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { .recalc_rate = clk_alpha_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = clk_alpha_pll_hwfsm_set_rate, + .init = clk_alpha_pll_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); +static void clk_trion_pll_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_CAL_L_VAL", PLL_OFF_CAL_L_VAL}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_USER_CTL_U", PLL_OFF_USER_CTL_U}, + {"PLL_USER_CTL_U1", PLL_OFF_USER_CTL_U1}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, + {"PLL_CONFIG_CTL_U1", PLL_OFF_CONFIG_CTL_U1}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_TEST_CTL_U1", PLL_OFF_TEST_CTL_U1}, + {"PLL_STATUS", PLL_OFF_STATUS}, + {"PLL_OPMODE", PLL_OFF_OPMODE}, + {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], + &val); + + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); + } +} + +static struct clk_regmap_ops clk_trion_pll_regmap_ops = { + .list_registers = &clk_trion_pll_list_registers, +}; + +static int clk_trion_pll_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_trion_pll_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_fixed_trion_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -968,6 +1145,8 @@ const struct clk_ops clk_alpha_pll_fixed_trion_ops = { .is_enabled = clk_trion_pll_is_enabled, .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, + .debug_init = clk_common_debug_init, + .init = clk_trion_pll_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_trion_ops); @@ -1299,6 +1478,62 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) return 0; } +static void clk_fabia_pll_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_CAL_L_VAL", PLL_OFF_CAL_L_VAL}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_USER_CTL_U", PLL_OFF_USER_CTL_U}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_STATUS", PLL_OFF_STATUS}, + {"PLL_OPMODE", PLL_OFF_OPMODE}, + {"PLL_FRAC", PLL_OFF_FRAC}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], + &val); + + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); + } +} + +static struct clk_regmap_ops clk_fabia_pll_regmap_ops = { + .list_registers = &clk_fabia_pll_list_registers, +}; + +static int clk_fabia_pll_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_fabia_pll_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_fabia_ops = { .prepare = alpha_pll_fabia_prepare, .unprepare = clk_unprepare_regmap, @@ -1310,6 +1545,8 @@ const struct clk_ops clk_alpha_pll_fabia_ops = { .set_rate = alpha_pll_fabia_set_rate, .recalc_rate = alpha_pll_fabia_recalc_rate, .round_rate = clk_alpha_pll_round_rate, + .debug_init = clk_common_debug_init, + .init = clk_fabia_pll_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_fabia_ops); @@ -1323,6 +1560,8 @@ const struct clk_ops clk_alpha_pll_fixed_fabia_ops = { .is_enabled = clk_alpha_pll_is_enabled, .recalc_rate = alpha_pll_fabia_recalc_rate, .round_rate = clk_alpha_pll_round_rate, + .debug_init = clk_common_debug_init, + .init = clk_fabia_pll_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_fabia_ops); @@ -1617,9 +1856,74 @@ const struct clk_ops clk_alpha_pll_trion_ops = { .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = alpha_pll_trion_set_rate, + .debug_init = clk_common_debug_init, + .init = clk_trion_pll_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_trion_ops); +static void lucid_pll_list_registers(struct seq_file *f, + struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_CAL_L_VAL", PLL_OFF_CAL_L_VAL}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_USER_CTL_U", PLL_OFF_USER_CTL_U}, + {"PLL_USER_CTL_U1", PLL_OFF_USER_CTL_U1}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, + {"PLL_CONFIG_CTL_U1", PLL_OFF_CONFIG_CTL_U1}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_TEST_CTL_U1", PLL_OFF_TEST_CTL_U1}, + {"PLL_STATUS", PLL_OFF_STATUS}, + {"PLL_OPMODE", PLL_OFF_OPMODE}, + {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, + {"PLL_SSC_DELTA_ALPHA", PLL_OFF_SSC_DELTA_ALPHA}, + {"PLL_SSC_NUM_STEPS", PLL_OFF_SSC_NUM_STEPS}, + {"PLL_SSC_UPDATE_RATE", PLL_OFF_SSC_UPDATE_RATE}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[0].offset], &val); + + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[0].name, val); + } +} + +static struct clk_regmap_ops clk_lucid_pll_regmap_ops = { + .list_registers = &lucid_pll_list_registers, +}; + +static int clk_lucid_pll_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_lucid_pll_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_lucid_ops = { .prepare = alpha_pll_lucid_prepare, .unprepare = clk_unprepare_regmap, @@ -1631,6 +1935,8 @@ const struct clk_ops clk_alpha_pll_lucid_ops = { .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = alpha_pll_trion_set_rate, + .debug_init = clk_common_debug_init, + .init = clk_lucid_pll_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops); @@ -1683,6 +1989,59 @@ static int clk_alpha_pll_agera_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } +static void clk_agera_pll_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_STATUS", PLL_OFF_STATUS}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], + &val); + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[0].name, val); + } +} + +static struct clk_regmap_ops clk_agera_pll_regmap_ops = { + .list_registers = clk_agera_pll_list_registers, +}; + +static int clk_agera_pll_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_agera_pll_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_agera_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -1694,6 +2053,8 @@ const struct clk_ops clk_alpha_pll_agera_ops = { .recalc_rate = alpha_pll_fabia_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = clk_alpha_pll_agera_set_rate, + .debug_init = clk_common_debug_init, + .init = clk_agera_pll_init, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops); @@ -1852,6 +2213,8 @@ const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = { .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = alpha_pll_lucid_5lpe_set_rate, + .debug_init = clk_common_debug_init, + .init = clk_lucid_pll_init, }; EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops); @@ -1865,6 +2228,8 @@ const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops = { .is_enabled = clk_trion_pll_is_enabled, .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, + .debug_init = clk_common_debug_init, + .init = clk_lucid_pll_init, }; EXPORT_SYMBOL(clk_alpha_pll_fixed_lucid_5lpe_ops); @@ -2018,6 +2383,65 @@ static int clk_zonda_pll_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } +static void clk_alpha_pll_zonda_list_registers(struct seq_file *f, + struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, + {"PLL_CONFIG_CTL_U1", PLL_OFF_CONFIG_CTL_U1}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_TEST_CTL_U1", PLL_OFF_TEST_CTL_U1}, + {"PLL_OPMODE", PLL_OFF_OPMODE}, + {"PLL_STATUS", PLL_OFF_STATUS}, + {"PLL_SSC_DELTA_ALPHA", PLL_OFF_SSC_DELTA_ALPHA}, + {"PLL_SSC_UPDATE_RATE", PLL_OFF_SSC_UPDATE_RATE}, + }; + + static struct clk_register_data data1[] = { + {"APSS_PLL_VOTE", 0x0}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], + &val); + + if (val & PLL_FSM_ENA) { + regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + + data1[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); + } +} + +static struct clk_regmap_ops clk_alpha_pll_zonda_regmap_ops = { + .list_registers = clk_alpha_pll_zonda_list_registers, +}; + +static int clk_alpha_pll_zonda_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_alpha_pll_zonda_regmap_ops; + + return 0; +} + const struct clk_ops clk_alpha_pll_zonda_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -2029,5 +2453,7 @@ const struct clk_ops clk_alpha_pll_zonda_ops = { .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .set_rate = clk_zonda_pll_set_rate, + .debug_init = clk_common_debug_init, + .init = clk_alpha_pll_zonda_init, }; EXPORT_SYMBOL(clk_alpha_pll_zonda_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 2b692eca6a50..9370cbe9a200 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015, 2018, 2021, The Linux Foundation. All rights reserved. */ #ifndef __QCOM_CLK_ALPHA_PLL_H__ #define __QCOM_CLK_ALPHA_PLL_H__ @@ -21,6 +21,7 @@ enum { }; enum { + PLL_OFF_MODE, PLL_OFF_L_VAL, PLL_OFF_CAL_L_VAL, PLL_OFF_ALPHA_VAL, @@ -38,6 +39,9 @@ enum { PLL_OFF_OPMODE, PLL_OFF_FRAC, PLL_OFF_CAL_VAL, + PLL_OFF_SSC_DELTA_ALPHA, + PLL_OFF_SSC_NUM_STEPS, + PLL_OFF_SSC_UPDATE_RATE, PLL_OFF_MAX_REGS }; diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 6ff66f18908a..adfd271dc827 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013, 2016, 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016, 2020-2021, The Linux Foundation. All rights reserved. */ #include @@ -14,6 +14,8 @@ #include #include "clk-branch.h" +#include "clk-debug.h" +#include "clk-regmap.h" static bool clk_branch_in_hwcg_mode(const struct clk_branch *br) { @@ -125,10 +127,17 @@ static void clk_branch_disable(struct clk_hw *hw) clk_branch_toggle(hw, false, clk_branch_check_halt); } +static void clk_branch_debug_init(struct clk_hw *hw, struct dentry *dentry) +{ + clk_common_debug_init(hw, dentry); + clk_debug_measure_add(hw, dentry); +} + const struct clk_ops clk_branch_ops = { .enable = clk_branch_enable, .disable = clk_branch_disable, .is_enabled = clk_is_enabled_regmap, + .debug_init = clk_branch_debug_init, }; EXPORT_SYMBOL_GPL(clk_branch_ops); @@ -162,6 +171,57 @@ static void clk_branch2_force_off_disable(struct clk_hw *hw) clk_branch2_disable(hw); } +static void clk_branch2_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_branch *br = to_clk_branch(hw); + struct clk_regmap *rclk = to_clk_regmap(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"CBCR", 0x0}, + }; + + static struct clk_register_data data1[] = { + {"APSS_VOTE", 0x0}, + {"APSS_SLEEP_VOTE", 0x4}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(br->clkr.regmap, br->halt_reg + data[i].offset, + &val); + seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val); + } + + if ((br->halt_check & BRANCH_HALT_VOTED) && + !(br->halt_check & BRANCH_VOTED)) { + if (rclk->enable_reg) { + size = ARRAY_SIZE(data1); + for (i = 0; i < size; i++) { + regmap_read(br->clkr.regmap, rclk->enable_reg + + data1[i].offset, &val); + seq_printf(f, "%20s: 0x%.8x\n", + data1[i].name, val); + } + } + } +} + +static struct clk_regmap_ops clk_branch2_regmap_ops = { + .list_registers = clk_branch2_list_registers, +}; + +static int clk_branch2_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_branch2_regmap_ops; + + return 0; +} + const struct clk_ops clk_branch2_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -170,12 +230,16 @@ const struct clk_ops clk_branch2_ops = { .enable = clk_branch2_enable, .disable = clk_branch2_disable, .is_enabled = clk_is_enabled_regmap, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, }; EXPORT_SYMBOL_GPL(clk_branch2_ops); const struct clk_ops clk_branch2_aon_ops = { .enable = clk_branch2_enable, .is_enabled = clk_is_enabled_regmap, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, }; EXPORT_SYMBOL_GPL(clk_branch2_aon_ops); @@ -183,6 +247,8 @@ const struct clk_ops clk_branch2_force_off_ops = { .enable = clk_branch2_force_off_enable, .disable = clk_branch2_force_off_disable, .is_enabled = clk_is_enabled_regmap, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, }; EXPORT_SYMBOL(clk_branch2_force_off_ops); @@ -234,6 +300,8 @@ const struct clk_ops clk_branch2_hw_ctl_ops = { .is_enabled = clk_is_enabled_regmap, .recalc_rate = clk_branch2_hw_ctl_recalc_rate, .determine_rate = clk_branch2_hw_ctl_determine_rate, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, }; EXPORT_SYMBOL(clk_branch2_hw_ctl_ops); @@ -241,6 +309,8 @@ const struct clk_ops clk_branch_simple_ops = { .enable = clk_enable_regmap, .disable = clk_disable_regmap, .is_enabled = clk_is_enabled_regmap, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, }; EXPORT_SYMBOL_GPL(clk_branch_simple_ops); diff --git a/drivers/clk/qcom/clk-dummy.c b/drivers/clk/qcom/clk-dummy.c index 7e624381773e..c3a356e388bf 100644 --- a/drivers/clk/qcom/clk-dummy.c +++ b/drivers/clk/qcom/clk-dummy.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, 2021, The Linux Foundation. All rights reserved. */ #include @@ -11,6 +11,7 @@ #include #include "common.h" +#include "clk-debug.h" #define to_clk_dummy(_hw) container_of(_hw, struct clk_dummy, hw) @@ -49,6 +50,7 @@ const struct clk_ops clk_dummy_ops = { .set_rate = dummy_clk_set_rate, .round_rate = dummy_clk_round_rate, .recalc_rate = dummy_clk_recalc_rate, + .debug_init = clk_debug_measure_add, }; EXPORT_SYMBOL(clk_dummy_ops); diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 1d6bd7705050..0c6b7a83c367 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -20,6 +20,7 @@ #include "clk-rcg.h" #include "common.h" +#include "clk-debug.h" #define CMD_REG 0x0 #define CMD_UPDATE BIT(0) @@ -447,6 +448,61 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) return update_config(rcg); } +static void clk_rcg2_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + int i = 0, size = 0, val; + + static struct clk_register_data data[] = { + {"CMD_RCGR", 0x0}, + {"CFG_RCGR", 0x4}, + }; + + static struct clk_register_data data1[] = { + {"CMD_RCGR", 0x0}, + {"CFG_RCGR", 0x4}, + {"M_VAL", 0x8}, + {"N_VAL", 0xC}, + {"D_VAL", 0x10}, + }; + + if (rcg->mnd_width) { + size = ARRAY_SIZE(data1); + for (i = 0; i < size; i++) { + regmap_read(rcg->clkr.regmap, (rcg->cmd_rcgr + + data1[i].offset), &val); + seq_printf(f, "%20s: 0x%.8x\n", data1[i].name, val); + } + } else { + size = ARRAY_SIZE(data); + for (i = 0; i < size; i++) { + regmap_read(rcg->clkr.regmap, (rcg->cmd_rcgr + + data[i].offset), &val); + seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val); + } + } +} + +/* Return the nth supported frequency for a given clock. */ +static long clk_rcg2_list_rate(struct clk_hw *hw, unsigned int n, + unsigned long fmax) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const struct freq_tbl *f = rcg->freq_tbl; + size_t freq_tbl_size = 0; + + if (!f) + return -ENXIO; + + for (; f->freq; f++) + freq_tbl_size++; + + if (n > freq_tbl_size - 1) + return -EINVAL; + + return (rcg->freq_tbl + n)->freq; +} + static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, enum freq_policy policy) { @@ -708,6 +764,21 @@ static void clk_rcg2_disable(struct clk_hw *hw) clk_rcg2_clear_force_enable(hw); } +static struct clk_regmap_ops clk_rcg2_regmap_ops = { + .list_rate = clk_rcg2_list_rate, + .list_registers = clk_rcg2_list_registers, +}; + +static int clk_rcg2_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_rcg2_regmap_ops; + + return 0; +} + const struct clk_ops clk_rcg2_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -724,6 +795,8 @@ const struct clk_ops clk_rcg2_ops = { .set_rate_and_parent = clk_rcg2_set_rate_and_parent, .get_duty_cycle = clk_rcg2_get_duty_cycle, .set_duty_cycle = clk_rcg2_set_duty_cycle, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_rcg2_ops); @@ -741,6 +814,8 @@ const struct clk_ops clk_rcg2_floor_ops = { .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent, .get_duty_cycle = clk_rcg2_get_duty_cycle, .set_duty_cycle = clk_rcg2_set_duty_cycle, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); @@ -874,6 +949,8 @@ const struct clk_ops clk_edp_pixel_ops = { .set_rate = clk_edp_pixel_set_rate, .set_rate_and_parent = clk_edp_pixel_set_rate_and_parent, .determine_rate = clk_edp_pixel_determine_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_edp_pixel_ops); @@ -938,6 +1015,8 @@ const struct clk_ops clk_byte_ops = { .set_rate = clk_byte_set_rate, .set_rate_and_parent = clk_byte_set_rate_and_parent, .determine_rate = clk_byte_determine_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_byte_ops); @@ -1013,6 +1092,8 @@ const struct clk_ops clk_byte2_ops = { .set_rate = clk_byte2_set_rate, .set_rate_and_parent = clk_byte2_set_rate_and_parent, .determine_rate = clk_byte2_determine_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_byte2_ops); @@ -1110,6 +1191,8 @@ const struct clk_ops clk_pixel_ops = { .set_rate = clk_pixel_set_rate, .set_rate_and_parent = clk_pixel_set_rate_and_parent, .determine_rate = clk_pixel_determine_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_pixel_ops); @@ -1221,6 +1304,8 @@ const struct clk_ops clk_gfx3d_ops = { .set_rate = clk_gfx3d_set_rate, .set_rate_and_parent = clk_gfx3d_set_rate_and_parent, .determine_rate = clk_gfx3d_determine_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_gfx3d_ops); @@ -1332,6 +1417,8 @@ const struct clk_ops clk_rcg2_shared_ops = { .determine_rate = clk_rcg2_determine_rate, .set_rate = clk_rcg2_shared_set_rate, .set_rate_and_parent = clk_rcg2_shared_set_rate_and_parent, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops); @@ -1481,6 +1568,8 @@ static const struct clk_ops clk_rcg2_dfs_ops = { .get_parent = clk_rcg2_get_parent, .determine_rate = clk_rcg2_dfs_determine_rate, .recalc_rate = clk_rcg2_dfs_recalc_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; static int clk_rcg2_enable_dfs(const struct clk_rcg_dfs_data *data, @@ -1609,5 +1698,7 @@ const struct clk_ops clk_dp_ops = { .set_rate = clk_rcg2_dp_set_rate, .set_rate_and_parent = clk_rcg2_dp_set_rate_and_parent, .determine_rate = clk_rcg2_dp_determine_rate, + .init = clk_rcg2_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_dp_ops); diff --git a/drivers/clk/qcom/clk-regmap.c b/drivers/clk/qcom/clk-regmap.c index e91d3a3161fe..087ae0c73090 100644 --- a/drivers/clk/qcom/clk-regmap.c +++ b/drivers/clk/qcom/clk-regmap.c @@ -10,6 +10,7 @@ #include #include "clk-regmap.h" +#include "clk-debug.h" static LIST_HEAD(clk_regmap_list); static DEFINE_MUTEX(clk_regmap_lock); @@ -300,6 +301,8 @@ int devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk) mutex_lock(&clk_regmap_lock); list_add(&rclk->list_node, &clk_regmap_list); mutex_unlock(&clk_regmap_lock); + + ret = clk_hw_debug_register(dev, &rclk->hw); } return ret; diff --git a/drivers/clk/qcom/clk-regmap.h b/drivers/clk/qcom/clk-regmap.h index b05cab443cbe..bf4cae8805af 100644 --- a/drivers/clk/qcom/clk-regmap.h +++ b/drivers/clk/qcom/clk-regmap.h @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2014, 2019-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2014, 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef __QCOM_CLK_REGMAP_H__ #define __QCOM_CLK_REGMAP_H__ #include +#include #include "vdd-class.h" struct regmap; @@ -72,4 +73,9 @@ bool clk_is_regmap_clk(struct clk_hw *hw); int clk_runtime_get_regmap(struct clk_regmap *rclk); void clk_runtime_put_regmap(struct clk_regmap *rclk); +struct clk_register_data { + char *name; + u32 offset; +}; + #endif