Commit 697fa27d authored by Peter Griffin's avatar Peter Griffin Committed by Philipp Zabel
Browse files

reset: hi6220: Add support for AO reset controller



This is required to bring Mali450 gpu out of reset.

Cc: Peter Griffin <peter.griffin@linaro.org>
Cc: Enrico Weigelt <info@metux.net>
Signed-off-by: default avatarPeter Griffin <peter.griffin@linaro.org>
[jstultz: Added comment, Fix void return build issue
Reported-by: default avatarkbuild test robot <lkp@intel.com&gt;]>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent e08672c0
Loading
Loading
Loading
Loading
+68 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
enum hi6220_reset_ctrl_type {
	PERIPHERAL,
	MEDIA,
	AO,
};

struct hi6220_reset_data {
@@ -92,6 +93,65 @@ static const struct reset_control_ops hi6220_media_reset_ops = {
	.deassert = hi6220_media_deassert,
};

#define AO_SCTRL_SC_PW_CLKEN0     0x800
#define AO_SCTRL_SC_PW_CLKDIS0    0x804

#define AO_SCTRL_SC_PW_RSTEN0     0x810
#define AO_SCTRL_SC_PW_RSTDIS0    0x814

#define AO_SCTRL_SC_PW_ISOEN0     0x820
#define AO_SCTRL_SC_PW_ISODIS0    0x824
#define AO_MAX_INDEX              12

static int hi6220_ao_assert(struct reset_controller_dev *rc_dev,
			       unsigned long idx)
{
	struct hi6220_reset_data *data = to_reset_data(rc_dev);
	struct regmap *regmap = data->regmap;
	int ret;

	ret = regmap_write(regmap, AO_SCTRL_SC_PW_RSTEN0, BIT(idx));
	if (ret)
		return ret;

	ret = regmap_write(regmap, AO_SCTRL_SC_PW_ISOEN0, BIT(idx));
	if (ret)
		return ret;

	ret = regmap_write(regmap, AO_SCTRL_SC_PW_CLKDIS0, BIT(idx));
	return ret;
}

static int hi6220_ao_deassert(struct reset_controller_dev *rc_dev,
				 unsigned long idx)
{
	struct hi6220_reset_data *data = to_reset_data(rc_dev);
	struct regmap *regmap = data->regmap;
	int ret;

	/*
	 * It was suggested to disable isolation before enabling
	 * the clocks and deasserting reset, to avoid glitches.
	 * But this order is preserved to keep it matching the
	 * vendor code.
	 */
	ret = regmap_write(regmap, AO_SCTRL_SC_PW_RSTDIS0, BIT(idx));
	if (ret)
		return ret;

	ret = regmap_write(regmap, AO_SCTRL_SC_PW_ISODIS0, BIT(idx));
	if (ret)
		return ret;

	ret = regmap_write(regmap, AO_SCTRL_SC_PW_CLKEN0, BIT(idx));
	return ret;
}

static const struct reset_control_ops hi6220_ao_reset_ops = {
	.assert = hi6220_ao_assert,
	.deassert = hi6220_ao_deassert,
};

static int hi6220_reset_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
@@ -117,9 +177,12 @@ static int hi6220_reset_probe(struct platform_device *pdev)
	if (type == MEDIA) {
		data->rc_dev.ops = &hi6220_media_reset_ops;
		data->rc_dev.nr_resets = MEDIA_MAX_INDEX;
	} else {
	} else if (type == PERIPHERAL) {
		data->rc_dev.ops = &hi6220_peripheral_reset_ops;
		data->rc_dev.nr_resets = PERIPH_MAX_INDEX;
	} else {
		data->rc_dev.ops = &hi6220_ao_reset_ops;
		data->rc_dev.nr_resets = AO_MAX_INDEX;
	}

	return reset_controller_register(&data->rc_dev);
@@ -134,6 +197,10 @@ static const struct of_device_id hi6220_reset_match[] = {
		.compatible = "hisilicon,hi6220-mediactrl",
		.data = (void *)MEDIA,
	},
	{
		.compatible = "hisilicon,hi6220-aoctrl",
		.data = (void *)AO,
	},
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, hi6220_reset_match);