diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 15:53:50 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 15:53:50 -0800 |
commit | 9d0d886799e49e0f6d51e70c823416919544fdb7 (patch) | |
tree | a0392a5a11884941f62b4db270e75a9451e280a2 /drivers/soc | |
parent | 605ea5aafe1341ac9b2144516f898ac78ad49c40 (diff) | |
parent | 4e970a0ada5299d017a4263074f725227c2d2852 (diff) | |
download | linux-9d0d886799e49e0f6d51e70c823416919544fdb7.tar.bz2 |
Merge branch 'i2c/for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"A bit smaller this time with mostly usual driver updates. Slave
support for imx stands out a little"
* 'i2c/for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (30 commits)
i2c: remove check that can never be true
i2c: Warn when device removing fails
dt-bindings: i2c: Update DT binding docs to support SiFive FU740 SoC
dt-bindings: i2c: Add compatible string for AM64 SoC
i2c: designware: Make register offsets all of the same width
i2c: designware: Switch header to use BIT() and GENMASK()
i2c: pxa: move to generic GPIO recovery
i2c: sh_mobile: Mark adapter suspended during suspend
i2c: owl: Add compatible for the Actions Semi S500 I2C controller
dt-bindings: i2c: owl: Convert Actions Semi Owl binding to a schema
i2c: imx: support slave mode for imx I2C driver
i2c: ismt: Adding support for I2C_SMBUS_BLOCK_PROC_CALL
i2c: ocores: Avoid false-positive error log message.
Revert "i2c: qcom-geni: Disable DMA processing on the Lenovo Yoga C630"
i2c: mxs: Remove unneeded platform_device_id
i2c: pca-platform: drop two members from driver data that are assigned to only
i2c: imx: Remove unused .id_table support
i2c: nvidia-gpu: drop empty stub for runtime pm
dt-bindings: i2c: mellanox,i2c-mlxbf: convert txt to YAML schema
i2c: mv64xxx: Add bus error recovery
...
Diffstat (limited to 'drivers/soc')
-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); |