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

Commit ada604f0 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Use bulk clock functions for GMU



Instead of using a bespoke function to get the list of clocks, use the
built in functions instead. To do this, we'll need a local function
to get a clock pointer by name from the list so this is a great time to
add a file just for general purpose driver functions.

Change-Id: Ic0dedbad96f478afc1a416a94df7c0e203ecca8a
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 3a2f09f3
Loading
Loading
Loading
Loading
+22 −71
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 */

#include <dt-bindings/regulator/qcom,rpmh-regulator-levels.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/io.h>
@@ -942,34 +943,6 @@ static int gmu_reg_probe(struct kgsl_device *device)
	return 0;
}

static int gmu_clocks_probe(struct gmu_device *gmu, struct device_node *node)
{
	const char *cname;
	struct property *prop;
	struct clk *c;
	int i = 0;

	of_property_for_each_string(node, "clock-names", prop, cname) {
		c = devm_clk_get(&gmu->pdev->dev, cname);

		if (IS_ERR(c)) {
			dev_err(&gmu->pdev->dev,
				"dt: Couldn't get GMU clock: %s\n", cname);
			return PTR_ERR(c);
		}

		if (i >= MAX_GMU_CLKS) {
			dev_err(&gmu->pdev->dev,
				"dt: too many GMU clocks defined\n");
			return -EINVAL;
		}

		gmu->clks[i++] = c;
	}

	return 0;
}

static int gmu_regulators_probe(struct gmu_device *gmu,
		struct device_node *node)
{
@@ -1206,11 +1179,20 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
	if (ret)
		goto error;

	/* Set up GMU clocks */
	ret = gmu_clocks_probe(gmu, node);
	if (ret)
	ret = devm_clk_bulk_get_all(&gmu->pdev->dev, &gmu->clks);
	if (ret < 0)
		goto error;

	gmu->num_clks = ret;

	/* Get a pointer to the GMU clock */
	gmu->gmu_clk = kgsl_of_clk_by_name(gmu->clks, gmu->num_clks, "gmu_clk");
	if (!gmu->gmu_clk) {
		dev_err(&gmu->pdev->dev, "Couldn't get gmu_clk\n");
		ret = -ENODEV;
		goto error;
	}

	/* Set up GMU IOMMU and shared memory with GMU */
	ret = gmu_iommu_init(gmu, node);
	if (ret)
@@ -1304,48 +1286,30 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
static int gmu_enable_clks(struct kgsl_device *device)
{
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	int ret, j = 0;

	if (IS_ERR_OR_NULL(gmu->clks[0]))
		return -EINVAL;
	int ret;

	ret = clk_set_rate(gmu->clks[0], GMU_FREQUENCY);
	ret = clk_set_rate(gmu->gmu_clk, GMU_FREQUENCY);
	if (ret) {
		dev_err(&gmu->pdev->dev, "fail to set default GMU clk freq %d\n",
				GMU_FREQUENCY);
		dev_err(&gmu->pdev->dev, "Unable to set GMU clock\n");
		return ret;
	}

	while ((j < MAX_GMU_CLKS) && gmu->clks[j]) {
		ret = clk_prepare_enable(gmu->clks[j]);
	ret = clk_bulk_prepare_enable(gmu->num_clks, gmu->clks);
	if (ret) {
			dev_err(&gmu->pdev->dev,
					"fail to enable gpucc clk idx %d\n",
					j);
		dev_err(&gmu->pdev->dev, "Cannot enable GMU clocks\n");
		return ret;
	}
		j++;
	}

	set_bit(GMU_CLK_ON, &device->gmu_core.flags);
	return 0;
}

static int gmu_disable_clks(struct kgsl_device *device)
static void gmu_disable_clks(struct kgsl_device *device)
{
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	int j = 0;

	if (IS_ERR_OR_NULL(gmu->clks[0]))
		return 0;

	while ((j < MAX_GMU_CLKS) && gmu->clks[j]) {
		clk_disable_unprepare(gmu->clks[j]);
		j++;
	}

	clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks);
	clear_bit(GMU_CLK_ON, &device->gmu_core.flags);
	return 0;

}

@@ -1592,7 +1556,6 @@ static void gmu_remove(struct kgsl_device *device)
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	struct kgsl_hfi *hfi;
	int i = 0;

	if (gmu == NULL || gmu->pdev == NULL)
		return;
@@ -1608,11 +1571,6 @@ static void gmu_remove(struct kgsl_device *device)

	clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag);

	while ((i < MAX_GMU_CLKS) && gmu->clks[i]) {
		gmu->clks[i] = NULL;
		i++;
	}

	icc_put(gmu->icc_path);

	if (gmu->fw_image) {
@@ -1622,13 +1580,6 @@ static void gmu_remove(struct kgsl_device *device)

	gmu_memory_close(gmu);

	for (i = 0; i < MAX_GMU_CLKS; i++) {
		if (gmu->clks[i]) {
			devm_clk_put(&gmu->pdev->dev, gmu->clks[i]);
			gmu->clks[i] = NULL;
		}
	}

	if (gmu->gx_gdsc) {
		devm_regulator_put(gmu->gx_gdsc);
		gmu->gx_gdsc = NULL;
+5 −1
Original line number Diff line number Diff line
@@ -206,7 +206,11 @@ struct gmu_device {
	struct rpmh_votes_t rpmh_votes;
	struct regulator *cx_gdsc;
	struct regulator *gx_gdsc;
	struct clk *clks[MAX_GMU_CLKS];
	struct clk_bulk_data *clks;
	/** @num_clks: Number of entries in the @clks array */
	int num_clks;
	/** @gmu_clk: Pointer to the core GMU clock */
	struct clk *gmu_clk;
	enum gmu_load_mode load_mode;
	unsigned int wakeup_pwrlevel;
	unsigned int pcl;
+0 −2
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@
#error "CNOC levels cannot exceed GX levels"
#endif

#define MAX_GMU_CLKS 6

/*
 * These are the different ways the GMU can boot. GMU_WARM_BOOT is waking up
 * from slumber. GMU_COLD_BOOT is booting for the first time. GMU_RESET
+16 −0
Original line number Diff line number Diff line
@@ -3,9 +3,13 @@
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 */


#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/regulator/consumer.h>
#include <linux/string.h>

#include "kgsl_util.h"

@@ -25,3 +29,15 @@ bool kgsl_regulator_disable_wait(struct regulator *reg, u32 timeout)
		usleep_range((100 >> 2) + 1, 100);
	}
}

struct clk *kgsl_of_clk_by_name(struct clk_bulk_data *clks, int count,
		const char *id)
{
	int i;

	for (i = 0; clks && i < count; i++)
		if (!strcmp(clks[i].id, id))
			return clks[i].clk;

	return NULL;
}
+12 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#define _KGSL_UTIL_H_

struct regulator;
struct clk_bulk_data;

/**
 * kgsl_regulator_disable_wait - Disable a regulator and wait for it
@@ -20,4 +21,15 @@ struct regulator;
 */
bool kgsl_regulator_disable_wait(struct regulator *reg, u32 timeout);

/**
 * kgsl_of_clk_by_name - Return a clock device for a given name
 * @clks: Pointer to an array of bulk clk data
 * @count: Number of entries in the array
 * @id: Name of the clock to search for
 *
 * Returns: A pointer to the clock device for the given name or NULL if not
 * found
 */
struct clk *kgsl_of_clk_by_name(struct clk_bulk_data *clks, int count,
		const char *id);
#endif