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

Commit 380bf477 authored by Paul Geurts's avatar Paul Geurts Committed by Greg Kroah-Hartman
Browse files

NFC: trf7970a: disable all regulators on removal



[ Upstream commit 6bea4f03c6a4e973ef369e15aac88f37981db49e ]

During module probe, regulator 'vin' and 'vdd-io' are used and enabled,
but the vdd-io regulator overwrites the 'vin' regulator pointer. During
remove, only the vdd-io is disabled, as the vin regulator pointer is not
available anymore. When regulator_put() is called during resource
cleanup a kernel warning is given, as the regulator is still enabled.

Store the two regulators in separate pointers and disable both the
regulators on module remove.

Fixes: 49d22c70 ("NFC: trf7970a: Add device tree option of 1.8 Volt IO voltage")
Signed-off-by: default avatarPaul Geurts <paul_geurts@live.nl>
Reviewed-by: default avatarKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/DB7PR09MB26847A4EBF88D9EDFEB1DA0F950E2@DB7PR09MB2684.eurprd09.prod.outlook.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 42de7aa3
Loading
Loading
Loading
Loading
+23 −19
Original line number Original line Diff line number Diff line
@@ -424,7 +424,8 @@ struct trf7970a {
	enum trf7970a_state		state;
	enum trf7970a_state		state;
	struct device			*dev;
	struct device			*dev;
	struct spi_device		*spi;
	struct spi_device		*spi;
	struct regulator		*regulator;
	struct regulator		*vin_regulator;
	struct regulator		*vddio_regulator;
	struct nfc_digital_dev		*ddev;
	struct nfc_digital_dev		*ddev;
	u32				quirks;
	u32				quirks;
	bool				is_initiator;
	bool				is_initiator;
@@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
	if (trf->state != TRF7970A_ST_PWR_OFF)
	if (trf->state != TRF7970A_ST_PWR_OFF)
		return 0;
		return 0;


	ret = regulator_enable(trf->regulator);
	ret = regulator_enable(trf->vin_regulator);
	if (ret) {
	if (ret) {
		dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
		dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
		return ret;
		return ret;
@@ -1926,7 +1927,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
	if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
	if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
		gpiod_set_value_cansleep(trf->en2_gpiod, 0);
		gpiod_set_value_cansleep(trf->en2_gpiod, 0);


	ret = regulator_disable(trf->regulator);
	ret = regulator_disable(trf->vin_regulator);
	if (ret)
	if (ret)
		dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
		dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
			ret);
			ret);
@@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi)
	mutex_init(&trf->lock);
	mutex_init(&trf->lock);
	INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
	INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);


	trf->regulator = devm_regulator_get(&spi->dev, "vin");
	trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
	if (IS_ERR(trf->regulator)) {
	if (IS_ERR(trf->vin_regulator)) {
		ret = PTR_ERR(trf->regulator);
		ret = PTR_ERR(trf->vin_regulator);
		dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
		dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
		goto err_destroy_lock;
		goto err_destroy_lock;
	}
	}


	ret = regulator_enable(trf->regulator);
	ret = regulator_enable(trf->vin_regulator);
	if (ret) {
	if (ret) {
		dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
		dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
		goto err_destroy_lock;
		goto err_destroy_lock;
	}
	}


	uvolts = regulator_get_voltage(trf->regulator);
	uvolts = regulator_get_voltage(trf->vin_regulator);
	if (uvolts > 4000000)
	if (uvolts > 4000000)
		trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
		trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;


	trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
	trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
	if (IS_ERR(trf->regulator)) {
	if (IS_ERR(trf->vddio_regulator)) {
		ret = PTR_ERR(trf->regulator);
		ret = PTR_ERR(trf->vddio_regulator);
		dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
		dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
		goto err_destroy_lock;
		goto err_disable_vin_regulator;
	}
	}


	ret = regulator_enable(trf->regulator);
	ret = regulator_enable(trf->vddio_regulator);
	if (ret) {
	if (ret) {
		dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
		dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
		goto err_destroy_lock;
		goto err_disable_vin_regulator;
	}
	}


	if (regulator_get_voltage(trf->regulator) == 1800000) {
	if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
		trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
		trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
		dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
		dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
	}
	}
@@ -2108,7 +2109,7 @@ static int trf7970a_probe(struct spi_device *spi)
	if (!trf->ddev) {
	if (!trf->ddev) {
		dev_err(trf->dev, "Can't allocate NFC digital device\n");
		dev_err(trf->dev, "Can't allocate NFC digital device\n");
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err_disable_regulator;
		goto err_disable_vddio_regulator;
	}
	}


	nfc_digital_set_parent_dev(trf->ddev, trf->dev);
	nfc_digital_set_parent_dev(trf->ddev, trf->dev);
@@ -2137,8 +2138,10 @@ static int trf7970a_probe(struct spi_device *spi)
	trf7970a_shutdown(trf);
	trf7970a_shutdown(trf);
err_free_ddev:
err_free_ddev:
	nfc_digital_free_device(trf->ddev);
	nfc_digital_free_device(trf->ddev);
err_disable_regulator:
err_disable_vddio_regulator:
	regulator_disable(trf->regulator);
	regulator_disable(trf->vddio_regulator);
err_disable_vin_regulator:
	regulator_disable(trf->vin_regulator);
err_destroy_lock:
err_destroy_lock:
	mutex_destroy(&trf->lock);
	mutex_destroy(&trf->lock);
	return ret;
	return ret;
@@ -2157,7 +2160,8 @@ static int trf7970a_remove(struct spi_device *spi)
	nfc_digital_unregister_device(trf->ddev);
	nfc_digital_unregister_device(trf->ddev);
	nfc_digital_free_device(trf->ddev);
	nfc_digital_free_device(trf->ddev);


	regulator_disable(trf->regulator);
	regulator_disable(trf->vddio_regulator);
	regulator_disable(trf->vin_regulator);


	mutex_destroy(&trf->lock);
	mutex_destroy(&trf->lock);