diff options
author | Mark A. Greer <mgreer@animalcreek.com> | 2014-03-25 11:54:38 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2014-04-21 18:37:28 -0400 |
commit | e6403b7c756f9d694332870ba0c2be7a4aa0b8c0 (patch) | |
tree | 06627a8ffbe78a58f04f70f4763e91d19b5ef2b0 /drivers/nfc | |
parent | a1d2dc5b407ae18b59b7a129c93c8eb5ad7b1c80 (diff) |
NFC: trf7970a: Add pm_runtime support
Add pm_runtime support by moving the code that enables the trf7970a to
the pm_runtime hook routines. The pm_runtime 'autosuspend' feature is
used so that the device isn't disabled until at least 30 seconds have
passed since trf7970a_switch_rf_off() was last called.
The result is that when trf7970a_switch_rf_on() is called, the device
will be enabled and initialized (if it isn't already). When
trf7970a_switch_rf_off() is called, it will turn off the RF immediately
but leave the device enabled for at least 30 seconds.
If 30 seconds have passed and the pm_runtime facility decides to suspend
the driver, the device will be disabled then.
Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/trf7970a.c | 122 |
1 files changed, 85 insertions, 37 deletions
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 0a46348f9af6..26e744934068 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/pm_runtime.h> | ||
19 | #include <linux/nfc.h> | 20 | #include <linux/nfc.h> |
20 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
@@ -106,6 +107,8 @@ | |||
106 | (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ | 107 | (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ |
107 | NFC_PROTO_ISO15693_MASK) | 108 | NFC_PROTO_ISO15693_MASK) |
108 | 109 | ||
110 | #define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */ | ||
111 | |||
109 | /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends | 112 | /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends |
110 | * on what the current framing is, the address of the TX length byte 1 | 113 | * on what the current framing is, the address of the TX length byte 1 |
111 | * register (0x1d), and the 2 byte length of the data to be transmitted. | 114 | * register (0x1d), and the 2 byte length of the data to be transmitted. |
@@ -330,7 +333,6 @@ struct trf7970a { | |||
330 | struct regulator *regulator; | 333 | struct regulator *regulator; |
331 | struct nfc_digital_dev *ddev; | 334 | struct nfc_digital_dev *ddev; |
332 | u32 quirks; | 335 | u32 quirks; |
333 | bool powering_up; | ||
334 | bool aborting; | 336 | bool aborting; |
335 | struct sk_buff *tx_skb; | 337 | struct sk_buff *tx_skb; |
336 | struct sk_buff *rx_skb; | 338 | struct sk_buff *rx_skb; |
@@ -795,47 +797,22 @@ static void trf7970a_switch_rf_off(struct trf7970a *trf) | |||
795 | 797 | ||
796 | trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl); | 798 | trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl); |
797 | 799 | ||
798 | gpio_set_value(trf->en_gpio, 0); | ||
799 | gpio_set_value(trf->en2_gpio, 0); | ||
800 | |||
801 | trf->aborting = false; | 800 | trf->aborting = false; |
802 | trf->state = TRF7970A_ST_OFF; | 801 | trf->state = TRF7970A_ST_OFF; |
802 | |||
803 | pm_runtime_mark_last_busy(trf->dev); | ||
804 | pm_runtime_put_autosuspend(trf->dev); | ||
803 | } | 805 | } |
804 | 806 | ||
805 | static int trf7970a_switch_rf_on(struct trf7970a *trf) | 807 | static int trf7970a_switch_rf_on(struct trf7970a *trf) |
806 | { | 808 | { |
807 | unsigned long delay; | ||
808 | int ret; | ||
809 | |||
810 | dev_dbg(trf->dev, "Switching rf on\n"); | 809 | dev_dbg(trf->dev, "Switching rf on\n"); |
811 | 810 | ||
812 | if (trf->powering_up) | 811 | pm_runtime_get_sync(trf->dev); |
813 | usleep_range(5000, 6000); | ||
814 | 812 | ||
815 | gpio_set_value(trf->en2_gpio, 1); | 813 | trf->state = TRF7970A_ST_IDLE; |
816 | usleep_range(1000, 2000); | ||
817 | gpio_set_value(trf->en_gpio, 1); | ||
818 | |||
819 | /* The delay between enabling the trf7970a and issuing the first | ||
820 | * command is significantly longer the very first time after powering | ||
821 | * up. Make sure the longer delay is only done the first time. | ||
822 | */ | ||
823 | if (trf->powering_up) { | ||
824 | delay = 20000; | ||
825 | trf->powering_up = false; | ||
826 | } else { | ||
827 | delay = 5000; | ||
828 | } | ||
829 | |||
830 | usleep_range(delay, delay + 1000); | ||
831 | |||
832 | ret = trf7970a_init(trf); | ||
833 | if (ret) | ||
834 | trf7970a_switch_rf_off(trf); | ||
835 | else | ||
836 | trf->state = TRF7970A_ST_IDLE; | ||
837 | 814 | ||
838 | return ret; | 815 | return 0; |
839 | } | 816 | } |
840 | 817 | ||
841 | static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) | 818 | static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) |
@@ -1331,8 +1308,6 @@ static int trf7970a_probe(struct spi_device *spi) | |||
1331 | if (uvolts > 4000000) | 1308 | if (uvolts > 4000000) |
1332 | trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; | 1309 | trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; |
1333 | 1310 | ||
1334 | trf->powering_up = true; | ||
1335 | |||
1336 | trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, | 1311 | trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, |
1337 | TRF7970A_SUPPORTED_PROTOCOLS, | 1312 | TRF7970A_SUPPORTED_PROTOCOLS, |
1338 | NFC_DIGITAL_DRV_CAPS_IN_CRC, TRF7970A_TX_SKB_HEADROOM, | 1313 | NFC_DIGITAL_DRV_CAPS_IN_CRC, TRF7970A_TX_SKB_HEADROOM, |
@@ -1347,6 +1322,10 @@ static int trf7970a_probe(struct spi_device *spi) | |||
1347 | nfc_digital_set_drvdata(trf->ddev, trf); | 1322 | nfc_digital_set_drvdata(trf->ddev, trf); |
1348 | spi_set_drvdata(spi, trf); | 1323 | spi_set_drvdata(spi, trf); |
1349 | 1324 | ||
1325 | pm_runtime_set_autosuspend_delay(trf->dev, TRF7970A_AUTOSUSPEND_DELAY); | ||
1326 | pm_runtime_use_autosuspend(trf->dev); | ||
1327 | pm_runtime_enable(trf->dev); | ||
1328 | |||
1350 | ret = nfc_digital_register_device(trf->ddev); | 1329 | ret = nfc_digital_register_device(trf->ddev); |
1351 | if (ret) { | 1330 | if (ret) { |
1352 | dev_err(trf->dev, "Can't register NFC digital device: %d\n", | 1331 | dev_err(trf->dev, "Can't register NFC digital device: %d\n", |
@@ -1357,6 +1336,7 @@ static int trf7970a_probe(struct spi_device *spi) | |||
1357 | return 0; | 1336 | return 0; |
1358 | 1337 | ||
1359 | err_free_ddev: | 1338 | err_free_ddev: |
1339 | pm_runtime_disable(trf->dev); | ||
1360 | nfc_digital_free_device(trf->ddev); | 1340 | nfc_digital_free_device(trf->ddev); |
1361 | err_disable_regulator: | 1341 | err_disable_regulator: |
1362 | regulator_disable(trf->regulator); | 1342 | regulator_disable(trf->regulator); |
@@ -1371,15 +1351,16 @@ static int trf7970a_remove(struct spi_device *spi) | |||
1371 | 1351 | ||
1372 | mutex_lock(&trf->lock); | 1352 | mutex_lock(&trf->lock); |
1373 | 1353 | ||
1374 | trf7970a_switch_rf_off(trf); | ||
1375 | trf7970a_init(trf); | ||
1376 | |||
1377 | switch (trf->state) { | 1354 | switch (trf->state) { |
1378 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: | 1355 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: |
1379 | case TRF7970A_ST_WAIT_FOR_RX_DATA: | 1356 | case TRF7970A_ST_WAIT_FOR_RX_DATA: |
1380 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: | 1357 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: |
1381 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: | 1358 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: |
1382 | trf7970a_send_err_upstream(trf, -ECANCELED); | 1359 | trf7970a_send_err_upstream(trf, -ECANCELED); |
1360 | /* FALLTHROUGH */ | ||
1361 | case TRF7970A_ST_IDLE: | ||
1362 | case TRF7970A_ST_IDLE_RX_BLOCKED: | ||
1363 | pm_runtime_put_sync(trf->dev); | ||
1383 | break; | 1364 | break; |
1384 | default: | 1365 | default: |
1385 | break; | 1366 | break; |
@@ -1387,6 +1368,8 @@ static int trf7970a_remove(struct spi_device *spi) | |||
1387 | 1368 | ||
1388 | mutex_unlock(&trf->lock); | 1369 | mutex_unlock(&trf->lock); |
1389 | 1370 | ||
1371 | pm_runtime_disable(trf->dev); | ||
1372 | |||
1390 | nfc_digital_unregister_device(trf->ddev); | 1373 | nfc_digital_unregister_device(trf->ddev); |
1391 | nfc_digital_free_device(trf->ddev); | 1374 | nfc_digital_free_device(trf->ddev); |
1392 | 1375 | ||
@@ -1397,6 +1380,70 @@ static int trf7970a_remove(struct spi_device *spi) | |||
1397 | return 0; | 1380 | return 0; |
1398 | } | 1381 | } |
1399 | 1382 | ||
1383 | #ifdef CONFIG_PM_RUNTIME | ||
1384 | static int trf7970a_pm_runtime_suspend(struct device *dev) | ||
1385 | { | ||
1386 | struct spi_device *spi = container_of(dev, struct spi_device, dev); | ||
1387 | struct trf7970a *trf = spi_get_drvdata(spi); | ||
1388 | int ret; | ||
1389 | |||
1390 | dev_dbg(dev, "Runtime suspend\n"); | ||
1391 | |||
1392 | if (trf->state != TRF7970A_ST_OFF) { | ||
1393 | dev_dbg(dev, "Can't suspend - not in OFF state (%d)\n", | ||
1394 | trf->state); | ||
1395 | return -EBUSY; | ||
1396 | } | ||
1397 | |||
1398 | gpio_set_value(trf->en_gpio, 0); | ||
1399 | gpio_set_value(trf->en2_gpio, 0); | ||
1400 | |||
1401 | ret = regulator_disable(trf->regulator); | ||
1402 | if (ret) | ||
1403 | dev_err(dev, "%s - Can't disable VIN: %d\n", __func__, ret); | ||
1404 | |||
1405 | return ret; | ||
1406 | } | ||
1407 | |||
1408 | static int trf7970a_pm_runtime_resume(struct device *dev) | ||
1409 | { | ||
1410 | struct spi_device *spi = container_of(dev, struct spi_device, dev); | ||
1411 | struct trf7970a *trf = spi_get_drvdata(spi); | ||
1412 | int ret; | ||
1413 | |||
1414 | dev_dbg(dev, "Runtime resume\n"); | ||
1415 | |||
1416 | ret = regulator_enable(trf->regulator); | ||
1417 | if (ret) { | ||
1418 | dev_err(dev, "%s - Can't enable VIN: %d\n", __func__, ret); | ||
1419 | return ret; | ||
1420 | } | ||
1421 | |||
1422 | usleep_range(5000, 6000); | ||
1423 | |||
1424 | gpio_set_value(trf->en2_gpio, 1); | ||
1425 | usleep_range(1000, 2000); | ||
1426 | gpio_set_value(trf->en_gpio, 1); | ||
1427 | |||
1428 | usleep_range(20000, 21000); | ||
1429 | |||
1430 | ret = trf7970a_init(trf); | ||
1431 | if (ret) { | ||
1432 | dev_err(dev, "%s - Can't initialize: %d\n", __func__, ret); | ||
1433 | return ret; | ||
1434 | } | ||
1435 | |||
1436 | pm_runtime_mark_last_busy(dev); | ||
1437 | |||
1438 | return 0; | ||
1439 | } | ||
1440 | #endif | ||
1441 | |||
1442 | static const struct dev_pm_ops trf7970a_pm_ops = { | ||
1443 | SET_RUNTIME_PM_OPS(trf7970a_pm_runtime_suspend, | ||
1444 | trf7970a_pm_runtime_resume, NULL) | ||
1445 | }; | ||
1446 | |||
1400 | static const struct spi_device_id trf7970a_id_table[] = { | 1447 | static const struct spi_device_id trf7970a_id_table[] = { |
1401 | { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA }, | 1448 | { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA }, |
1402 | { } | 1449 | { } |
@@ -1410,6 +1457,7 @@ static struct spi_driver trf7970a_spi_driver = { | |||
1410 | .driver = { | 1457 | .driver = { |
1411 | .name = "trf7970a", | 1458 | .name = "trf7970a", |
1412 | .owner = THIS_MODULE, | 1459 | .owner = THIS_MODULE, |
1460 | .pm = &trf7970a_pm_ops, | ||
1413 | }, | 1461 | }, |
1414 | }; | 1462 | }; |
1415 | 1463 | ||