diff options
| author | Sebastian Reichel <sre@kernel.org> | 2016-05-11 11:22:00 -0400 |
|---|---|---|
| committer | Sebastian Reichel <sre@kernel.org> | 2016-06-27 18:40:03 -0400 |
| commit | ad60db2f9fe3367e60a21fc0afe19999516f8b27 (patch) | |
| tree | e20669ae89c608890fb67450d994153e5ebcd2b9 /drivers/hsi/controllers | |
| parent | 4e552310cdf0c81210b5fc9173f7cf497eeb9feb (diff) | |
HSI: omap_ssi_port: use rpm autosuspend API
Instead of immediately sending the SSI module to
sleep, wait some time in case of new incoming or
outgoing traffic.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
Diffstat (limited to 'drivers/hsi/controllers')
| -rw-r--r-- | drivers/hsi/controllers/omap_ssi_port.c | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c index 7717c769c4dd..f95efabc27b0 100644 --- a/drivers/hsi/controllers/omap_ssi_port.c +++ b/drivers/hsi/controllers/omap_ssi_port.c | |||
| @@ -126,7 +126,7 @@ static int ssi_debug_port_show(struct seq_file *m, void *p __maybe_unused) | |||
| 126 | seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch, | 126 | seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch, |
| 127 | readl(base + SSI_SSR_BUFFER_CH_REG(ch))); | 127 | readl(base + SSI_SSR_BUFFER_CH_REG(ch))); |
| 128 | } | 128 | } |
| 129 | pm_runtime_put_sync(omap_port->pdev); | 129 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 130 | 130 | ||
| 131 | return 0; | 131 | return 0; |
| 132 | } | 132 | } |
| @@ -150,7 +150,7 @@ static int ssi_div_get(void *data, u64 *val) | |||
| 150 | 150 | ||
| 151 | pm_runtime_get_sync(omap_port->pdev); | 151 | pm_runtime_get_sync(omap_port->pdev); |
| 152 | *val = readl(omap_port->sst_base + SSI_SST_DIVISOR_REG); | 152 | *val = readl(omap_port->sst_base + SSI_SST_DIVISOR_REG); |
| 153 | pm_runtime_put_sync(omap_port->pdev); | 153 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 154 | 154 | ||
| 155 | return 0; | 155 | return 0; |
| 156 | } | 156 | } |
| @@ -166,7 +166,7 @@ static int ssi_div_set(void *data, u64 val) | |||
| 166 | pm_runtime_get_sync(omap_port->pdev); | 166 | pm_runtime_get_sync(omap_port->pdev); |
| 167 | writel(val, omap_port->sst_base + SSI_SST_DIVISOR_REG); | 167 | writel(val, omap_port->sst_base + SSI_SST_DIVISOR_REG); |
| 168 | omap_port->sst.divisor = val; | 168 | omap_port->sst.divisor = val; |
| 169 | pm_runtime_put_sync(omap_port->pdev); | 169 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 170 | 170 | ||
| 171 | return 0; | 171 | return 0; |
| 172 | } | 172 | } |
| @@ -245,7 +245,7 @@ static int ssi_start_dma(struct hsi_msg *msg, int lch) | |||
| 245 | 245 | ||
| 246 | if (!pm_runtime_active(omap_port->pdev)) { | 246 | if (!pm_runtime_active(omap_port->pdev)) { |
| 247 | dev_warn(&port->device, "ssi_start_dma called without runtime PM!\n"); | 247 | dev_warn(&port->device, "ssi_start_dma called without runtime PM!\n"); |
| 248 | pm_runtime_put(omap_port->pdev); | 248 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 249 | return -EREMOTEIO; | 249 | return -EREMOTEIO; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| @@ -254,7 +254,7 @@ static int ssi_start_dma(struct hsi_msg *msg, int lch) | |||
| 254 | DMA_FROM_DEVICE); | 254 | DMA_FROM_DEVICE); |
| 255 | if (err < 0) { | 255 | if (err < 0) { |
| 256 | dev_dbg(&ssi->device, "DMA map SG failed !\n"); | 256 | dev_dbg(&ssi->device, "DMA map SG failed !\n"); |
| 257 | pm_runtime_put(omap_port->pdev); | 257 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 258 | return err; | 258 | return err; |
| 259 | } | 259 | } |
| 260 | csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT | | 260 | csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT | |
| @@ -271,7 +271,7 @@ static int ssi_start_dma(struct hsi_msg *msg, int lch) | |||
| 271 | DMA_TO_DEVICE); | 271 | DMA_TO_DEVICE); |
| 272 | if (err < 0) { | 272 | if (err < 0) { |
| 273 | dev_dbg(&ssi->device, "DMA map SG failed !\n"); | 273 | dev_dbg(&ssi->device, "DMA map SG failed !\n"); |
| 274 | pm_runtime_put(omap_port->pdev); | 274 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 275 | return err; | 275 | return err; |
| 276 | } | 276 | } |
| 277 | csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT | | 277 | csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT | |
| @@ -317,7 +317,7 @@ static int ssi_start_pio(struct hsi_msg *msg) | |||
| 317 | 317 | ||
| 318 | if (!pm_runtime_active(omap_port->pdev)) { | 318 | if (!pm_runtime_active(omap_port->pdev)) { |
| 319 | dev_warn(&port->device, "ssi_start_pio called without runtime PM!\n"); | 319 | dev_warn(&port->device, "ssi_start_pio called without runtime PM!\n"); |
| 320 | pm_runtime_put(omap_port->pdev); | 320 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 321 | return -EREMOTEIO; | 321 | return -EREMOTEIO; |
| 322 | } | 322 | } |
| 323 | 323 | ||
| @@ -332,7 +332,7 @@ static int ssi_start_pio(struct hsi_msg *msg) | |||
| 332 | msg->ttype ? "write" : "read"); | 332 | msg->ttype ? "write" : "read"); |
| 333 | val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); | 333 | val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); |
| 334 | writel(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); | 334 | writel(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); |
| 335 | pm_runtime_put(omap_port->pdev); | 335 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 336 | msg->actual_len = 0; | 336 | msg->actual_len = 0; |
| 337 | msg->status = HSI_STATUS_PROCEEDING; | 337 | msg->status = HSI_STATUS_PROCEEDING; |
| 338 | 338 | ||
| @@ -390,7 +390,8 @@ static int ssi_async_break(struct hsi_msg *msg) | |||
| 390 | spin_unlock_bh(&omap_port->lock); | 390 | spin_unlock_bh(&omap_port->lock); |
| 391 | } | 391 | } |
| 392 | out: | 392 | out: |
| 393 | pm_runtime_put(omap_port->pdev); | 393 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 394 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 394 | 395 | ||
| 395 | return err; | 396 | return err; |
| 396 | } | 397 | } |
| @@ -428,7 +429,8 @@ static int ssi_async(struct hsi_msg *msg) | |||
| 428 | msg->status = HSI_STATUS_ERROR; | 429 | msg->status = HSI_STATUS_ERROR; |
| 429 | } | 430 | } |
| 430 | spin_unlock_bh(&omap_port->lock); | 431 | spin_unlock_bh(&omap_port->lock); |
| 431 | pm_runtime_put(omap_port->pdev); | 432 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 433 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 432 | dev_dbg(&port->device, "msg status %d ttype %d ch %d\n", | 434 | dev_dbg(&port->device, "msg status %d ttype %d ch %d\n", |
| 433 | msg->status, msg->ttype, msg->channel); | 435 | msg->status, msg->ttype, msg->channel); |
| 434 | 436 | ||
| @@ -530,7 +532,8 @@ static int ssi_setup(struct hsi_client *cl) | |||
| 530 | omap_port->ssr.mode = cl->rx_cfg.mode; | 532 | omap_port->ssr.mode = cl->rx_cfg.mode; |
| 531 | out: | 533 | out: |
| 532 | spin_unlock_bh(&omap_port->lock); | 534 | spin_unlock_bh(&omap_port->lock); |
| 533 | pm_runtime_put(omap_port->pdev); | 535 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 536 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 534 | 537 | ||
| 535 | return err; | 538 | return err; |
| 536 | } | 539 | } |
| @@ -561,7 +564,7 @@ static int ssi_flush(struct hsi_client *cl) | |||
| 561 | continue; | 564 | continue; |
| 562 | writew_relaxed(0, omap_ssi->gdd + SSI_GDD_CCR_REG(i)); | 565 | writew_relaxed(0, omap_ssi->gdd + SSI_GDD_CCR_REG(i)); |
| 563 | if (msg->ttype == HSI_MSG_READ) | 566 | if (msg->ttype == HSI_MSG_READ) |
| 564 | pm_runtime_put(omap_port->pdev); | 567 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 565 | omap_ssi->gdd_trn[i].msg = NULL; | 568 | omap_ssi->gdd_trn[i].msg = NULL; |
| 566 | } | 569 | } |
| 567 | /* Flush all SST buffers */ | 570 | /* Flush all SST buffers */ |
| @@ -585,7 +588,7 @@ static int ssi_flush(struct hsi_client *cl) | |||
| 585 | for (i = 0; i < omap_port->channels; i++) { | 588 | for (i = 0; i < omap_port->channels; i++) { |
| 586 | /* Release write clocks */ | 589 | /* Release write clocks */ |
| 587 | if (!list_empty(&omap_port->txqueue[i])) | 590 | if (!list_empty(&omap_port->txqueue[i])) |
| 588 | pm_runtime_put(omap_port->pdev); | 591 | pm_runtime_put_autosuspend(omap_port->pdev); |
| 589 | ssi_flush_queue(&omap_port->txqueue[i], NULL); | 592 | ssi_flush_queue(&omap_port->txqueue[i], NULL); |
| 590 | ssi_flush_queue(&omap_port->rxqueue[i], NULL); | 593 | ssi_flush_queue(&omap_port->rxqueue[i], NULL); |
| 591 | } | 594 | } |
| @@ -595,7 +598,8 @@ static int ssi_flush(struct hsi_client *cl) | |||
| 595 | pinctrl_pm_select_default_state(omap_port->pdev); | 598 | pinctrl_pm_select_default_state(omap_port->pdev); |
| 596 | 599 | ||
| 597 | spin_unlock_bh(&omap_port->lock); | 600 | spin_unlock_bh(&omap_port->lock); |
| 598 | pm_runtime_put(omap_port->pdev); | 601 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 602 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 599 | 603 | ||
| 600 | return 0; | 604 | return 0; |
| 601 | } | 605 | } |
| @@ -649,7 +653,9 @@ static int ssi_stop_tx(struct hsi_client *cl) | |||
| 649 | writel(SSI_WAKE(0), omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); | 653 | writel(SSI_WAKE(0), omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); |
| 650 | spin_unlock_bh(&omap_port->wk_lock); | 654 | spin_unlock_bh(&omap_port->wk_lock); |
| 651 | 655 | ||
| 652 | pm_runtime_put(omap_port->pdev); /* Release clocks */ | 656 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 657 | pm_runtime_put_autosuspend(omap_port->pdev); /* Release clocks */ | ||
| 658 | |||
| 653 | 659 | ||
| 654 | return 0; | 660 | return 0; |
| 655 | } | 661 | } |
| @@ -675,7 +681,8 @@ static void ssi_transfer(struct omap_ssi_port *omap_port, | |||
| 675 | } | 681 | } |
| 676 | } | 682 | } |
| 677 | spin_unlock_bh(&omap_port->lock); | 683 | spin_unlock_bh(&omap_port->lock); |
| 678 | pm_runtime_put(omap_port->pdev); | 684 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 685 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 679 | } | 686 | } |
| 680 | 687 | ||
| 681 | static void ssi_cleanup_queues(struct hsi_client *cl) | 688 | static void ssi_cleanup_queues(struct hsi_client *cl) |
| @@ -704,7 +711,8 @@ static void ssi_cleanup_queues(struct hsi_client *cl) | |||
| 704 | txbufstate |= (1 << i); | 711 | txbufstate |= (1 << i); |
| 705 | status |= SSI_DATAACCEPT(i); | 712 | status |= SSI_DATAACCEPT(i); |
| 706 | /* Release the clocks writes, also GDD ones */ | 713 | /* Release the clocks writes, also GDD ones */ |
| 707 | pm_runtime_put(omap_port->pdev); | 714 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 715 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 708 | } | 716 | } |
| 709 | ssi_flush_queue(&omap_port->txqueue[i], cl); | 717 | ssi_flush_queue(&omap_port->txqueue[i], cl); |
| 710 | } | 718 | } |
| @@ -758,8 +766,10 @@ static void ssi_cleanup_gdd(struct hsi_controller *ssi, struct hsi_client *cl) | |||
| 758 | * Clock references for write will be handled in | 766 | * Clock references for write will be handled in |
| 759 | * ssi_cleanup_queues | 767 | * ssi_cleanup_queues |
| 760 | */ | 768 | */ |
| 761 | if (msg->ttype == HSI_MSG_READ) | 769 | if (msg->ttype == HSI_MSG_READ) { |
| 762 | pm_runtime_put(omap_port->pdev); | 770 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 771 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 772 | } | ||
| 763 | omap_ssi->gdd_trn[i].msg = NULL; | 773 | omap_ssi->gdd_trn[i].msg = NULL; |
| 764 | } | 774 | } |
| 765 | tmp = readl_relaxed(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG); | 775 | tmp = readl_relaxed(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG); |
| @@ -807,7 +817,7 @@ static int ssi_release(struct hsi_client *cl) | |||
| 807 | WARN_ON(omap_port->wk_refcount != 0); | 817 | WARN_ON(omap_port->wk_refcount != 0); |
| 808 | } | 818 | } |
| 809 | spin_unlock_bh(&omap_port->lock); | 819 | spin_unlock_bh(&omap_port->lock); |
| 810 | pm_runtime_put(omap_port->pdev); | 820 | pm_runtime_put_sync(omap_port->pdev); |
| 811 | 821 | ||
| 812 | return 0; | 822 | return 0; |
| 813 | } | 823 | } |
| @@ -954,7 +964,8 @@ static void ssi_pio_complete(struct hsi_port *port, struct list_head *queue) | |||
| 954 | reg = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); | 964 | reg = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); |
| 955 | if (msg->ttype == HSI_MSG_WRITE) { | 965 | if (msg->ttype == HSI_MSG_WRITE) { |
| 956 | /* Release clocks for write transfer */ | 966 | /* Release clocks for write transfer */ |
| 957 | pm_runtime_put(omap_port->pdev); | 967 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 968 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 958 | } | 969 | } |
| 959 | reg &= ~val; | 970 | reg &= ~val; |
| 960 | writel_relaxed(reg, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); | 971 | writel_relaxed(reg, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0)); |
| @@ -998,7 +1009,9 @@ static irqreturn_t ssi_pio_thread(int irq, void *ssi_port) | |||
| 998 | /* TODO: sleep if we retry? */ | 1009 | /* TODO: sleep if we retry? */ |
| 999 | } while (status_reg); | 1010 | } while (status_reg); |
| 1000 | 1011 | ||
| 1001 | pm_runtime_put(omap_port->pdev); | 1012 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 1013 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 1014 | |||
| 1002 | return IRQ_HANDLED; | 1015 | return IRQ_HANDLED; |
| 1003 | } | 1016 | } |
| 1004 | 1017 | ||
| @@ -1032,8 +1045,10 @@ static irqreturn_t ssi_wake_thread(int irq __maybe_unused, void *ssi_port) | |||
| 1032 | omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); | 1045 | omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); |
| 1033 | } | 1046 | } |
| 1034 | hsi_event(port, HSI_EVENT_STOP_RX); | 1047 | hsi_event(port, HSI_EVENT_STOP_RX); |
| 1035 | if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags)) | 1048 | if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags)) { |
| 1036 | pm_runtime_put_sync(omap_port->pdev); | 1049 | pm_runtime_mark_last_busy(omap_port->pdev); |
| 1050 | pm_runtime_put_autosuspend(omap_port->pdev); | ||
| 1051 | } | ||
| 1037 | } | 1052 | } |
| 1038 | 1053 | ||
| 1039 | return IRQ_HANDLED; | 1054 | return IRQ_HANDLED; |
| @@ -1222,6 +1237,9 @@ static int ssi_port_probe(struct platform_device *pd) | |||
| 1222 | omap_port->dev = &port->device; | 1237 | omap_port->dev = &port->device; |
| 1223 | 1238 | ||
| 1224 | pm_runtime_irq_safe(omap_port->pdev); | 1239 | pm_runtime_irq_safe(omap_port->pdev); |
| 1240 | |||
| 1241 | pm_runtime_use_autosuspend(omap_port->pdev); | ||
| 1242 | pm_runtime_set_autosuspend_delay(omap_port->pdev, 250); | ||
| 1225 | pm_runtime_enable(omap_port->pdev); | 1243 | pm_runtime_enable(omap_port->pdev); |
| 1226 | 1244 | ||
| 1227 | #ifdef CONFIG_DEBUG_FS | 1245 | #ifdef CONFIG_DEBUG_FS |
| @@ -1266,6 +1284,8 @@ static int ssi_port_remove(struct platform_device *pd) | |||
| 1266 | 1284 | ||
| 1267 | omap_ssi->port[omap_port->port_id] = NULL; | 1285 | omap_ssi->port[omap_port->port_id] = NULL; |
| 1268 | platform_set_drvdata(pd, NULL); | 1286 | platform_set_drvdata(pd, NULL); |
| 1287 | |||
| 1288 | pm_runtime_dont_use_autosuspend(&pd->dev); | ||
| 1269 | pm_runtime_disable(&pd->dev); | 1289 | pm_runtime_disable(&pd->dev); |
| 1270 | 1290 | ||
| 1271 | return 0; | 1291 | return 0; |
