diff options
author | Bjorn Andersson <bjorn.andersson@linaro.org> | 2020-10-26 22:13:30 +0100 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2020-10-26 22:13:30 +0100 |
commit | bb4b1e3f0c8772eff0f4d22f725f6eaba9540c52 (patch) | |
tree | bfb40ea0edb790a2ffeaeb0ebaeba5c75dddf532 /drivers/soc/qcom | |
parent | soc: qcom: cmd-db: allow loading as a module (diff) | |
parent | soc: qcom: geni: Optimize/comment select fifo/dma mode (diff) | |
download | linux-bb4b1e3f0c8772eff0f4d22f725f6eaba9540c52.tar.xz linux-bb4b1e3f0c8772eff0f4d22f725f6eaba9540c52.zip |
Merge tag '20201013212531.428538-1-dianders@chromium.org' into drivers-for-5.11
Diffstat (limited to 'drivers/soc/qcom')
-rw-r--r-- | drivers/soc/qcom/qcom-geni-se.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index d0e4f520cff8..7649b2057b9a 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -266,36 +266,63 @@ EXPORT_SYMBOL(geni_se_init); static void geni_se_select_fifo_mode(struct geni_se *se) { u32 proto = geni_se_read_proto(se); - u32 val; + u32 val, val_old; geni_se_irq_clear(se); - val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); + /* + * The RX path for the UART is asynchronous and so needs more + * complex logic for enabling / disabling its interrupts. + * + * Specific notes: + * - The done and TX-related interrupts are managed manually. + * - We don't RX from the main sequencer (we use the secondary) so + * we don't need the RX-related interrupts enabled in the main + * sequencer for UART. + */ if (proto != GENI_SE_UART) { + val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; - } - writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - if (proto != GENI_SE_UART) + val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); val |= S_CMD_DONE_EN; - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + } - val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); + val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val &= ~GENI_DMA_MODE_EN; - writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } static void geni_se_select_dma_mode(struct geni_se *se) { - u32 val; + u32 proto = geni_se_read_proto(se); + u32 val, val_old; geni_se_irq_clear(se); - val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); + if (proto != GENI_SE_UART) { + val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); + val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); + val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); + + val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); + val &= ~S_CMD_DONE_EN; + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + } + + val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val |= GENI_DMA_MODE_EN; - writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } /** @@ -651,7 +678,7 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len, writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L); writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H); writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR); - writel_relaxed(len, se->base + SE_DMA_TX_LEN); + writel(len, se->base + SE_DMA_TX_LEN); return 0; } EXPORT_SYMBOL(geni_se_tx_dma_prep); @@ -688,7 +715,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H); /* RX does not have EOT buffer type bit. So just reset RX_ATTR */ writel_relaxed(0, se->base + SE_DMA_RX_ATTR); - writel_relaxed(len, se->base + SE_DMA_RX_LEN); + writel(len, se->base + SE_DMA_RX_LEN); return 0; } EXPORT_SYMBOL(geni_se_rx_dma_prep); |