Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fd58eb7 authored by Deepak Katragadda's avatar Deepak Katragadda
Browse files

clk: qcom: gdsc: Fix issue with dereferencing NULL pointer in gdsc APIs



Fix the issue with deferencing the rdev structure for
the GDSC prior to it being populated. Replace the
qcom,vote-parent-supply-voltage property with
vdd_parent-supply and use the regulator handle that's
returned from calling regulator_get for the parent
regulator directly.

Change-Id: I9a80cbeb4fd88b718e6e7509d8868d965253ae5e
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
parent a8cbba84
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -50,10 +50,11 @@ Optional properties:
			to enable.
 - qcom,reset-aon-logic: If present, the GPU DEMET cells need to be reset while
			 enabling the GX GDSC.
 - qcom,vote-parent-supply-voltage: If present, need to vote for a minimum
			operational voltage (LOW_SVS) on the GDSC parent
			regulator prior to configuring it. The vote is removed
			once the GDSC FSM has latched on to the new state.
 - vdd_parent-supply:	phandle to the regulator that this GDSC gates. If
			present, need to vote for a minimum operational voltage
			(LOW_SVS) on the GDSC parent regulator prior to
			configuring it. The vote is removed once the GDSC FSM
			has latched on to the new state.
 - resets: reset specifier pair consisting of phandle for the reset controller
			and reset lines used by this controller. These can be
			supplied only if we support qcom,skip-logic-collapse.
+13 −13
Original line number Diff line number Diff line
@@ -1012,7 +1012,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1020,7 +1020,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1028,7 +1028,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1036,7 +1036,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1044,7 +1044,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1052,7 +1052,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1060,7 +1060,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1068,7 +1068,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1076,7 +1076,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_DISP_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1086,7 +1086,7 @@

&gpu_gx_gdsc {
	parent-supply = <&pm855_1_s10_level>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&pm855_1_s10_level>;
	status = "ok";
};

@@ -1094,7 +1094,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1102,7 +1102,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -1110,7 +1110,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

+11 −11
Original line number Diff line number Diff line
@@ -3234,7 +3234,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3242,7 +3242,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3250,7 +3250,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3258,7 +3258,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3266,7 +3266,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3274,7 +3274,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3282,7 +3282,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_DISP_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3292,7 +3292,7 @@

&gpu_gx_gdsc {
	parent-supply = <&pm855l_s2_level>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&pm855l_s2_level>;
	status = "ok";
};

@@ -3300,7 +3300,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3308,7 +3308,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

@@ -3316,7 +3316,7 @@
	clock-names = "ahb_clk";
	clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>;
	parent-supply = <&VDD_MMCX_LEVEL>;
	qcom,vote-parent-supply-voltage;
	vdd_parent-supply = <&VDD_MMCX_LEVEL>;
	status = "ok";
};

+26 −19
Original line number Diff line number Diff line
/*
 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -60,6 +60,7 @@ struct gdsc {
	struct regmap           *hw_ctrl;
	struct regmap           *sw_reset;
	struct clk		**clocks;
	struct regulator	*parent_regulator;
	struct reset_control	**reset_clocks;
	bool			toggle_mem;
	bool			toggle_periph;
@@ -71,7 +72,6 @@ struct gdsc {
	bool			is_gdsc_enabled;
	bool			allow_clear;
	bool			reset_aon;
	bool			vote_supply_voltage;
	int			clock_count;
	int			reset_count;
	int			root_clk_idx;
@@ -170,8 +170,8 @@ static int gdsc_enable(struct regulator_dev *rdev)

	mutex_lock(&gdsc_seq_lock);

	if (sc->vote_supply_voltage) {
		ret = regulator_set_voltage(sc->rdev->supply,
	if (sc->parent_regulator) {
		ret = regulator_set_voltage(sc->parent_regulator,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
		if (ret) {
			mutex_unlock(&gdsc_seq_lock);
@@ -316,8 +316,8 @@ static int gdsc_enable(struct regulator_dev *rdev)

	sc->is_gdsc_enabled = true;
end:
	if (sc->vote_supply_voltage)
		regulator_set_voltage(sc->rdev->supply, 0, INT_MAX);
	if (sc->parent_regulator)
		regulator_set_voltage(sc->parent_regulator, 0, INT_MAX);

	mutex_unlock(&gdsc_seq_lock);

@@ -332,8 +332,8 @@ static int gdsc_disable(struct regulator_dev *rdev)

	mutex_lock(&gdsc_seq_lock);

	if (sc->vote_supply_voltage) {
		ret = regulator_set_voltage(sc->rdev->supply,
	if (sc->parent_regulator) {
		ret = regulator_set_voltage(sc->parent_regulator,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
		if (ret) {
			mutex_unlock(&gdsc_seq_lock);
@@ -398,8 +398,8 @@ static int gdsc_disable(struct regulator_dev *rdev)
	if ((sc->is_gdsc_enabled && sc->root_en) || sc->force_root_en)
		clk_disable_unprepare(sc->clocks[sc->root_clk_idx]);

	if (sc->vote_supply_voltage)
		regulator_set_voltage(sc->rdev->supply, 0, INT_MAX);
	if (sc->parent_regulator)
		regulator_set_voltage(sc->parent_regulator, 0, INT_MAX);

	sc->is_gdsc_enabled = false;

@@ -431,8 +431,8 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode)

	mutex_lock(&gdsc_seq_lock);

	if (sc->vote_supply_voltage) {
		ret = regulator_set_voltage(sc->rdev->supply,
	if (sc->parent_regulator) {
		ret = regulator_set_voltage(sc->parent_regulator,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
		if (ret) {
			mutex_unlock(&gdsc_seq_lock);
@@ -483,8 +483,8 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode)
		break;
	}

	if (sc->vote_supply_voltage)
		regulator_set_voltage(sc->rdev->supply, 0, INT_MAX);
	if (sc->parent_regulator)
		regulator_set_voltage(sc->parent_regulator, 0, INT_MAX);

	mutex_unlock(&gdsc_seq_lock);

@@ -602,8 +602,18 @@ static int gdsc_probe(struct platform_device *pdev)
	sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
						"qcom,force-enable-root-clk");

	sc->vote_supply_voltage = of_property_read_bool(pdev->dev.of_node,
					"qcom,vote-parent-supply-voltage");
	if (of_find_property(pdev->dev.of_node, "vdd_parent-supply", NULL)) {
		sc->parent_regulator = devm_regulator_get(&pdev->dev,
							"vdd_parent");
		if (IS_ERR(sc->parent_regulator)) {
			ret = PTR_ERR(sc->parent_regulator);
			if (ret != -EPROBE_DEFER)
				dev_err(&pdev->dev,
				"Unable to get vdd_parent regulator, err: %d\n",
					ret);
			return ret;
		}
	}

	for (i = 0; i < sc->clock_count; i++) {
		const char *clock_name;
@@ -749,9 +759,6 @@ static int gdsc_probe(struct platform_device *pdev)
		return PTR_ERR(sc->rdev);
	}

	if (!sc->rdev->supply)
		sc->vote_supply_voltage = false;

	return 0;
}