diff options
Diffstat (limited to 'drivers/spi/spi-atmel.c')
-rw-r--r-- | drivers/spi/spi-atmel.c | 115 |
1 files changed, 72 insertions, 43 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 113c83f44b5c..e4193ccc4970 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/pinctrl/consumer.h> | 28 | #include <linux/pinctrl/consumer.h> |
29 | #include <linux/pm_runtime.h> | ||
29 | 30 | ||
30 | /* SPI register offsets */ | 31 | /* SPI register offsets */ |
31 | #define SPI_CR 0x0000 | 32 | #define SPI_CR 0x0000 |
@@ -191,6 +192,8 @@ | |||
191 | 192 | ||
192 | #define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) | 193 | #define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) |
193 | 194 | ||
195 | #define AUTOSUSPEND_TIMEOUT 2000 | ||
196 | |||
194 | struct atmel_spi_dma { | 197 | struct atmel_spi_dma { |
195 | struct dma_chan *chan_rx; | 198 | struct dma_chan *chan_rx; |
196 | struct dma_chan *chan_tx; | 199 | struct dma_chan *chan_tx; |
@@ -414,23 +417,6 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, | |||
414 | return err; | 417 | return err; |
415 | } | 418 | } |
416 | 419 | ||
417 | static bool filter(struct dma_chan *chan, void *pdata) | ||
418 | { | ||
419 | struct atmel_spi_dma *sl_pdata = pdata; | ||
420 | struct at_dma_slave *sl; | ||
421 | |||
422 | if (!sl_pdata) | ||
423 | return false; | ||
424 | |||
425 | sl = &sl_pdata->dma_slave; | ||
426 | if (sl->dma_dev == chan->device->dev) { | ||
427 | chan->private = sl; | ||
428 | return true; | ||
429 | } else { | ||
430 | return false; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | static int atmel_spi_configure_dma(struct atmel_spi *as) | 420 | static int atmel_spi_configure_dma(struct atmel_spi *as) |
435 | { | 421 | { |
436 | struct dma_slave_config slave_config; | 422 | struct dma_slave_config slave_config; |
@@ -441,19 +427,24 @@ static int atmel_spi_configure_dma(struct atmel_spi *as) | |||
441 | dma_cap_zero(mask); | 427 | dma_cap_zero(mask); |
442 | dma_cap_set(DMA_SLAVE, mask); | 428 | dma_cap_set(DMA_SLAVE, mask); |
443 | 429 | ||
444 | as->dma.chan_tx = dma_request_slave_channel_compat(mask, filter, | 430 | as->dma.chan_tx = dma_request_slave_channel_reason(dev, "tx"); |
445 | &as->dma, | 431 | if (IS_ERR(as->dma.chan_tx)) { |
446 | dev, "tx"); | 432 | err = PTR_ERR(as->dma.chan_tx); |
447 | if (!as->dma.chan_tx) { | 433 | if (err == -EPROBE_DEFER) { |
434 | dev_warn(dev, "no DMA channel available at the moment\n"); | ||
435 | return err; | ||
436 | } | ||
448 | dev_err(dev, | 437 | dev_err(dev, |
449 | "DMA TX channel not available, SPI unable to use DMA\n"); | 438 | "DMA TX channel not available, SPI unable to use DMA\n"); |
450 | err = -EBUSY; | 439 | err = -EBUSY; |
451 | goto error; | 440 | goto error; |
452 | } | 441 | } |
453 | 442 | ||
454 | as->dma.chan_rx = dma_request_slave_channel_compat(mask, filter, | 443 | /* |
455 | &as->dma, | 444 | * No reason to check EPROBE_DEFER here since we have already requested |
456 | dev, "rx"); | 445 | * tx channel. If it fails here, it's for another reason. |
446 | */ | ||
447 | as->dma.chan_rx = dma_request_slave_channel(dev, "rx"); | ||
457 | 448 | ||
458 | if (!as->dma.chan_rx) { | 449 | if (!as->dma.chan_rx) { |
459 | dev_err(dev, | 450 | dev_err(dev, |
@@ -474,7 +465,7 @@ static int atmel_spi_configure_dma(struct atmel_spi *as) | |||
474 | error: | 465 | error: |
475 | if (as->dma.chan_rx) | 466 | if (as->dma.chan_rx) |
476 | dma_release_channel(as->dma.chan_rx); | 467 | dma_release_channel(as->dma.chan_rx); |
477 | if (as->dma.chan_tx) | 468 | if (!IS_ERR(as->dma.chan_tx)) |
478 | dma_release_channel(as->dma.chan_tx); | 469 | dma_release_channel(as->dma.chan_tx); |
479 | return err; | 470 | return err; |
480 | } | 471 | } |
@@ -482,11 +473,9 @@ error: | |||
482 | static void atmel_spi_stop_dma(struct atmel_spi *as) | 473 | static void atmel_spi_stop_dma(struct atmel_spi *as) |
483 | { | 474 | { |
484 | if (as->dma.chan_rx) | 475 | if (as->dma.chan_rx) |
485 | as->dma.chan_rx->device->device_control(as->dma.chan_rx, | 476 | dmaengine_terminate_all(as->dma.chan_rx); |
486 | DMA_TERMINATE_ALL, 0); | ||
487 | if (as->dma.chan_tx) | 477 | if (as->dma.chan_tx) |
488 | as->dma.chan_tx->device->device_control(as->dma.chan_tx, | 478 | dmaengine_terminate_all(as->dma.chan_tx); |
489 | DMA_TERMINATE_ALL, 0); | ||
490 | } | 479 | } |
491 | 480 | ||
492 | static void atmel_spi_release_dma(struct atmel_spi *as) | 481 | static void atmel_spi_release_dma(struct atmel_spi *as) |
@@ -1315,6 +1304,7 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
1315 | master->setup = atmel_spi_setup; | 1304 | master->setup = atmel_spi_setup; |
1316 | master->transfer_one_message = atmel_spi_transfer_one_message; | 1305 | master->transfer_one_message = atmel_spi_transfer_one_message; |
1317 | master->cleanup = atmel_spi_cleanup; | 1306 | master->cleanup = atmel_spi_cleanup; |
1307 | master->auto_runtime_pm = true; | ||
1318 | platform_set_drvdata(pdev, master); | 1308 | platform_set_drvdata(pdev, master); |
1319 | 1309 | ||
1320 | as = spi_master_get_devdata(master); | 1310 | as = spi_master_get_devdata(master); |
@@ -1347,8 +1337,11 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
1347 | as->use_dma = false; | 1337 | as->use_dma = false; |
1348 | as->use_pdc = false; | 1338 | as->use_pdc = false; |
1349 | if (as->caps.has_dma_support) { | 1339 | if (as->caps.has_dma_support) { |
1350 | if (atmel_spi_configure_dma(as) == 0) | 1340 | ret = atmel_spi_configure_dma(as); |
1341 | if (ret == 0) | ||
1351 | as->use_dma = true; | 1342 | as->use_dma = true; |
1343 | else if (ret == -EPROBE_DEFER) | ||
1344 | return ret; | ||
1352 | } else { | 1345 | } else { |
1353 | as->use_pdc = true; | 1346 | as->use_pdc = true; |
1354 | } | 1347 | } |
@@ -1387,6 +1380,11 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
1387 | dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", | 1380 | dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", |
1388 | (unsigned long)regs->start, irq); | 1381 | (unsigned long)regs->start, irq); |
1389 | 1382 | ||
1383 | pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT); | ||
1384 | pm_runtime_use_autosuspend(&pdev->dev); | ||
1385 | pm_runtime_set_active(&pdev->dev); | ||
1386 | pm_runtime_enable(&pdev->dev); | ||
1387 | |||
1390 | ret = devm_spi_register_master(&pdev->dev, master); | 1388 | ret = devm_spi_register_master(&pdev->dev, master); |
1391 | if (ret) | 1389 | if (ret) |
1392 | goto out_free_dma; | 1390 | goto out_free_dma; |
@@ -1394,6 +1392,9 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
1394 | return 0; | 1392 | return 0; |
1395 | 1393 | ||
1396 | out_free_dma: | 1394 | out_free_dma: |
1395 | pm_runtime_disable(&pdev->dev); | ||
1396 | pm_runtime_set_suspended(&pdev->dev); | ||
1397 | |||
1397 | if (as->use_dma) | 1398 | if (as->use_dma) |
1398 | atmel_spi_release_dma(as); | 1399 | atmel_spi_release_dma(as); |
1399 | 1400 | ||
@@ -1415,6 +1416,8 @@ static int atmel_spi_remove(struct platform_device *pdev) | |||
1415 | struct spi_master *master = platform_get_drvdata(pdev); | 1416 | struct spi_master *master = platform_get_drvdata(pdev); |
1416 | struct atmel_spi *as = spi_master_get_devdata(master); | 1417 | struct atmel_spi *as = spi_master_get_devdata(master); |
1417 | 1418 | ||
1419 | pm_runtime_get_sync(&pdev->dev); | ||
1420 | |||
1418 | /* reset the hardware and block queue progress */ | 1421 | /* reset the hardware and block queue progress */ |
1419 | spin_lock_irq(&as->lock); | 1422 | spin_lock_irq(&as->lock); |
1420 | if (as->use_dma) { | 1423 | if (as->use_dma) { |
@@ -1432,14 +1435,37 @@ static int atmel_spi_remove(struct platform_device *pdev) | |||
1432 | 1435 | ||
1433 | clk_disable_unprepare(as->clk); | 1436 | clk_disable_unprepare(as->clk); |
1434 | 1437 | ||
1438 | pm_runtime_put_noidle(&pdev->dev); | ||
1439 | pm_runtime_disable(&pdev->dev); | ||
1440 | |||
1435 | return 0; | 1441 | return 0; |
1436 | } | 1442 | } |
1437 | 1443 | ||
1438 | #ifdef CONFIG_PM_SLEEP | 1444 | #ifdef CONFIG_PM |
1445 | static int atmel_spi_runtime_suspend(struct device *dev) | ||
1446 | { | ||
1447 | struct spi_master *master = dev_get_drvdata(dev); | ||
1448 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
1449 | |||
1450 | clk_disable_unprepare(as->clk); | ||
1451 | pinctrl_pm_select_sleep_state(dev); | ||
1452 | |||
1453 | return 0; | ||
1454 | } | ||
1455 | |||
1456 | static int atmel_spi_runtime_resume(struct device *dev) | ||
1457 | { | ||
1458 | struct spi_master *master = dev_get_drvdata(dev); | ||
1459 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
1460 | |||
1461 | pinctrl_pm_select_default_state(dev); | ||
1462 | |||
1463 | return clk_prepare_enable(as->clk); | ||
1464 | } | ||
1465 | |||
1439 | static int atmel_spi_suspend(struct device *dev) | 1466 | static int atmel_spi_suspend(struct device *dev) |
1440 | { | 1467 | { |
1441 | struct spi_master *master = dev_get_drvdata(dev); | 1468 | struct spi_master *master = dev_get_drvdata(dev); |
1442 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
1443 | int ret; | 1469 | int ret; |
1444 | 1470 | ||
1445 | /* Stop the queue running */ | 1471 | /* Stop the queue running */ |
@@ -1449,22 +1475,22 @@ static int atmel_spi_suspend(struct device *dev) | |||
1449 | return ret; | 1475 | return ret; |
1450 | } | 1476 | } |
1451 | 1477 | ||
1452 | clk_disable_unprepare(as->clk); | 1478 | if (!pm_runtime_suspended(dev)) |
1453 | 1479 | atmel_spi_runtime_suspend(dev); | |
1454 | pinctrl_pm_select_sleep_state(dev); | ||
1455 | 1480 | ||
1456 | return 0; | 1481 | return 0; |
1457 | } | 1482 | } |
1458 | 1483 | ||
1459 | static int atmel_spi_resume(struct device *dev) | 1484 | static int atmel_spi_resume(struct device *dev) |
1460 | { | 1485 | { |
1461 | struct spi_master *master = dev_get_drvdata(dev); | 1486 | struct spi_master *master = dev_get_drvdata(dev); |
1462 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
1463 | int ret; | 1487 | int ret; |
1464 | 1488 | ||
1465 | pinctrl_pm_select_default_state(dev); | 1489 | if (!pm_runtime_suspended(dev)) { |
1466 | 1490 | ret = atmel_spi_runtime_resume(dev); | |
1467 | clk_prepare_enable(as->clk); | 1491 | if (ret) |
1492 | return ret; | ||
1493 | } | ||
1468 | 1494 | ||
1469 | /* Start the queue running */ | 1495 | /* Start the queue running */ |
1470 | ret = spi_master_resume(master); | 1496 | ret = spi_master_resume(master); |
@@ -1474,8 +1500,11 @@ static int atmel_spi_resume(struct device *dev) | |||
1474 | return ret; | 1500 | return ret; |
1475 | } | 1501 | } |
1476 | 1502 | ||
1477 | static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume); | 1503 | static const struct dev_pm_ops atmel_spi_pm_ops = { |
1478 | 1504 | SET_SYSTEM_SLEEP_PM_OPS(atmel_spi_suspend, atmel_spi_resume) | |
1505 | SET_RUNTIME_PM_OPS(atmel_spi_runtime_suspend, | ||
1506 | atmel_spi_runtime_resume, NULL) | ||
1507 | }; | ||
1479 | #define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops) | 1508 | #define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops) |
1480 | #else | 1509 | #else |
1481 | #define ATMEL_SPI_PM_OPS NULL | 1510 | #define ATMEL_SPI_PM_OPS NULL |