From db9bcd7bd9ec24f12c924282e059d84e5c2cfff3 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Tue, 23 Feb 2021 08:22:04 +0530 Subject: [PATCH] clk: qcom: clk-debug: Add support to dump GDSC registers Add support to dump client's GDSC registers when client passes a regulator(GDSC) handle to clock dump functions. While at it, increase the GDSC regmap size to include all GDSC registers. And for legacy HW, that only supports single GDSCR per GDSC, 'qcom,no-config-gdscr' flag can be specified in GDSC DT node to decrease the regmap size and map only single GDSCR. Change-Id: Ia03c647deae9ffe9df93be60abd901bef25c3503 Signed-off-by: Jagadeesh Kona --- drivers/clk/qcom/clk-debug.c | 26 ++++++++++++++++------- drivers/clk/qcom/gdsc-debug.h | 11 ++++++++++ drivers/clk/qcom/gdsc-regulator.c | 34 +++++++++++++++++++++++++++++-- include/linux/clk/qcom.h | 8 +++++--- 4 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 drivers/clk/qcom/gdsc-debug.h diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c index 35528d1d2b98..6a0dbadd3442 100644 --- a/drivers/clk/qcom/clk-debug.c +++ b/drivers/clk/qcom/clk-debug.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016, 2019-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016, 2019-2021, The Linux Foundation. All rights reserved. */ #include #include @@ -15,6 +15,7 @@ #include "clk-regmap.h" #include "clk-debug.h" +#include "gdsc-debug.h" static struct clk_hw *measure; @@ -565,16 +566,22 @@ void clk_common_debug_init(struct clk_hw *hw, struct dentry *dentry) /** * qcom_clk_dump - dump the HW specific registers associated with this clock + * and regulator * @clk: clock source + * @regulator: regulator * @calltrace: indicates whether calltrace is required * * This function attempts to print all the registers associated with the - * clock and it's parents. + * clock, it's parents and regulator. */ -void qcom_clk_dump(struct clk *clk, bool calltrace) +void qcom_clk_dump(struct clk *clk, struct regulator *regulator, + bool calltrace) { struct clk_hw *hw; + if (!IS_ERR_OR_NULL(regulator)) + gdsc_debug_print_regs(regulator); + if (IS_ERR_OR_NULL(clk)) return; @@ -589,22 +596,27 @@ EXPORT_SYMBOL(qcom_clk_dump); /** * qcom_clk_bulk_dump - dump the HW specific registers associated with clocks - * @clks: the clk_bulk_data table of consumer + * and regulator * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * @regulator: regulator source * @calltrace: indicates whether calltrace is required * * This function attempts to print all the registers associated with the - * clock and it's parents for all the clocks in the list. + * clocks in the list and regulator. */ void qcom_clk_bulk_dump(int num_clks, struct clk_bulk_data *clks, - bool calltrace) + struct regulator *regulator, bool calltrace) { int i; + if (!IS_ERR_OR_NULL(regulator)) + gdsc_debug_print_regs(regulator); + if (IS_ERR_OR_NULL(clks)) return; for (i = 0; i < num_clks; i++) - qcom_clk_dump(clks[i].clk, calltrace); + qcom_clk_dump(clks[i].clk, NULL, calltrace); } EXPORT_SYMBOL(qcom_clk_bulk_dump); diff --git a/drivers/clk/qcom/gdsc-debug.h b/drivers/clk/qcom/gdsc-debug.h new file mode 100644 index 000000000000..5f1798ef2078 --- /dev/null +++ b/drivers/clk/qcom/gdsc-debug.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef __QCOM_GDSC_DEBUG_H__ +#define __QCOM_GDSC_DEBUG_H__ + +void gdsc_debug_print_regs(struct regulator *regulator); + +#endif /* __QCOM_GDSC_DEBUG_H__ */ diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c index 9f1e9e61054e..abbe34609675 100644 --- a/drivers/clk/qcom/gdsc-regulator.c +++ b/drivers/clk/qcom/gdsc-regulator.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -21,6 +21,7 @@ #include #include "../../regulator/internal.h" +#include "gdsc-debug.h" /* GDSCR */ #define PWR_ON_MASK BIT(31) @@ -566,13 +567,38 @@ static struct regulator_ops gdsc_ops = { .get_mode = gdsc_get_mode, }; -static const struct regmap_config gdsc_regmap_config = { +static struct regmap_config gdsc_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, + .max_register = 0x8, .fast_io = true, }; +void gdsc_debug_print_regs(struct regulator *regulator) +{ + struct gdsc *sc = rdev_get_drvdata(regulator->rdev); + uint32_t regvals[3] = {0}; + int ret; + + if (!sc) { + pr_err("Failed to get GDSC Handle\n"); + return; + } + + ret = regmap_bulk_read(sc->regmap, REG_OFFSET, regvals, + gdsc_regmap_config.max_register ? 3 : 1); + if (ret) { + pr_err("Failed to read %s registers\n", sc->rdesc.name); + return; + } + + pr_info("Dumping %s Registers:\n", sc->rdesc.name); + pr_info("GDSCR: 0x%.8x CFG: 0x%.8x CFG2: 0x%.8x\n", + regvals[0], regvals[1], regvals[2]); +} +EXPORT_SYMBOL(gdsc_debug_print_regs); + static int gdsc_parse_dt_data(struct gdsc *sc, struct device *dev, struct regulator_init_data **init_data) { @@ -712,6 +738,10 @@ static int gdsc_get_resources(struct gdsc *sc, struct platform_device *pdev) if (sc->gdscr == NULL) return -ENOMEM; + + if (of_property_read_bool(dev->of_node, "qcom,no-config-gdscr")) + gdsc_regmap_config.max_register = 0; + sc->regmap = devm_regmap_init_mmio(dev, sc->gdscr, &gdsc_regmap_config); if (!sc->regmap) { dev_err(dev, "Couldn't get regmap\n"); diff --git a/include/linux/clk/qcom.h b/include/linux/clk/qcom.h index 8fe1d4afc775..efe7818d7ce2 100644 --- a/include/linux/clk/qcom.h +++ b/include/linux/clk/qcom.h @@ -1,12 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef __LINUX_CLK_QCOM_H_ #define __LINUX_CLK_QCOM_H_ #include +#include enum branch_mem_flags { CLKFLAG_RETAIN_PERIPH, @@ -19,8 +20,9 @@ enum branch_mem_flags { int qcom_clk_get_voltage(struct clk *clk, unsigned long rate); int qcom_clk_set_flags(struct clk *clk, unsigned long flags); -void qcom_clk_dump(struct clk *clk, bool calltrace); -void qcom_clk_bulk_dump(int num_clks, struct clk_bulk_data *clks, +void qcom_clk_dump(struct clk *clk, struct regulator *regulator, bool calltrace); +void qcom_clk_bulk_dump(int num_clks, struct clk_bulk_data *clks, + struct regulator *regulator, bool calltrace); #endif /* __LINUX_CLK_QCOM_H_ */