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

Commit a3095a5c authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dts: msm: Add cx gdsc control for A640 GPU"

parents a95b107d 6a6c0579
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@ Optional properties:
			[1] for details.
 - qcom,msm-bus,vectors-KBps: Required if qcom,msm-bus,name is specified.  See
			[1] for an explanation of the data format.
 - mboxes:		Mailbox tuple containing QMP mailbox phandle and channel
			identifier.  If this is specified, then a QMP message
			should be sent to enable the GDSC instead of setting
			SW_COLLAPSE=0.

[1]: Documentation/devicetree/bindings/arm/msm/msm_bus.txt

+1 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@
		qcom,skip-disable;
		qcom,gds-timeout = <500>;
		qcom,clk-dis-wait-val = <8>;
		mboxes = <&qmp_aop 0>;
		status = "disabled";
	};

+1 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@
		qcom,initial-pwrlevel = <5>;

		qcom,gpu-quirk-secvid-set-once;
		qcom,gpu-quirk-cx-gdsc;

		qcom,idle-timeout = <80>; //msecs
		qcom,no-nap;
+103 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/mailbox_client.h>
#include <linux/msm-bus.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
@@ -28,6 +29,7 @@
#include <linux/reset.h>
#include <linux/mfd/syscon.h>
#include <linux/clk/qcom.h>
#include <linux/mailbox/qmp.h>

#include <dt-bindings/regulator/qcom,rpmh-regulator.h>

@@ -52,6 +54,8 @@
/* Timeout Delay */
#define TIMEOUT_US		100

#define MBOX_TOUT_MS		100

struct gdsc {
	struct regulator_dev	*rdev;
	struct regulator_desc	rdesc;
@@ -64,6 +68,8 @@ struct gdsc {
	struct regulator	*parent_regulator;
	struct reset_control	**reset_clocks;
	struct msm_bus_scale_pdata *bus_pdata;
	struct mbox_client	mbox_client;
	struct mbox_chan	*mbox;
	u32			bus_handle;
	bool			toggle_mem;
	bool			toggle_periph;
@@ -73,6 +79,7 @@ struct gdsc {
	bool			force_root_en;
	bool			no_status_check_on_disable;
	bool			skip_disable;
	bool			bypass_skip_disable;
	bool			is_gdsc_enabled;
	bool			allow_clear;
	bool			reset_aon;
@@ -218,6 +225,35 @@ static int gdsc_is_enabled(struct regulator_dev *rdev)
	return is_enabled;
}

#define MAX_LEN 96

static int gdsc_qmp_enable(struct gdsc *sc)
{
	char buf[MAX_LEN] = "{class: clock, res: gpu_noc_wa}";
	struct qmp_pkt pkt;
	uint32_t regval;
	int ret;

	regmap_read(sc->regmap, REG_OFFSET, &regval);
	if (!(regval & SW_COLLAPSE_MASK)) {
		/*
		 * Do not enable via a QMP request if the GDSC is already
		 * enabled by software.
		 */
		return 0;
	}

	pkt.size = MAX_LEN;
	pkt.data = buf;

	ret = mbox_send_message(sc->mbox, &pkt);
	if (ret < 0)
		dev_err(&sc->rdev->dev, "qmp message send failed, ret=%d\n",
			ret);

	return ret;
}

static int gdsc_enable(struct regulator_dev *rdev)
{
	struct gdsc *sc = rdev_get_drvdata(rdev);
@@ -308,9 +344,15 @@ static int gdsc_enable(struct regulator_dev *rdev)
			gdsc_mb(sc);
		}

		if (sc->mbox) {
			ret = gdsc_qmp_enable(sc);
			if (ret < 0)
				goto end;
		} else {
			regmap_read(sc->regmap, REG_OFFSET, &regval);
			regval &= ~SW_COLLAPSE_MASK;
			regmap_write(sc->regmap, REG_OFFSET, regval);
		}

		/* Wait for 8 XO cycles before polling the status bit. */
		gdsc_mb(sc);
@@ -426,7 +468,7 @@ static int gdsc_disable(struct regulator_dev *rdev)
	/* Delay to account for staggered memory powerdown. */
	udelay(1);

	if (sc->skip_disable) {
	if (sc->skip_disable && !sc->bypass_skip_disable) {
		/*
		 * Don't change the GDSCR register state on disable.  AOP will
		 * handle this during system sleep.
@@ -497,6 +539,12 @@ static unsigned int gdsc_get_mode(struct regulator_dev *rdev)
	uint32_t regval;
	int ret;

	if (sc->skip_disable) {
		if (sc->bypass_skip_disable)
			return REGULATOR_MODE_IDLE;
		return REGULATOR_MODE_NORMAL;
	}

	mutex_lock(&gdsc_seq_lock);

	if (sc->parent_regulator) {
@@ -556,6 +604,23 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode)

	mutex_lock(&gdsc_seq_lock);

	if (sc->skip_disable) {
		switch (mode) {
		case REGULATOR_MODE_IDLE:
			sc->bypass_skip_disable = true;
			break;
		case REGULATOR_MODE_NORMAL:
			sc->bypass_skip_disable = false;
			break;
		default:
			ret = -EINVAL;
			break;
		}

		mutex_unlock(&gdsc_seq_lock);
		return ret;
	}

	if (sc->parent_regulator) {
		ret = regulator_set_voltage(sc->parent_regulator,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
@@ -817,6 +882,23 @@ static int gdsc_probe(struct platform_device *pdev)
		sc->is_bus_enabled = true;
	}

	if (of_find_property(pdev->dev.of_node, "mboxes", NULL)) {
		sc->mbox_client.dev = &pdev->dev;
		sc->mbox_client.tx_block = true;
		sc->mbox_client.tx_tout = MBOX_TOUT_MS;
		sc->mbox_client.knows_txdone = false;

		sc->mbox = mbox_request_channel(&sc->mbox_client, 0);
		if (IS_ERR(sc->mbox)) {
			ret = PTR_ERR(sc->mbox);
			if (ret != -EPROBE_DEFER)
				dev_err(&pdev->dev, "mailbox channel request failed, ret=%d\n",
					ret);
			sc->mbox = NULL;
			goto err;
		}
	}

	sc->rdesc.id = atomic_inc_return(&gdsc_count);
	sc->rdesc.ops = &gdsc_ops;
	sc->rdesc.type = REGULATOR_VOLTAGE;
@@ -862,6 +944,17 @@ static int gdsc_probe(struct platform_device *pdev)
				REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
	}

	if (sc->skip_disable) {
		/*
		 * If the disable skipping feature is allowed, then use mode
		 * control to enable and disable the feature at runtime instead
		 * of using it to enable and disable hardware triggering.
		 */
		init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
		init_data->constraints.valid_modes_mask =
				REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE;
	}

	if (!sc->toggle_logic) {
		sc->reset_count = of_property_count_strings(pdev->dev.of_node,
					    "reset-names");
@@ -955,6 +1048,9 @@ static int gdsc_probe(struct platform_device *pdev)
	return 0;

err:
	if (sc->mbox)
		mbox_free_channel(sc->mbox);

	if (sc->bus_handle) {
		if (sc->is_bus_enabled)
			msm_bus_scale_client_update_request(sc->bus_handle, 0);
@@ -970,6 +1066,9 @@ static int gdsc_remove(struct platform_device *pdev)

	regulator_unregister(sc->rdev);

	if (sc->mbox)
		mbox_free_channel(sc->mbox);

	if (sc->bus_handle) {
		if (sc->is_bus_enabled)
			msm_bus_scale_client_update_request(sc->bus_handle, 0);