]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
NFC: trf7970a: disable all regulators on removal
authorPaul Geurts <paul_geurts@live.nl>
Thu, 18 Apr 2024 19:25:38 +0000 (21:25 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 22 Apr 2024 21:19:58 +0000 (14:19 -0700)
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: 49d22c70aaf0 ("NFC: trf7970a: Add device tree option of 1.8 Volt IO voltage")
Signed-off-by: Paul Geurts <paul_geurts@live.nl>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/DB7PR09MB26847A4EBF88D9EDFEB1DA0F950E2@DB7PR09MB2684.eurprd09.prod.outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/nfc/trf7970a.c

index 7eb17f46a8153d88705603e421f350b0fd091c2b..9e1a34e23af26e0a2bd7e18b4e3fe5f6726f560d 100644 (file)
@@ -424,7 +424,8 @@ struct trf7970a {
        enum trf7970a_state             state;
        struct device                   *dev;
        struct spi_device               *spi;
-       struct regulator                *regulator;
+       struct regulator                *vin_regulator;
+       struct regulator                *vddio_regulator;
        struct nfc_digital_dev          *ddev;
        u32                             quirks;
        bool                            is_initiator;
@@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
        if (trf->state != TRF7970A_ST_PWR_OFF)
                return 0;
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, 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))
                gpiod_set_value_cansleep(trf->en2_gpiod, 0);
 
-       ret = regulator_disable(trf->regulator);
+       ret = regulator_disable(trf->vin_regulator);
        if (ret)
                dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
                        ret);
@@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi)
        mutex_init(&trf->lock);
        INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vin");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
+       if (IS_ERR(trf->vin_regulator)) {
+               ret = PTR_ERR(trf->vin_regulator);
                dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       uvolts = regulator_get_voltage(trf->regulator);
+       uvolts = regulator_get_voltage(trf->vin_regulator);
        if (uvolts > 4000000)
                trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
+       if (IS_ERR(trf->vddio_regulator)) {
+               ret = PTR_ERR(trf->vddio_regulator);
                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) {
                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;
                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) {
                dev_err(trf->dev, "Can't allocate NFC digital device\n");
                ret = -ENOMEM;
-               goto err_disable_regulator;
+               goto err_disable_vddio_regulator;
        }
 
        nfc_digital_set_parent_dev(trf->ddev, trf->dev);
@@ -2137,8 +2138,10 @@ err_shutdown:
        trf7970a_shutdown(trf);
 err_free_ddev:
        nfc_digital_free_device(trf->ddev);
-err_disable_regulator:
-       regulator_disable(trf->regulator);
+err_disable_vddio_regulator:
+       regulator_disable(trf->vddio_regulator);
+err_disable_vin_regulator:
+       regulator_disable(trf->vin_regulator);
 err_destroy_lock:
        mutex_destroy(&trf->lock);
        return ret;
@@ -2157,7 +2160,8 @@ static void trf7970a_remove(struct spi_device *spi)
        nfc_digital_unregister_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);
 }