1802d0beecafe (Thomas Gleixner 2019-05-27 08:55:21 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 2) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 3) *
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 4) * Copyright (C) STMicroelectronics SA 2017
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 5) * Author(s): M'boumba Cedric Madianga <cedric.madianga@gmail.com>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 6) * Pierre-Yves Mordret <pierre-yves.mordret@st.com>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 7) *
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 8) * Driver for STM32 MDMA controller
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 9) *
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 10) * Inspired by stm32-dma.c and dma-jz4780.c
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 11) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 12)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 13) #include <linux/clk.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 14) #include <linux/delay.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 15) #include <linux/dmaengine.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 16) #include <linux/dma-mapping.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 17) #include <linux/dmapool.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 18) #include <linux/err.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 19) #include <linux/init.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 20) #include <linux/iopoll.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 21) #include <linux/jiffies.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 22) #include <linux/list.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 23) #include <linux/log2.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 24) #include <linux/module.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 25) #include <linux/of.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 26) #include <linux/of_device.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 27) #include <linux/of_dma.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 28) #include <linux/platform_device.h>
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 29) #include <linux/pm_runtime.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 30) #include <linux/reset.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 31) #include <linux/slab.h>
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 32)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 33) #include "virt-dma.h"
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 34)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 35) /* MDMA Generic getter/setter */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 36) #define STM32_MDMA_SHIFT(n) (ffs(n) - 1)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 37) #define STM32_MDMA_SET(n, mask) (((n) << STM32_MDMA_SHIFT(mask)) & \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 38) (mask))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 39) #define STM32_MDMA_GET(n, mask) (((n) & (mask)) >> \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 40) STM32_MDMA_SHIFT(mask))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 41)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 42) #define STM32_MDMA_GISR0 0x0000 /* MDMA Int Status Reg 1 */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 43) #define STM32_MDMA_GISR1 0x0004 /* MDMA Int Status Reg 2 */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 44)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 45) /* MDMA Channel x interrupt/status register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 46) #define STM32_MDMA_CISR(x) (0x40 + 0x40 * (x)) /* x = 0..62 */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 47) #define STM32_MDMA_CISR_CRQA BIT(16)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 48) #define STM32_MDMA_CISR_TCIF BIT(4)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 49) #define STM32_MDMA_CISR_BTIF BIT(3)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 50) #define STM32_MDMA_CISR_BRTIF BIT(2)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 51) #define STM32_MDMA_CISR_CTCIF BIT(1)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 52) #define STM32_MDMA_CISR_TEIF BIT(0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 53)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 54) /* MDMA Channel x interrupt flag clear register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 55) #define STM32_MDMA_CIFCR(x) (0x44 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 56) #define STM32_MDMA_CIFCR_CLTCIF BIT(4)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 57) #define STM32_MDMA_CIFCR_CBTIF BIT(3)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 58) #define STM32_MDMA_CIFCR_CBRTIF BIT(2)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 59) #define STM32_MDMA_CIFCR_CCTCIF BIT(1)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 60) #define STM32_MDMA_CIFCR_CTEIF BIT(0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 61) #define STM32_MDMA_CIFCR_CLEAR_ALL (STM32_MDMA_CIFCR_CLTCIF \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 62) | STM32_MDMA_CIFCR_CBTIF \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 63) | STM32_MDMA_CIFCR_CBRTIF \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 64) | STM32_MDMA_CIFCR_CCTCIF \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 65) | STM32_MDMA_CIFCR_CTEIF)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 66)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 67) /* MDMA Channel x error status register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 68) #define STM32_MDMA_CESR(x) (0x48 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 69) #define STM32_MDMA_CESR_BSE BIT(11)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 70) #define STM32_MDMA_CESR_ASR BIT(10)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 71) #define STM32_MDMA_CESR_TEMD BIT(9)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 72) #define STM32_MDMA_CESR_TELD BIT(8)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 73) #define STM32_MDMA_CESR_TED BIT(7)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 74) #define STM32_MDMA_CESR_TEA_MASK GENMASK(6, 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 75)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 76) /* MDMA Channel x control register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 77) #define STM32_MDMA_CCR(x) (0x4C + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 78) #define STM32_MDMA_CCR_SWRQ BIT(16)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 79) #define STM32_MDMA_CCR_WEX BIT(14)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 80) #define STM32_MDMA_CCR_HEX BIT(13)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 81) #define STM32_MDMA_CCR_BEX BIT(12)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 82) #define STM32_MDMA_CCR_PL_MASK GENMASK(7, 6)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 83) #define STM32_MDMA_CCR_PL(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 84) STM32_MDMA_CCR_PL_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 85) #define STM32_MDMA_CCR_TCIE BIT(5)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 86) #define STM32_MDMA_CCR_BTIE BIT(4)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 87) #define STM32_MDMA_CCR_BRTIE BIT(3)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 88) #define STM32_MDMA_CCR_CTCIE BIT(2)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 89) #define STM32_MDMA_CCR_TEIE BIT(1)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 90) #define STM32_MDMA_CCR_EN BIT(0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 91) #define STM32_MDMA_CCR_IRQ_MASK (STM32_MDMA_CCR_TCIE \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 92) | STM32_MDMA_CCR_BTIE \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 93) | STM32_MDMA_CCR_BRTIE \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 94) | STM32_MDMA_CCR_CTCIE \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 95) | STM32_MDMA_CCR_TEIE)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 96)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 97) /* MDMA Channel x transfer configuration register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 98) #define STM32_MDMA_CTCR(x) (0x50 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 99) #define STM32_MDMA_CTCR_BWM BIT(31)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 100) #define STM32_MDMA_CTCR_SWRM BIT(30)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 101) #define STM32_MDMA_CTCR_TRGM_MSK GENMASK(29, 28)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 102) #define STM32_MDMA_CTCR_TRGM(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 103) STM32_MDMA_CTCR_TRGM_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 104) #define STM32_MDMA_CTCR_TRGM_GET(n) STM32_MDMA_GET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 105) STM32_MDMA_CTCR_TRGM_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 106) #define STM32_MDMA_CTCR_PAM_MASK GENMASK(27, 26)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 107) #define STM32_MDMA_CTCR_PAM(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 108) STM32_MDMA_CTCR_PAM_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 109) #define STM32_MDMA_CTCR_PKE BIT(25)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 110) #define STM32_MDMA_CTCR_TLEN_MSK GENMASK(24, 18)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 111) #define STM32_MDMA_CTCR_TLEN(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 112) STM32_MDMA_CTCR_TLEN_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 113) #define STM32_MDMA_CTCR_TLEN_GET(n) STM32_MDMA_GET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 114) STM32_MDMA_CTCR_TLEN_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 115) #define STM32_MDMA_CTCR_LEN2_MSK GENMASK(25, 18)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 116) #define STM32_MDMA_CTCR_LEN2(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 117) STM32_MDMA_CTCR_LEN2_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 118) #define STM32_MDMA_CTCR_LEN2_GET(n) STM32_MDMA_GET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 119) STM32_MDMA_CTCR_LEN2_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 120) #define STM32_MDMA_CTCR_DBURST_MASK GENMASK(17, 15)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 121) #define STM32_MDMA_CTCR_DBURST(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 122) STM32_MDMA_CTCR_DBURST_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 123) #define STM32_MDMA_CTCR_SBURST_MASK GENMASK(14, 12)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 124) #define STM32_MDMA_CTCR_SBURST(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 125) STM32_MDMA_CTCR_SBURST_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 126) #define STM32_MDMA_CTCR_DINCOS_MASK GENMASK(11, 10)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 127) #define STM32_MDMA_CTCR_DINCOS(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 128) STM32_MDMA_CTCR_DINCOS_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 129) #define STM32_MDMA_CTCR_SINCOS_MASK GENMASK(9, 8)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 130) #define STM32_MDMA_CTCR_SINCOS(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 131) STM32_MDMA_CTCR_SINCOS_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 132) #define STM32_MDMA_CTCR_DSIZE_MASK GENMASK(7, 6)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 133) #define STM32_MDMA_CTCR_DSIZE(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 134) STM32_MDMA_CTCR_DSIZE_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 135) #define STM32_MDMA_CTCR_SSIZE_MASK GENMASK(5, 4)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 136) #define STM32_MDMA_CTCR_SSIZE(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 137) STM32_MDMA_CTCR_SSIZE_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 138) #define STM32_MDMA_CTCR_DINC_MASK GENMASK(3, 2)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 139) #define STM32_MDMA_CTCR_DINC(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 140) STM32_MDMA_CTCR_DINC_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 141) #define STM32_MDMA_CTCR_SINC_MASK GENMASK(1, 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 142) #define STM32_MDMA_CTCR_SINC(n) STM32_MDMA_SET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 143) STM32_MDMA_CTCR_SINC_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 144) #define STM32_MDMA_CTCR_CFG_MASK (STM32_MDMA_CTCR_SINC_MASK \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 145) | STM32_MDMA_CTCR_DINC_MASK \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 146) | STM32_MDMA_CTCR_SINCOS_MASK \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 147) | STM32_MDMA_CTCR_DINCOS_MASK \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 148) | STM32_MDMA_CTCR_LEN2_MSK \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 149) | STM32_MDMA_CTCR_TRGM_MSK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 150)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 151) /* MDMA Channel x block number of data register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 152) #define STM32_MDMA_CBNDTR(x) (0x54 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 153) #define STM32_MDMA_CBNDTR_BRC_MK GENMASK(31, 20)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 154) #define STM32_MDMA_CBNDTR_BRC(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 155) STM32_MDMA_CBNDTR_BRC_MK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 156) #define STM32_MDMA_CBNDTR_BRC_GET(n) STM32_MDMA_GET((n), \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 157) STM32_MDMA_CBNDTR_BRC_MK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 158)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 159) #define STM32_MDMA_CBNDTR_BRDUM BIT(19)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 160) #define STM32_MDMA_CBNDTR_BRSUM BIT(18)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 161) #define STM32_MDMA_CBNDTR_BNDT_MASK GENMASK(16, 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 162) #define STM32_MDMA_CBNDTR_BNDT(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 163) STM32_MDMA_CBNDTR_BNDT_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 164)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 165) /* MDMA Channel x source address register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 166) #define STM32_MDMA_CSAR(x) (0x58 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 167)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 168) /* MDMA Channel x destination address register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 169) #define STM32_MDMA_CDAR(x) (0x5C + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 170)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 171) /* MDMA Channel x block repeat address update register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 172) #define STM32_MDMA_CBRUR(x) (0x60 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 173) #define STM32_MDMA_CBRUR_DUV_MASK GENMASK(31, 16)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 174) #define STM32_MDMA_CBRUR_DUV(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 175) STM32_MDMA_CBRUR_DUV_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 176) #define STM32_MDMA_CBRUR_SUV_MASK GENMASK(15, 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 177) #define STM32_MDMA_CBRUR_SUV(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 178) STM32_MDMA_CBRUR_SUV_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 179)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 180) /* MDMA Channel x link address register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 181) #define STM32_MDMA_CLAR(x) (0x64 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 182)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 183) /* MDMA Channel x trigger and bus selection register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 184) #define STM32_MDMA_CTBR(x) (0x68 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 185) #define STM32_MDMA_CTBR_DBUS BIT(17)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 186) #define STM32_MDMA_CTBR_SBUS BIT(16)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 187) #define STM32_MDMA_CTBR_TSEL_MASK GENMASK(7, 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 188) #define STM32_MDMA_CTBR_TSEL(n) STM32_MDMA_SET(n, \
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 189) STM32_MDMA_CTBR_TSEL_MASK)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 190)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 191) /* MDMA Channel x mask address register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 192) #define STM32_MDMA_CMAR(x) (0x70 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 193)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 194) /* MDMA Channel x mask data register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 195) #define STM32_MDMA_CMDR(x) (0x74 + 0x40 * (x))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 196)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 197) #define STM32_MDMA_MAX_BUF_LEN 128
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 198) #define STM32_MDMA_MAX_BLOCK_LEN 65536
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 199) #define STM32_MDMA_MAX_CHANNELS 63
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 200) #define STM32_MDMA_MAX_REQUESTS 256
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 201) #define STM32_MDMA_MAX_BURST 128
e1263f9277bad (Amelie Delaunay 2021-01-04 15:20:45 +0100 202) #define STM32_MDMA_VERY_HIGH_PRIORITY 0x3
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 203)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 204) enum stm32_mdma_trigger_mode {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 205) STM32_MDMA_BUFFER,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 206) STM32_MDMA_BLOCK,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 207) STM32_MDMA_BLOCK_REP,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 208) STM32_MDMA_LINKED_LIST,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 209) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 210)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 211) enum stm32_mdma_width {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 212) STM32_MDMA_BYTE,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 213) STM32_MDMA_HALF_WORD,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 214) STM32_MDMA_WORD,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 215) STM32_MDMA_DOUBLE_WORD,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 216) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 217)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 218) enum stm32_mdma_inc_mode {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 219) STM32_MDMA_FIXED = 0,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 220) STM32_MDMA_INC = 2,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 221) STM32_MDMA_DEC = 3,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 222) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 223)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 224) struct stm32_mdma_chan_config {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 225) u32 request;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 226) u32 priority_level;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 227) u32 transfer_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 228) u32 mask_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 229) u32 mask_data;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 230) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 231)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 232) struct stm32_mdma_hwdesc {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 233) u32 ctcr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 234) u32 cbndtr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 235) u32 csar;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 236) u32 cdar;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 237) u32 cbrur;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 238) u32 clar;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 239) u32 ctbr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 240) u32 dummy;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 241) u32 cmar;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 242) u32 cmdr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 243) } __aligned(64);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 244)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 245) struct stm32_mdma_desc_node {
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 246) struct stm32_mdma_hwdesc *hwdesc;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 247) dma_addr_t hwdesc_phys;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 248) };
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 249)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 250) struct stm32_mdma_desc {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 251) struct virt_dma_desc vdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 252) u32 ccr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 253) bool cyclic;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 254) u32 count;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 255) struct stm32_mdma_desc_node node[];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 256) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 257)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 258) struct stm32_mdma_chan {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 259) struct virt_dma_chan vchan;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 260) struct dma_pool *desc_pool;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 261) u32 id;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 262) struct stm32_mdma_desc *desc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 263) u32 curr_hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 264) struct dma_slave_config dma_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 265) struct stm32_mdma_chan_config chan_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 266) bool busy;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 267) u32 mem_burst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 268) u32 mem_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 269) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 270)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 271) struct stm32_mdma_device {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 272) struct dma_device ddev;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 273) void __iomem *base;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 274) struct clk *clk;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 275) int irq;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 276) u32 nr_channels;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 277) u32 nr_requests;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 278) u32 nr_ahb_addr_masks;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 279) struct stm32_mdma_chan chan[STM32_MDMA_MAX_CHANNELS];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 280) u32 ahb_addr_masks[];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 281) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 282)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 283) static struct stm32_mdma_device *stm32_mdma_get_dev(
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 284) struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 285) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 286) return container_of(chan->vchan.chan.device, struct stm32_mdma_device,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 287) ddev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 288) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 289)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 290) static struct stm32_mdma_chan *to_stm32_mdma_chan(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 291) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 292) return container_of(c, struct stm32_mdma_chan, vchan.chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 293) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 294)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 295) static struct stm32_mdma_desc *to_stm32_mdma_desc(struct virt_dma_desc *vdesc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 296) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 297) return container_of(vdesc, struct stm32_mdma_desc, vdesc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 298) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 299)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 300) static struct device *chan2dev(struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 301) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 302) return &chan->vchan.chan.dev->device;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 303) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 304)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 305) static struct device *mdma2dev(struct stm32_mdma_device *mdma_dev)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 306) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 307) return mdma_dev->ddev.dev;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 308) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 309)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 310) static u32 stm32_mdma_read(struct stm32_mdma_device *dmadev, u32 reg)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 311) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 312) return readl_relaxed(dmadev->base + reg);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 313) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 314)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 315) static void stm32_mdma_write(struct stm32_mdma_device *dmadev, u32 reg, u32 val)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 316) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 317) writel_relaxed(val, dmadev->base + reg);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 318) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 319)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 320) static void stm32_mdma_set_bits(struct stm32_mdma_device *dmadev, u32 reg,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 321) u32 mask)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 322) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 323) void __iomem *addr = dmadev->base + reg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 324)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 325) writel_relaxed(readl_relaxed(addr) | mask, addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 326) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 327)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 328) static void stm32_mdma_clr_bits(struct stm32_mdma_device *dmadev, u32 reg,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 329) u32 mask)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 330) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 331) void __iomem *addr = dmadev->base + reg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 332)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 333) writel_relaxed(readl_relaxed(addr) & ~mask, addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 334) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 335)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 336) static struct stm32_mdma_desc *stm32_mdma_alloc_desc(
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 337) struct stm32_mdma_chan *chan, u32 count)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 338) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 339) struct stm32_mdma_desc *desc;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 340) int i;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 341)
8145dce88a788 (Gustavo A. R. Silva 2020-10-08 09:18:28 -0500 342) desc = kzalloc(struct_size(desc, node, count), GFP_NOWAIT);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 343) if (!desc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 344) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 345)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 346) for (i = 0; i < count; i++) {
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 347) desc->node[i].hwdesc =
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 348) dma_pool_alloc(chan->desc_pool, GFP_NOWAIT,
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 349) &desc->node[i].hwdesc_phys);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 350) if (!desc->node[i].hwdesc)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 351) goto err;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 352) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 353)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 354) desc->count = count;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 355)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 356) return desc;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 357)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 358) err:
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 359) dev_err(chan2dev(chan), "Failed to allocate descriptor\n");
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 360) while (--i >= 0)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 361) dma_pool_free(chan->desc_pool, desc->node[i].hwdesc,
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 362) desc->node[i].hwdesc_phys);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 363) kfree(desc);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 364) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 365) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 366)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 367) static void stm32_mdma_desc_free(struct virt_dma_desc *vdesc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 368) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 369) struct stm32_mdma_desc *desc = to_stm32_mdma_desc(vdesc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 370) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(vdesc->tx.chan);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 371) int i;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 372)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 373) for (i = 0; i < desc->count; i++)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 374) dma_pool_free(chan->desc_pool, desc->node[i].hwdesc,
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 375) desc->node[i].hwdesc_phys);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 376) kfree(desc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 377) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 378)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 379) static int stm32_mdma_get_width(struct stm32_mdma_chan *chan,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 380) enum dma_slave_buswidth width)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 381) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 382) switch (width) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 383) case DMA_SLAVE_BUSWIDTH_1_BYTE:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 384) case DMA_SLAVE_BUSWIDTH_2_BYTES:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 385) case DMA_SLAVE_BUSWIDTH_4_BYTES:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 386) case DMA_SLAVE_BUSWIDTH_8_BYTES:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 387) return ffs(width) - 1;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 388) default:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 389) dev_err(chan2dev(chan), "Dma bus width %i not supported\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 390) width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 391) return -EINVAL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 392) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 393) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 394)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 395) static enum dma_slave_buswidth stm32_mdma_get_max_width(dma_addr_t addr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 396) u32 buf_len, u32 tlen)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 397) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 398) enum dma_slave_buswidth max_width = DMA_SLAVE_BUSWIDTH_8_BYTES;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 399)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 400) for (max_width = DMA_SLAVE_BUSWIDTH_8_BYTES;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 401) max_width > DMA_SLAVE_BUSWIDTH_1_BYTE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 402) max_width >>= 1) {
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 403) /*
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 404) * Address and buffer length both have to be aligned on
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 405) * bus width
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 406) */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 407) if ((((buf_len | addr) & (max_width - 1)) == 0) &&
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 408) tlen >= max_width)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 409) break;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 410) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 411)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 412) return max_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 413) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 414)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 415) static u32 stm32_mdma_get_best_burst(u32 buf_len, u32 tlen, u32 max_burst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 416) enum dma_slave_buswidth width)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 417) {
ee6de9ac527f0 (Pierre-Yves MORDRET 2018-04-13 15:52:12 +0200 418) u32 best_burst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 419)
ee6de9ac527f0 (Pierre-Yves MORDRET 2018-04-13 15:52:12 +0200 420) best_burst = min((u32)1 << __ffs(tlen | buf_len),
ee6de9ac527f0 (Pierre-Yves MORDRET 2018-04-13 15:52:12 +0200 421) max_burst * width) / width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 422)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 423) return (best_burst > 0) ? best_burst : 1;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 424) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 425)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 426) static int stm32_mdma_disable_chan(struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 427) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 428) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 429) u32 ccr, cisr, id, reg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 430) int ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 431)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 432) id = chan->id;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 433) reg = STM32_MDMA_CCR(id);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 434)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 435) /* Disable interrupts */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 436) stm32_mdma_clr_bits(dmadev, reg, STM32_MDMA_CCR_IRQ_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 437)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 438) ccr = stm32_mdma_read(dmadev, reg);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 439) if (ccr & STM32_MDMA_CCR_EN) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 440) stm32_mdma_clr_bits(dmadev, reg, STM32_MDMA_CCR_EN);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 441)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 442) /* Ensure that any ongoing transfer has been completed */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 443) ret = readl_relaxed_poll_timeout_atomic(
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 444) dmadev->base + STM32_MDMA_CISR(id), cisr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 445) (cisr & STM32_MDMA_CISR_CTCIF), 10, 1000);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 446) if (ret) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 447) dev_err(chan2dev(chan), "%s: timeout!\n", __func__);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 448) return -EBUSY;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 449) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 450) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 451)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 452) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 453) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 454)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 455) static void stm32_mdma_stop(struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 456) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 457) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 458) u32 status;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 459) int ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 460)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 461) /* Disable DMA */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 462) ret = stm32_mdma_disable_chan(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 463) if (ret < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 464) return;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 465)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 466) /* Clear interrupt status if it is there */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 467) status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 468) if (status) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 469) dev_dbg(chan2dev(chan), "%s(): clearing interrupt: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 470) __func__, status);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 471) stm32_mdma_set_bits(dmadev, STM32_MDMA_CIFCR(chan->id), status);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 472) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 473)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 474) chan->busy = false;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 475) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 476)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 477) static void stm32_mdma_set_bus(struct stm32_mdma_device *dmadev, u32 *ctbr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 478) u32 ctbr_mask, u32 src_addr)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 479) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 480) u32 mask;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 481) int i;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 482)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 483) /* Check if memory device is on AHB or AXI */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 484) *ctbr &= ~ctbr_mask;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 485) mask = src_addr & 0xF0000000;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 486) for (i = 0; i < dmadev->nr_ahb_addr_masks; i++) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 487) if (mask == dmadev->ahb_addr_masks[i]) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 488) *ctbr |= ctbr_mask;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 489) break;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 490) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 491) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 492) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 493)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 494) static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 495) enum dma_transfer_direction direction,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 496) u32 *mdma_ccr, u32 *mdma_ctcr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 497) u32 *mdma_ctbr, dma_addr_t addr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 498) u32 buf_len)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 499) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 500) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 501) struct stm32_mdma_chan_config *chan_config = &chan->chan_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 502) enum dma_slave_buswidth src_addr_width, dst_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 503) phys_addr_t src_addr, dst_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 504) int src_bus_width, dst_bus_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 505) u32 src_maxburst, dst_maxburst, src_best_burst, dst_best_burst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 506) u32 ccr, ctcr, ctbr, tlen;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 507)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 508) src_addr_width = chan->dma_config.src_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 509) dst_addr_width = chan->dma_config.dst_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 510) src_maxburst = chan->dma_config.src_maxburst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 511) dst_maxburst = chan->dma_config.dst_maxburst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 512)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 513) ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 514) ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 515) ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 516)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 517) /* Enable HW request mode */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 518) ctcr &= ~STM32_MDMA_CTCR_SWRM;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 519)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 520) /* Set DINC, SINC, DINCOS, SINCOS, TRGM and TLEN retrieve from DT */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 521) ctcr &= ~STM32_MDMA_CTCR_CFG_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 522) ctcr |= chan_config->transfer_config & STM32_MDMA_CTCR_CFG_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 523)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 524) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 525) * For buffer transfer length (TLEN) we have to set
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 526) * the number of bytes - 1 in CTCR register
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 527) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 528) tlen = STM32_MDMA_CTCR_LEN2_GET(ctcr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 529) ctcr &= ~STM32_MDMA_CTCR_LEN2_MSK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 530) ctcr |= STM32_MDMA_CTCR_TLEN((tlen - 1));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 531)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 532) /* Disable Pack Enable */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 533) ctcr &= ~STM32_MDMA_CTCR_PKE;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 534)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 535) /* Check burst size constraints */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 536) if (src_maxburst * src_addr_width > STM32_MDMA_MAX_BURST ||
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 537) dst_maxburst * dst_addr_width > STM32_MDMA_MAX_BURST) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 538) dev_err(chan2dev(chan),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 539) "burst size * bus width higher than %d bytes\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 540) STM32_MDMA_MAX_BURST);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 541) return -EINVAL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 542) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 543)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 544) if ((!is_power_of_2(src_maxburst) && src_maxburst > 0) ||
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 545) (!is_power_of_2(dst_maxburst) && dst_maxburst > 0)) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 546) dev_err(chan2dev(chan), "burst size must be a power of 2\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 547) return -EINVAL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 548) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 549)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 550) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 551) * Configure channel control:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 552) * - Clear SW request as in this case this is a HW one
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 553) * - Clear WEX, HEX and BEX bits
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 554) * - Set priority level
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 555) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 556) ccr &= ~(STM32_MDMA_CCR_SWRQ | STM32_MDMA_CCR_WEX | STM32_MDMA_CCR_HEX |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 557) STM32_MDMA_CCR_BEX | STM32_MDMA_CCR_PL_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 558) ccr |= STM32_MDMA_CCR_PL(chan_config->priority_level);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 559)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 560) /* Configure Trigger selection */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 561) ctbr &= ~STM32_MDMA_CTBR_TSEL_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 562) ctbr |= STM32_MDMA_CTBR_TSEL(chan_config->request);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 563)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 564) switch (direction) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 565) case DMA_MEM_TO_DEV:
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 566) dst_addr = chan->dma_config.dst_addr;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 567)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 568) /* Set device data size */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 569) dst_bus_width = stm32_mdma_get_width(chan, dst_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 570) if (dst_bus_width < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 571) return dst_bus_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 572) ctcr &= ~STM32_MDMA_CTCR_DSIZE_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 573) ctcr |= STM32_MDMA_CTCR_DSIZE(dst_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 574)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 575) /* Set device burst value */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 576) dst_best_burst = stm32_mdma_get_best_burst(buf_len, tlen,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 577) dst_maxburst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 578) dst_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 579) chan->mem_burst = dst_best_burst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 580) ctcr &= ~STM32_MDMA_CTCR_DBURST_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 581) ctcr |= STM32_MDMA_CTCR_DBURST((ilog2(dst_best_burst)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 582)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 583) /* Set memory data size */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 584) src_addr_width = stm32_mdma_get_max_width(addr, buf_len, tlen);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 585) chan->mem_width = src_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 586) src_bus_width = stm32_mdma_get_width(chan, src_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 587) if (src_bus_width < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 588) return src_bus_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 589) ctcr &= ~STM32_MDMA_CTCR_SSIZE_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 590) STM32_MDMA_CTCR_SINCOS_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 591) ctcr |= STM32_MDMA_CTCR_SSIZE(src_bus_width) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 592) STM32_MDMA_CTCR_SINCOS(src_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 593)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 594) /* Set memory burst value */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 595) src_maxburst = STM32_MDMA_MAX_BUF_LEN / src_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 596) src_best_burst = stm32_mdma_get_best_burst(buf_len, tlen,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 597) src_maxburst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 598) src_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 599) chan->mem_burst = src_best_burst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 600) ctcr &= ~STM32_MDMA_CTCR_SBURST_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 601) ctcr |= STM32_MDMA_CTCR_SBURST((ilog2(src_best_burst)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 602)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 603) /* Select bus */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 604) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_DBUS,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 605) dst_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 606)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 607) if (dst_bus_width != src_bus_width)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 608) ctcr |= STM32_MDMA_CTCR_PKE;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 609)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 610) /* Set destination address */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 611) stm32_mdma_write(dmadev, STM32_MDMA_CDAR(chan->id), dst_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 612) break;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 613)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 614) case DMA_DEV_TO_MEM:
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 615) src_addr = chan->dma_config.src_addr;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 616)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 617) /* Set device data size */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 618) src_bus_width = stm32_mdma_get_width(chan, src_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 619) if (src_bus_width < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 620) return src_bus_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 621) ctcr &= ~STM32_MDMA_CTCR_SSIZE_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 622) ctcr |= STM32_MDMA_CTCR_SSIZE(src_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 623)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 624) /* Set device burst value */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 625) src_best_burst = stm32_mdma_get_best_burst(buf_len, tlen,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 626) src_maxburst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 627) src_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 628) ctcr &= ~STM32_MDMA_CTCR_SBURST_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 629) ctcr |= STM32_MDMA_CTCR_SBURST((ilog2(src_best_burst)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 630)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 631) /* Set memory data size */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 632) dst_addr_width = stm32_mdma_get_max_width(addr, buf_len, tlen);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 633) chan->mem_width = dst_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 634) dst_bus_width = stm32_mdma_get_width(chan, dst_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 635) if (dst_bus_width < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 636) return dst_bus_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 637) ctcr &= ~(STM32_MDMA_CTCR_DSIZE_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 638) STM32_MDMA_CTCR_DINCOS_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 639) ctcr |= STM32_MDMA_CTCR_DSIZE(dst_bus_width) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 640) STM32_MDMA_CTCR_DINCOS(dst_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 641)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 642) /* Set memory burst value */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 643) dst_maxburst = STM32_MDMA_MAX_BUF_LEN / dst_addr_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 644) dst_best_burst = stm32_mdma_get_best_burst(buf_len, tlen,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 645) dst_maxburst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 646) dst_addr_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 647) ctcr &= ~STM32_MDMA_CTCR_DBURST_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 648) ctcr |= STM32_MDMA_CTCR_DBURST((ilog2(dst_best_burst)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 649)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 650) /* Select bus */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 651) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_SBUS,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 652) src_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 653)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 654) if (dst_bus_width != src_bus_width)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 655) ctcr |= STM32_MDMA_CTCR_PKE;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 656)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 657) /* Set source address */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 658) stm32_mdma_write(dmadev, STM32_MDMA_CSAR(chan->id), src_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 659) break;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 660)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 661) default:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 662) dev_err(chan2dev(chan), "Dma direction is not supported\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 663) return -EINVAL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 664) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 665)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 666) *mdma_ccr = ccr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 667) *mdma_ctcr = ctcr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 668) *mdma_ctbr = ctbr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 669)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 670) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 671) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 672)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 673) static void stm32_mdma_dump_hwdesc(struct stm32_mdma_chan *chan,
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 674) struct stm32_mdma_desc_node *node)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 675) {
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 676) dev_dbg(chan2dev(chan), "hwdesc: %pad\n", &node->hwdesc_phys);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 677) dev_dbg(chan2dev(chan), "CTCR: 0x%08x\n", node->hwdesc->ctcr);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 678) dev_dbg(chan2dev(chan), "CBNDTR: 0x%08x\n", node->hwdesc->cbndtr);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 679) dev_dbg(chan2dev(chan), "CSAR: 0x%08x\n", node->hwdesc->csar);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 680) dev_dbg(chan2dev(chan), "CDAR: 0x%08x\n", node->hwdesc->cdar);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 681) dev_dbg(chan2dev(chan), "CBRUR: 0x%08x\n", node->hwdesc->cbrur);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 682) dev_dbg(chan2dev(chan), "CLAR: 0x%08x\n", node->hwdesc->clar);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 683) dev_dbg(chan2dev(chan), "CTBR: 0x%08x\n", node->hwdesc->ctbr);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 684) dev_dbg(chan2dev(chan), "CMAR: 0x%08x\n", node->hwdesc->cmar);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 685) dev_dbg(chan2dev(chan), "CMDR: 0x%08x\n\n", node->hwdesc->cmdr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 686) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 687)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 688) static void stm32_mdma_setup_hwdesc(struct stm32_mdma_chan *chan,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 689) struct stm32_mdma_desc *desc,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 690) enum dma_transfer_direction dir, u32 count,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 691) dma_addr_t src_addr, dma_addr_t dst_addr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 692) u32 len, u32 ctcr, u32 ctbr, bool is_last,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 693) bool is_first, bool is_cyclic)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 694) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 695) struct stm32_mdma_chan_config *config = &chan->chan_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 696) struct stm32_mdma_hwdesc *hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 697) u32 next = count + 1;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 698)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 699) hwdesc = desc->node[count].hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 700) hwdesc->ctcr = ctcr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 701) hwdesc->cbndtr &= ~(STM32_MDMA_CBNDTR_BRC_MK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 702) STM32_MDMA_CBNDTR_BRDUM |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 703) STM32_MDMA_CBNDTR_BRSUM |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 704) STM32_MDMA_CBNDTR_BNDT_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 705) hwdesc->cbndtr |= STM32_MDMA_CBNDTR_BNDT(len);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 706) hwdesc->csar = src_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 707) hwdesc->cdar = dst_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 708) hwdesc->cbrur = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 709) hwdesc->ctbr = ctbr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 710) hwdesc->cmar = config->mask_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 711) hwdesc->cmdr = config->mask_data;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 712)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 713) if (is_last) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 714) if (is_cyclic)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 715) hwdesc->clar = desc->node[0].hwdesc_phys;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 716) else
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 717) hwdesc->clar = 0;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 718) } else {
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 719) hwdesc->clar = desc->node[next].hwdesc_phys;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 720) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 721)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 722) stm32_mdma_dump_hwdesc(chan, &desc->node[count]);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 723) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 724)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 725) static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 726) struct stm32_mdma_desc *desc,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 727) struct scatterlist *sgl, u32 sg_len,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 728) enum dma_transfer_direction direction)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 729) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 730) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 731) struct dma_slave_config *dma_config = &chan->dma_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 732) struct scatterlist *sg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 733) dma_addr_t src_addr, dst_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 734) u32 ccr, ctcr, ctbr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 735) int i, ret = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 736)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 737) for_each_sg(sgl, sg, sg_len, i) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 738) if (sg_dma_len(sg) > STM32_MDMA_MAX_BLOCK_LEN) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 739) dev_err(chan2dev(chan), "Invalid block len\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 740) return -EINVAL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 741) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 742)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 743) if (direction == DMA_MEM_TO_DEV) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 744) src_addr = sg_dma_address(sg);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 745) dst_addr = dma_config->dst_addr;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 746) ret = stm32_mdma_set_xfer_param(chan, direction, &ccr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 747) &ctcr, &ctbr, src_addr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 748) sg_dma_len(sg));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 749) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_SBUS,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 750) src_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 751) } else {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 752) src_addr = dma_config->src_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 753) dst_addr = sg_dma_address(sg);
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 754) ret = stm32_mdma_set_xfer_param(chan, direction, &ccr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 755) &ctcr, &ctbr, dst_addr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 756) sg_dma_len(sg));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 757) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_DBUS,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 758) dst_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 759) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 760)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 761) if (ret < 0)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 762) return ret;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 763)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 764) stm32_mdma_setup_hwdesc(chan, desc, direction, i, src_addr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 765) dst_addr, sg_dma_len(sg), ctcr, ctbr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 766) i == sg_len - 1, i == 0, false);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 767) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 768)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 769) /* Enable interrupts */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 770) ccr &= ~STM32_MDMA_CCR_IRQ_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 771) ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 772) if (sg_len > 1)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 773) ccr |= STM32_MDMA_CCR_BTIE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 774) desc->ccr = ccr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 775)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 776) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 777) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 778)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 779) static struct dma_async_tx_descriptor *
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 780) stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 781) u32 sg_len, enum dma_transfer_direction direction,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 782) unsigned long flags, void *context)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 783) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 784) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 785) struct stm32_mdma_desc *desc;
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 786) int i, ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 787)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 788) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 789) * Once DMA is in setup cyclic mode the channel we cannot assign this
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 790) * channel anymore. The DMA channel needs to be aborted or terminated
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 791) * for allowing another request.
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 792) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 793) if (chan->desc && chan->desc->cyclic) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 794) dev_err(chan2dev(chan),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 795) "Request not allowed when dma in cyclic mode\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 796) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 797) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 798)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 799) desc = stm32_mdma_alloc_desc(chan, sg_len);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 800) if (!desc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 801) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 802)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 803) ret = stm32_mdma_setup_xfer(chan, desc, sgl, sg_len, direction);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 804) if (ret < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 805) goto xfer_setup_err;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 806)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 807) desc->cyclic = false;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 808)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 809) return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 810)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 811) xfer_setup_err:
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 812) for (i = 0; i < desc->count; i++)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 813) dma_pool_free(chan->desc_pool, desc->node[i].hwdesc,
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 814) desc->node[i].hwdesc_phys);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 815) kfree(desc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 816) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 817) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 818)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 819) static struct dma_async_tx_descriptor *
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 820) stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 821) size_t buf_len, size_t period_len,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 822) enum dma_transfer_direction direction,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 823) unsigned long flags)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 824) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 825) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 826) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 827) struct dma_slave_config *dma_config = &chan->dma_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 828) struct stm32_mdma_desc *desc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 829) dma_addr_t src_addr, dst_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 830) u32 ccr, ctcr, ctbr, count;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 831) int i, ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 832)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 833) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 834) * Once DMA is in setup cyclic mode the channel we cannot assign this
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 835) * channel anymore. The DMA channel needs to be aborted or terminated
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 836) * for allowing another request.
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 837) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 838) if (chan->desc && chan->desc->cyclic) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 839) dev_err(chan2dev(chan),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 840) "Request not allowed when dma in cyclic mode\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 841) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 842) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 843)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 844) if (!buf_len || !period_len || period_len > STM32_MDMA_MAX_BLOCK_LEN) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 845) dev_err(chan2dev(chan), "Invalid buffer/period len\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 846) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 847) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 848)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 849) if (buf_len % period_len) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 850) dev_err(chan2dev(chan), "buf_len not multiple of period_len\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 851) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 852) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 853)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 854) count = buf_len / period_len;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 855)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 856) desc = stm32_mdma_alloc_desc(chan, count);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 857) if (!desc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 858) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 859)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 860) /* Select bus */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 861) if (direction == DMA_MEM_TO_DEV) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 862) src_addr = buf_addr;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 863) ret = stm32_mdma_set_xfer_param(chan, direction, &ccr, &ctcr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 864) &ctbr, src_addr, period_len);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 865) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_SBUS,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 866) src_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 867) } else {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 868) dst_addr = buf_addr;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 869) ret = stm32_mdma_set_xfer_param(chan, direction, &ccr, &ctcr,
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 870) &ctbr, dst_addr, period_len);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 871) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_DBUS,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 872) dst_addr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 873) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 874)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 875) if (ret < 0)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 876) goto xfer_setup_err;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 877)
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 878) /* Enable interrupts */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 879) ccr &= ~STM32_MDMA_CCR_IRQ_MASK;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 880) ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE | STM32_MDMA_CCR_BTIE;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 881) desc->ccr = ccr;
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 882)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 883) /* Configure hwdesc list */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 884) for (i = 0; i < count; i++) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 885) if (direction == DMA_MEM_TO_DEV) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 886) src_addr = buf_addr + i * period_len;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 887) dst_addr = dma_config->dst_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 888) } else {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 889) src_addr = dma_config->src_addr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 890) dst_addr = buf_addr + i * period_len;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 891) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 892)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 893) stm32_mdma_setup_hwdesc(chan, desc, direction, i, src_addr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 894) dst_addr, period_len, ctcr, ctbr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 895) i == count - 1, i == 0, true);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 896) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 897)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 898) desc->cyclic = true;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 899)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 900) return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 901)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 902) xfer_setup_err:
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 903) for (i = 0; i < desc->count; i++)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 904) dma_pool_free(chan->desc_pool, desc->node[i].hwdesc,
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 905) desc->node[i].hwdesc_phys);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 906) kfree(desc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 907) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 908) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 909)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 910) static struct dma_async_tx_descriptor *
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 911) stm32_mdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, dma_addr_t src,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 912) size_t len, unsigned long flags)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 913) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 914) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 915) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 916) enum dma_slave_buswidth max_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 917) struct stm32_mdma_desc *desc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 918) struct stm32_mdma_hwdesc *hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 919) u32 ccr, ctcr, ctbr, cbndtr, count, max_burst, mdma_burst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 920) u32 best_burst, tlen;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 921) size_t xfer_count, offset;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 922) int src_bus_width, dst_bus_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 923) int i;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 924)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 925) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 926) * Once DMA is in setup cyclic mode the channel we cannot assign this
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 927) * channel anymore. The DMA channel needs to be aborted or terminated
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 928) * to allow another request
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 929) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 930) if (chan->desc && chan->desc->cyclic) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 931) dev_err(chan2dev(chan),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 932) "Request not allowed when dma in cyclic mode\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 933) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 934) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 935)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 936) count = DIV_ROUND_UP(len, STM32_MDMA_MAX_BLOCK_LEN);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 937) desc = stm32_mdma_alloc_desc(chan, count);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 938) if (!desc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 939) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 940)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 941) ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 942) ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 943) ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 944) cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 945)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 946) /* Enable sw req, some interrupts and clear other bits */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 947) ccr &= ~(STM32_MDMA_CCR_WEX | STM32_MDMA_CCR_HEX |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 948) STM32_MDMA_CCR_BEX | STM32_MDMA_CCR_PL_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 949) STM32_MDMA_CCR_IRQ_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 950) ccr |= STM32_MDMA_CCR_TEIE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 951)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 952) /* Enable SW request mode, dest/src inc and clear other bits */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 953) ctcr &= ~(STM32_MDMA_CTCR_BWM | STM32_MDMA_CTCR_TRGM_MSK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 954) STM32_MDMA_CTCR_PAM_MASK | STM32_MDMA_CTCR_PKE |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 955) STM32_MDMA_CTCR_TLEN_MSK | STM32_MDMA_CTCR_DBURST_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 956) STM32_MDMA_CTCR_SBURST_MASK | STM32_MDMA_CTCR_DINCOS_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 957) STM32_MDMA_CTCR_SINCOS_MASK | STM32_MDMA_CTCR_DSIZE_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 958) STM32_MDMA_CTCR_SSIZE_MASK | STM32_MDMA_CTCR_DINC_MASK |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 959) STM32_MDMA_CTCR_SINC_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 960) ctcr |= STM32_MDMA_CTCR_SWRM | STM32_MDMA_CTCR_SINC(STM32_MDMA_INC) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 961) STM32_MDMA_CTCR_DINC(STM32_MDMA_INC);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 962)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 963) /* Reset HW request */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 964) ctbr &= ~STM32_MDMA_CTBR_TSEL_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 965)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 966) /* Select bus */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 967) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_SBUS, src);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 968) stm32_mdma_set_bus(dmadev, &ctbr, STM32_MDMA_CTBR_DBUS, dest);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 969)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 970) /* Clear CBNDTR registers */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 971) cbndtr &= ~(STM32_MDMA_CBNDTR_BRC_MK | STM32_MDMA_CBNDTR_BRDUM |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 972) STM32_MDMA_CBNDTR_BRSUM | STM32_MDMA_CBNDTR_BNDT_MASK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 973)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 974) if (len <= STM32_MDMA_MAX_BLOCK_LEN) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 975) cbndtr |= STM32_MDMA_CBNDTR_BNDT(len);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 976) if (len <= STM32_MDMA_MAX_BUF_LEN) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 977) /* Setup a buffer transfer */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 978) ccr |= STM32_MDMA_CCR_TCIE | STM32_MDMA_CCR_CTCIE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 979) ctcr |= STM32_MDMA_CTCR_TRGM(STM32_MDMA_BUFFER);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 980) } else {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 981) /* Setup a block transfer */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 982) ccr |= STM32_MDMA_CCR_BTIE | STM32_MDMA_CCR_CTCIE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 983) ctcr |= STM32_MDMA_CTCR_TRGM(STM32_MDMA_BLOCK);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 984) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 985)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 986) tlen = STM32_MDMA_MAX_BUF_LEN;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 987) ctcr |= STM32_MDMA_CTCR_TLEN((tlen - 1));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 988)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 989) /* Set source best burst size */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 990) max_width = stm32_mdma_get_max_width(src, len, tlen);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 991) src_bus_width = stm32_mdma_get_width(chan, max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 992)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 993) max_burst = tlen / max_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 994) best_burst = stm32_mdma_get_best_burst(len, tlen, max_burst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 995) max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 996) mdma_burst = ilog2(best_burst);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 997)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 998) ctcr |= STM32_MDMA_CTCR_SBURST(mdma_burst) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 999) STM32_MDMA_CTCR_SSIZE(src_bus_width) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1000) STM32_MDMA_CTCR_SINCOS(src_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1001)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1002) /* Set destination best burst size */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 1003) max_width = stm32_mdma_get_max_width(dest, len, tlen);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1004) dst_bus_width = stm32_mdma_get_width(chan, max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1005)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1006) max_burst = tlen / max_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1007) best_burst = stm32_mdma_get_best_burst(len, tlen, max_burst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1008) max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1009) mdma_burst = ilog2(best_burst);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1010)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1011) ctcr |= STM32_MDMA_CTCR_DBURST(mdma_burst) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1012) STM32_MDMA_CTCR_DSIZE(dst_bus_width) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1013) STM32_MDMA_CTCR_DINCOS(dst_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1014)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1015) if (dst_bus_width != src_bus_width)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1016) ctcr |= STM32_MDMA_CTCR_PKE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1017)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1018) /* Prepare hardware descriptor */
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 1019) hwdesc = desc->node[0].hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1020) hwdesc->ctcr = ctcr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1021) hwdesc->cbndtr = cbndtr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1022) hwdesc->csar = src;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1023) hwdesc->cdar = dest;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1024) hwdesc->cbrur = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1025) hwdesc->clar = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1026) hwdesc->ctbr = ctbr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1027) hwdesc->cmar = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1028) hwdesc->cmdr = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1029)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 1030) stm32_mdma_dump_hwdesc(chan, &desc->node[0]);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1031) } else {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1032) /* Setup a LLI transfer */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1033) ctcr |= STM32_MDMA_CTCR_TRGM(STM32_MDMA_LINKED_LIST) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1034) STM32_MDMA_CTCR_TLEN((STM32_MDMA_MAX_BUF_LEN - 1));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1035) ccr |= STM32_MDMA_CCR_BTIE | STM32_MDMA_CCR_CTCIE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1036) tlen = STM32_MDMA_MAX_BUF_LEN;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1037)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1038) for (i = 0, offset = 0; offset < len;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1039) i++, offset += xfer_count) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1040) xfer_count = min_t(size_t, len - offset,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1041) STM32_MDMA_MAX_BLOCK_LEN);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1042)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1043) /* Set source best burst size */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 1044) max_width = stm32_mdma_get_max_width(src, len, tlen);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1045) src_bus_width = stm32_mdma_get_width(chan, max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1046)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1047) max_burst = tlen / max_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1048) best_burst = stm32_mdma_get_best_burst(len, tlen,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1049) max_burst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1050) max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1051) mdma_burst = ilog2(best_burst);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1052)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1053) ctcr |= STM32_MDMA_CTCR_SBURST(mdma_burst) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1054) STM32_MDMA_CTCR_SSIZE(src_bus_width) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1055) STM32_MDMA_CTCR_SINCOS(src_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1056)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1057) /* Set destination best burst size */
d83f4131c2e06 (Pierre-Yves MORDRET 2017-10-17 15:43:47 +0200 1058) max_width = stm32_mdma_get_max_width(dest, len, tlen);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1059) dst_bus_width = stm32_mdma_get_width(chan, max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1060)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1061) max_burst = tlen / max_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1062) best_burst = stm32_mdma_get_best_burst(len, tlen,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1063) max_burst,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1064) max_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1065) mdma_burst = ilog2(best_burst);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1066)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1067) ctcr |= STM32_MDMA_CTCR_DBURST(mdma_burst) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1068) STM32_MDMA_CTCR_DSIZE(dst_bus_width) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1069) STM32_MDMA_CTCR_DINCOS(dst_bus_width);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1070)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1071) if (dst_bus_width != src_bus_width)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1072) ctcr |= STM32_MDMA_CTCR_PKE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1073)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1074) /* Prepare hardware descriptor */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1075) stm32_mdma_setup_hwdesc(chan, desc, DMA_MEM_TO_MEM, i,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1076) src + offset, dest + offset,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1077) xfer_count, ctcr, ctbr,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1078) i == count - 1, i == 0, false);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1079) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1080) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1081)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1082) desc->ccr = ccr;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1083)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1084) desc->cyclic = false;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1085)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1086) return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1087) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1088)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1089) static void stm32_mdma_dump_reg(struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1090) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1091) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1092)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1093) dev_dbg(chan2dev(chan), "CCR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1094) stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1095) dev_dbg(chan2dev(chan), "CTCR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1096) stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1097) dev_dbg(chan2dev(chan), "CBNDTR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1098) stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1099) dev_dbg(chan2dev(chan), "CSAR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1100) stm32_mdma_read(dmadev, STM32_MDMA_CSAR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1101) dev_dbg(chan2dev(chan), "CDAR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1102) stm32_mdma_read(dmadev, STM32_MDMA_CDAR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1103) dev_dbg(chan2dev(chan), "CBRUR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1104) stm32_mdma_read(dmadev, STM32_MDMA_CBRUR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1105) dev_dbg(chan2dev(chan), "CLAR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1106) stm32_mdma_read(dmadev, STM32_MDMA_CLAR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1107) dev_dbg(chan2dev(chan), "CTBR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1108) stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1109) dev_dbg(chan2dev(chan), "CMAR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1110) stm32_mdma_read(dmadev, STM32_MDMA_CMAR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1111) dev_dbg(chan2dev(chan), "CMDR: 0x%08x\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1112) stm32_mdma_read(dmadev, STM32_MDMA_CMDR(chan->id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1113) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1114)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1115) static void stm32_mdma_start_transfer(struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1116) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1117) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1118) struct virt_dma_desc *vdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1119) struct stm32_mdma_hwdesc *hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1120) u32 id = chan->id;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1121) u32 status, reg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1122)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1123) vdesc = vchan_next_desc(&chan->vchan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1124) if (!vdesc) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1125) chan->desc = NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1126) return;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1127) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1128)
dfc708812a2ac (Amelie Delaunay 2020-01-27 09:53:34 +0100 1129) list_del(&vdesc->node);
dfc708812a2ac (Amelie Delaunay 2020-01-27 09:53:34 +0100 1130)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1131) chan->desc = to_stm32_mdma_desc(vdesc);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 1132) hwdesc = chan->desc->node[0].hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1133) chan->curr_hwdesc = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1134)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1135) stm32_mdma_write(dmadev, STM32_MDMA_CCR(id), chan->desc->ccr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1136) stm32_mdma_write(dmadev, STM32_MDMA_CTCR(id), hwdesc->ctcr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1137) stm32_mdma_write(dmadev, STM32_MDMA_CBNDTR(id), hwdesc->cbndtr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1138) stm32_mdma_write(dmadev, STM32_MDMA_CSAR(id), hwdesc->csar);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1139) stm32_mdma_write(dmadev, STM32_MDMA_CDAR(id), hwdesc->cdar);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1140) stm32_mdma_write(dmadev, STM32_MDMA_CBRUR(id), hwdesc->cbrur);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1141) stm32_mdma_write(dmadev, STM32_MDMA_CLAR(id), hwdesc->clar);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1142) stm32_mdma_write(dmadev, STM32_MDMA_CTBR(id), hwdesc->ctbr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1143) stm32_mdma_write(dmadev, STM32_MDMA_CMAR(id), hwdesc->cmar);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1144) stm32_mdma_write(dmadev, STM32_MDMA_CMDR(id), hwdesc->cmdr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1145)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1146) /* Clear interrupt status if it is there */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1147) status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1148) if (status)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1149) stm32_mdma_set_bits(dmadev, STM32_MDMA_CIFCR(id), status);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1150)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1151) stm32_mdma_dump_reg(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1152)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1153) /* Start DMA */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1154) stm32_mdma_set_bits(dmadev, STM32_MDMA_CCR(id), STM32_MDMA_CCR_EN);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1155)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1156) /* Set SW request in case of MEM2MEM transfer */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1157) if (hwdesc->ctcr & STM32_MDMA_CTCR_SWRM) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1158) reg = STM32_MDMA_CCR(id);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1159) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CCR_SWRQ);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1160) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1161)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1162) chan->busy = true;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1163)
90ec93cb6bca5 (Benjamin Gaignard 2018-07-06 15:02:20 +0200 1164) dev_dbg(chan2dev(chan), "vchan %pK: started\n", &chan->vchan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1165) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1166)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1167) static void stm32_mdma_issue_pending(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1168) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1169) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1170) unsigned long flags;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1171)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1172) spin_lock_irqsave(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1173)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1174) if (!vchan_issue_pending(&chan->vchan))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1175) goto end;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1176)
90ec93cb6bca5 (Benjamin Gaignard 2018-07-06 15:02:20 +0200 1177) dev_dbg(chan2dev(chan), "vchan %pK: issued\n", &chan->vchan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1178)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1179) if (!chan->desc && !chan->busy)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1180) stm32_mdma_start_transfer(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1181)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1182) end:
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1183) spin_unlock_irqrestore(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1184) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1185)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1186) static int stm32_mdma_pause(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1187) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1188) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1189) unsigned long flags;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1190) int ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1191)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1192) spin_lock_irqsave(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1193) ret = stm32_mdma_disable_chan(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1194) spin_unlock_irqrestore(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1195)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1196) if (!ret)
90ec93cb6bca5 (Benjamin Gaignard 2018-07-06 15:02:20 +0200 1197) dev_dbg(chan2dev(chan), "vchan %pK: pause\n", &chan->vchan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1198)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1199) return ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1200) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1201)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1202) static int stm32_mdma_resume(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1203) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1204) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1205) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1206) struct stm32_mdma_hwdesc *hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1207) unsigned long flags;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1208) u32 status, reg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1209)
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 1210) hwdesc = chan->desc->node[chan->curr_hwdesc].hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1211)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1212) spin_lock_irqsave(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1213)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1214) /* Re-configure control register */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1215) stm32_mdma_write(dmadev, STM32_MDMA_CCR(chan->id), chan->desc->ccr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1216)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1217) /* Clear interrupt status if it is there */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1218) status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1219) if (status)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1220) stm32_mdma_set_bits(dmadev, STM32_MDMA_CIFCR(chan->id), status);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1221)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1222) stm32_mdma_dump_reg(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1223)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1224) /* Re-start DMA */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1225) reg = STM32_MDMA_CCR(chan->id);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1226) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CCR_EN);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1227)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1228) /* Set SW request in case of MEM2MEM transfer */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1229) if (hwdesc->ctcr & STM32_MDMA_CTCR_SWRM)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1230) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CCR_SWRQ);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1231)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1232) spin_unlock_irqrestore(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1233)
90ec93cb6bca5 (Benjamin Gaignard 2018-07-06 15:02:20 +0200 1234) dev_dbg(chan2dev(chan), "vchan %pK: resume\n", &chan->vchan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1235)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1236) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1237) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1238)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1239) static int stm32_mdma_terminate_all(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1240) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1241) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1242) unsigned long flags;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1243) LIST_HEAD(head);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1244)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1245) spin_lock_irqsave(&chan->vchan.lock, flags);
dfc708812a2ac (Amelie Delaunay 2020-01-27 09:53:34 +0100 1246) if (chan->desc) {
dfc708812a2ac (Amelie Delaunay 2020-01-27 09:53:34 +0100 1247) vchan_terminate_vdesc(&chan->desc->vdesc);
dfc708812a2ac (Amelie Delaunay 2020-01-27 09:53:34 +0100 1248) if (chan->busy)
dfc708812a2ac (Amelie Delaunay 2020-01-27 09:53:34 +0100 1249) stm32_mdma_stop(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1250) chan->desc = NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1251) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1252) vchan_get_all_descriptors(&chan->vchan, &head);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1253) spin_unlock_irqrestore(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1254)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1255) vchan_dma_desc_free_list(&chan->vchan, &head);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1256)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1257) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1258) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1259)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1260) static void stm32_mdma_synchronize(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1261) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1262) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1263)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1264) vchan_synchronize(&chan->vchan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1265) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1266)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1267) static int stm32_mdma_slave_config(struct dma_chan *c,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1268) struct dma_slave_config *config)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1269) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1270) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1271)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1272) memcpy(&chan->dma_config, config, sizeof(*config));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1273)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1274) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1275) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1276)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1277) static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1278) struct stm32_mdma_desc *desc,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1279) u32 curr_hwdesc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1280) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1281) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 1282) struct stm32_mdma_hwdesc *hwdesc = desc->node[0].hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1283) u32 cbndtr, residue, modulo, burst_size;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1284) int i;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1285)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1286) residue = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1287) for (i = curr_hwdesc + 1; i < desc->count; i++) {
bbb5a4e1e772c (Pierre-Yves MORDRET 2018-04-13 15:52:13 +0200 1288) hwdesc = desc->node[i].hwdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1289) residue += STM32_MDMA_CBNDTR_BNDT(hwdesc->cbndtr);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1290) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1291) cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1292) residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1293)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1294) if (!chan->mem_burst)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1295) return residue;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1296)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1297) burst_size = chan->mem_burst * chan->mem_width;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1298) modulo = residue % burst_size;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1299) if (modulo)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1300) residue = residue - modulo + burst_size;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1301)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1302) return residue;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1303) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1304)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1305) static enum dma_status stm32_mdma_tx_status(struct dma_chan *c,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1306) dma_cookie_t cookie,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1307) struct dma_tx_state *state)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1308) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1309) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1310) struct virt_dma_desc *vdesc;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1311) enum dma_status status;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1312) unsigned long flags;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1313) u32 residue = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1314)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1315) status = dma_cookie_status(c, cookie, state);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1316) if ((status == DMA_COMPLETE) || (!state))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1317) return status;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1318)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1319) spin_lock_irqsave(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1320)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1321) vdesc = vchan_find_desc(&chan->vchan, cookie);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1322) if (chan->desc && cookie == chan->desc->vdesc.tx.cookie)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1323) residue = stm32_mdma_desc_residue(chan, chan->desc,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1324) chan->curr_hwdesc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1325) else if (vdesc)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1326) residue = stm32_mdma_desc_residue(chan,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1327) to_stm32_mdma_desc(vdesc), 0);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1328) dma_set_residue(state, residue);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1329)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1330) spin_unlock_irqrestore(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1331)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1332) return status;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1333) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1334)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1335) static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1336) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1337) vchan_cookie_complete(&chan->desc->vdesc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1338) chan->desc = NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1339) chan->busy = false;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1340)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1341) /* Start the next transfer if this driver has a next desc */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1342) stm32_mdma_start_transfer(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1343) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1344)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1345) static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1346) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1347) struct stm32_mdma_device *dmadev = devid;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1348) struct stm32_mdma_chan *chan = devid;
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1349) u32 reg, id, ccr, ien, status;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1350)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1351) /* Find out which channel generates the interrupt */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1352) status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1353) if (status) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1354) id = __ffs(status);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1355) } else {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1356) status = readl_relaxed(dmadev->base + STM32_MDMA_GISR1);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1357) if (!status) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1358) dev_dbg(mdma2dev(dmadev), "spurious it\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1359) return IRQ_NONE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1360) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1361) id = __ffs(status);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1362) /*
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1363) * As GISR0 provides status for channel id from 0 to 31,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1364) * so GISR1 provides status for channel id from 32 to 62
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1365) */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1366) id += 32;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1367) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1368)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1369) chan = &dmadev->chan[id];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1370) if (!chan) {
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1371) dev_warn(mdma2dev(dmadev), "MDMA channel not initialized\n");
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1372) return IRQ_NONE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1373) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1374)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1375) /* Handle interrupt for the channel */
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1376) spin_lock(&chan->vchan.lock);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1377) status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(id));
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1378) /* Mask Channel ReQuest Active bit which can be set in case of MEM2MEM */
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1379) status &= ~STM32_MDMA_CISR_CRQA;
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1380) ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(id));
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1381) ien = (ccr & STM32_MDMA_CCR_IRQ_MASK) >> 1;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1382)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1383) if (!(status & ien)) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1384) spin_unlock(&chan->vchan.lock);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1385) dev_warn(chan2dev(chan),
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1386) "spurious it (status=0x%04x, ien=0x%04x)\n",
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1387) status, ien);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1388) return IRQ_NONE;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1389) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1390)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1391) reg = STM32_MDMA_CIFCR(id);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1392)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1393) if (status & STM32_MDMA_CISR_TEIF) {
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1394) dev_err(chan2dev(chan), "Transfer Err: stat=0x%08x\n",
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1395) readl_relaxed(dmadev->base + STM32_MDMA_CESR(id)));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1396) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CTEIF);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1397) status &= ~STM32_MDMA_CISR_TEIF;
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1398) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1399)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1400) if (status & STM32_MDMA_CISR_CTCIF) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1401) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CCTCIF);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1402) status &= ~STM32_MDMA_CISR_CTCIF;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1403) stm32_mdma_xfer_end(chan);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1404) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1405)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1406) if (status & STM32_MDMA_CISR_BRTIF) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1407) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CBRTIF);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1408) status &= ~STM32_MDMA_CISR_BRTIF;
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1409) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1410)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1411) if (status & STM32_MDMA_CISR_BTIF) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1412) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CBTIF);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1413) status &= ~STM32_MDMA_CISR_BTIF;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1414) chan->curr_hwdesc++;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1415) if (chan->desc && chan->desc->cyclic) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1416) if (chan->curr_hwdesc == chan->desc->count)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1417) chan->curr_hwdesc = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1418) vchan_cyclic_callback(&chan->desc->vdesc);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1419) }
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1420) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1421)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1422) if (status & STM32_MDMA_CISR_TCIF) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1423) stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CLTCIF);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1424) status &= ~STM32_MDMA_CISR_TCIF;
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1425) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1426)
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1427) if (status) {
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1428) stm32_mdma_set_bits(dmadev, reg, status);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1429) dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status);
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1430) if (!(ccr & STM32_MDMA_CCR_EN))
1d3dd68749b9f (Amelie Delaunay 2020-11-20 15:33:20 +0100 1431) dev_err(chan2dev(chan), "chan disabled by HW\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1432) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1433)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1434) spin_unlock(&chan->vchan.lock);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1435)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1436) return IRQ_HANDLED;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1437) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1438)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1439) static int stm32_mdma_alloc_chan_resources(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1440) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1441) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1442) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1443) int ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1444)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1445) chan->desc_pool = dmam_pool_create(dev_name(&c->dev->device),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1446) c->device->dev,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1447) sizeof(struct stm32_mdma_hwdesc),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1448) __alignof__(struct stm32_mdma_hwdesc),
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1449) 0);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1450) if (!chan->desc_pool) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1451) dev_err(chan2dev(chan), "failed to allocate descriptor pool\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1452) return -ENOMEM;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1453) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1454)
83eb4868d325b (Yu Kuai 2021-05-17 16:18:24 +0800 1455) ret = pm_runtime_resume_and_get(dmadev->ddev.dev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1456) if (ret < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1457) return ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1458)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1459) ret = stm32_mdma_disable_chan(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1460) if (ret < 0)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1461) pm_runtime_put(dmadev->ddev.dev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1462)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1463) return ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1464) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1465)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1466) static void stm32_mdma_free_chan_resources(struct dma_chan *c)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1467) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1468) struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1469) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1470) unsigned long flags;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1471)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1472) dev_dbg(chan2dev(chan), "Freeing channel %d\n", chan->id);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1473)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1474) if (chan->busy) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1475) spin_lock_irqsave(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1476) stm32_mdma_stop(chan);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1477) chan->desc = NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1478) spin_unlock_irqrestore(&chan->vchan.lock, flags);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1479) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1480)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1481) pm_runtime_put(dmadev->ddev.dev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1482) vchan_free_chan_resources(to_virt_chan(c));
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1483) dmam_pool_destroy(chan->desc_pool);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1484) chan->desc_pool = NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1485) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1486)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1487) static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1488) struct of_dma *ofdma)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1489) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1490) struct stm32_mdma_device *dmadev = ofdma->of_dma_data;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1491) struct stm32_mdma_chan *chan;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1492) struct dma_chan *c;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1493) struct stm32_mdma_chan_config config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1494)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1495) if (dma_spec->args_count < 5) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1496) dev_err(mdma2dev(dmadev), "Bad number of args\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1497) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1498) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1499)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1500) config.request = dma_spec->args[0];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1501) config.priority_level = dma_spec->args[1];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1502) config.transfer_config = dma_spec->args[2];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1503) config.mask_addr = dma_spec->args[3];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1504) config.mask_data = dma_spec->args[4];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1505)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1506) if (config.request >= dmadev->nr_requests) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1507) dev_err(mdma2dev(dmadev), "Bad request line\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1508) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1509) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1510)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1511) if (config.priority_level > STM32_MDMA_VERY_HIGH_PRIORITY) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1512) dev_err(mdma2dev(dmadev), "Priority level not supported\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1513) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1514) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1515)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1516) c = dma_get_any_slave_channel(&dmadev->ddev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1517) if (!c) {
d317d32b4f9ad (Colin Ian King 2018-04-28 23:03:52 +0100 1518) dev_err(mdma2dev(dmadev), "No more channels available\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1519) return NULL;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1520) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1521)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1522) chan = to_stm32_mdma_chan(c);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1523) chan->chan_config = config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1524)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1525) return c;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1526) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1527)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1528) static const struct of_device_id stm32_mdma_of_match[] = {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1529) { .compatible = "st,stm32h7-mdma", },
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1530) { /* sentinel */ },
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1531) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1532) MODULE_DEVICE_TABLE(of, stm32_mdma_of_match);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1533)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1534) static int stm32_mdma_probe(struct platform_device *pdev)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1535) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1536) struct stm32_mdma_chan *chan;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1537) struct stm32_mdma_device *dmadev;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1538) struct dma_device *dd;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1539) struct device_node *of_node;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1540) struct resource *res;
54d50c8184f69 (Etienne Carriere 2020-01-27 09:53:30 +0100 1541) struct reset_control *rst;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1542) u32 nr_channels, nr_requests;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1543) int i, count, ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1544)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1545) of_node = pdev->dev.of_node;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1546) if (!of_node)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1547) return -ENODEV;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1548)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1549) ret = device_property_read_u32(&pdev->dev, "dma-channels",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1550) &nr_channels);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1551) if (ret) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1552) nr_channels = STM32_MDMA_MAX_CHANNELS;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1553) dev_warn(&pdev->dev, "MDMA defaulting on %i channels\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1554) nr_channels);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1555) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1556)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1557) ret = device_property_read_u32(&pdev->dev, "dma-requests",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1558) &nr_requests);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1559) if (ret) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1560) nr_requests = STM32_MDMA_MAX_REQUESTS;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1561) dev_warn(&pdev->dev, "MDMA defaulting on %i request lines\n",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1562) nr_requests);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1563) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1564)
57dbd0e4b97d3 (Andy Shevchenko 2019-07-23 22:07:57 +0300 1565) count = device_property_count_u32(&pdev->dev, "st,ahb-addr-masks");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1566) if (count < 0)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1567) count = 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1568)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1569) dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev) + sizeof(u32) * count,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1570) GFP_KERNEL);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1571) if (!dmadev)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1572) return -ENOMEM;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1573)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1574) dmadev->nr_channels = nr_channels;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1575) dmadev->nr_requests = nr_requests;
9dfec7ca0ba7e (Pierre-Yves MORDRET 2019-03-25 17:21:55 +0100 1576) device_property_read_u32_array(&pdev->dev, "st,ahb-addr-masks",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1577) dmadev->ahb_addr_masks,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1578) count);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1579) dmadev->nr_ahb_addr_masks = count;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1580)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1581) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1582) dmadev->base = devm_ioremap_resource(&pdev->dev, res);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1583) if (IS_ERR(dmadev->base))
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1584) return PTR_ERR(dmadev->base);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1585)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1586) dmadev->clk = devm_clk_get(&pdev->dev, NULL);
1c966e1d948ba (Krzysztof Kozlowski 2020-08-28 17:26:36 +0200 1587) if (IS_ERR(dmadev->clk))
1c966e1d948ba (Krzysztof Kozlowski 2020-08-28 17:26:36 +0200 1588) return dev_err_probe(&pdev->dev, PTR_ERR(dmadev->clk),
1c966e1d948ba (Krzysztof Kozlowski 2020-08-28 17:26:36 +0200 1589) "Missing clock controller\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1590)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1591) ret = clk_prepare_enable(dmadev->clk);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1592) if (ret < 0) {
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1593) dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1594) return ret;
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1595) }
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1596)
54d50c8184f69 (Etienne Carriere 2020-01-27 09:53:30 +0100 1597) rst = devm_reset_control_get(&pdev->dev, NULL);
56cf8ddaa3115 (Amelie Delaunay 2020-01-27 09:53:32 +0100 1598) if (IS_ERR(rst)) {
56cf8ddaa3115 (Amelie Delaunay 2020-01-27 09:53:32 +0100 1599) ret = PTR_ERR(rst);
56cf8ddaa3115 (Amelie Delaunay 2020-01-27 09:53:32 +0100 1600) if (ret == -EPROBE_DEFER)
56cf8ddaa3115 (Amelie Delaunay 2020-01-27 09:53:32 +0100 1601) goto err_clk;
56cf8ddaa3115 (Amelie Delaunay 2020-01-27 09:53:32 +0100 1602) } else {
54d50c8184f69 (Etienne Carriere 2020-01-27 09:53:30 +0100 1603) reset_control_assert(rst);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1604) udelay(2);
54d50c8184f69 (Etienne Carriere 2020-01-27 09:53:30 +0100 1605) reset_control_deassert(rst);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1606) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1607)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1608) dd = &dmadev->ddev;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1609) dma_cap_set(DMA_SLAVE, dd->cap_mask);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1610) dma_cap_set(DMA_PRIVATE, dd->cap_mask);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1611) dma_cap_set(DMA_CYCLIC, dd->cap_mask);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1612) dma_cap_set(DMA_MEMCPY, dd->cap_mask);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1613) dd->device_alloc_chan_resources = stm32_mdma_alloc_chan_resources;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1614) dd->device_free_chan_resources = stm32_mdma_free_chan_resources;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1615) dd->device_tx_status = stm32_mdma_tx_status;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1616) dd->device_issue_pending = stm32_mdma_issue_pending;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1617) dd->device_prep_slave_sg = stm32_mdma_prep_slave_sg;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1618) dd->device_prep_dma_cyclic = stm32_mdma_prep_dma_cyclic;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1619) dd->device_prep_dma_memcpy = stm32_mdma_prep_dma_memcpy;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1620) dd->device_config = stm32_mdma_slave_config;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1621) dd->device_pause = stm32_mdma_pause;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1622) dd->device_resume = stm32_mdma_resume;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1623) dd->device_terminate_all = stm32_mdma_terminate_all;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1624) dd->device_synchronize = stm32_mdma_synchronize;
542fbc463aabd (Pierre-Yves MORDRET 2020-01-27 09:53:33 +0100 1625) dd->descriptor_reuse = true;
542fbc463aabd (Pierre-Yves MORDRET 2020-01-27 09:53:33 +0100 1626)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1627) dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1628) BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1629) BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1630) BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1631) dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1632) BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1633) BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1634) BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1635) dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) |
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1636) BIT(DMA_MEM_TO_MEM);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1637) dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1638) dd->max_burst = STM32_MDMA_MAX_BURST;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1639) dd->dev = &pdev->dev;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1640) INIT_LIST_HEAD(&dd->channels);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1641)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1642) for (i = 0; i < dmadev->nr_channels; i++) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1643) chan = &dmadev->chan[i];
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1644) chan->id = i;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1645) chan->vchan.desc_free = stm32_mdma_desc_free;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1646) vchan_init(&chan->vchan, dd);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1647) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1648)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1649) dmadev->irq = platform_get_irq(pdev, 0);
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1650) if (dmadev->irq < 0) {
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1651) ret = dmadev->irq;
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1652) goto err_clk;
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1653) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1654)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1655) ret = devm_request_irq(&pdev->dev, dmadev->irq, stm32_mdma_irq_handler,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1656) 0, dev_name(&pdev->dev), dmadev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1657) if (ret) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1658) dev_err(&pdev->dev, "failed to request IRQ\n");
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1659) goto err_clk;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1660) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1661)
42f604b6516b9 (Huang Shijie 2018-08-06 16:52:24 +0800 1662) ret = dmaenginem_async_device_register(dd);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1663) if (ret)
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1664) goto err_clk;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1665)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1666) ret = of_dma_controller_register(of_node, stm32_mdma_of_xlate, dmadev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1667) if (ret < 0) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1668) dev_err(&pdev->dev,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1669) "STM32 MDMA DMA OF registration failed %d\n", ret);
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1670) goto err_clk;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1671) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1672)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1673) platform_set_drvdata(pdev, dmadev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1674) pm_runtime_set_active(&pdev->dev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1675) pm_runtime_enable(&pdev->dev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1676) pm_runtime_get_noresume(&pdev->dev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1677) pm_runtime_put(&pdev->dev);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1678)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1679) dev_info(&pdev->dev, "STM32 MDMA driver registered\n");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1680)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1681) return 0;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1682)
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1683) err_clk:
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1684) clk_disable_unprepare(dmadev->clk);
cb0bc2d09166e (Etienne Carriere 2020-01-27 09:53:31 +0100 1685)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1686) return ret;
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1687) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1688)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1689) #ifdef CONFIG_PM
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1690) static int stm32_mdma_runtime_suspend(struct device *dev)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1691) {
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1692) struct stm32_mdma_device *dmadev = dev_get_drvdata(dev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1693)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1694) clk_disable_unprepare(dmadev->clk);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1695)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1696) return 0;
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1697) }
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1698)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1699) static int stm32_mdma_runtime_resume(struct device *dev)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1700) {
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1701) struct stm32_mdma_device *dmadev = dev_get_drvdata(dev);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1702) int ret;
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1703)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1704) ret = clk_prepare_enable(dmadev->clk);
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1705) if (ret) {
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1706) dev_err(dev, "failed to prepare_enable clock\n");
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1707) return ret;
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1708) }
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1709)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1710) return 0;
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1711) }
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1712) #endif
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1713)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1714) #ifdef CONFIG_PM_SLEEP
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1715) static int stm32_mdma_pm_suspend(struct device *dev)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1716) {
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1717) struct stm32_mdma_device *dmadev = dev_get_drvdata(dev);
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1718) u32 ccr, id;
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1719) int ret;
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1720)
83eb4868d325b (Yu Kuai 2021-05-17 16:18:24 +0800 1721) ret = pm_runtime_resume_and_get(dev);
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1722) if (ret < 0)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1723) return ret;
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1724)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1725) for (id = 0; id < dmadev->nr_channels; id++) {
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1726) ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(id));
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1727) if (ccr & STM32_MDMA_CCR_EN) {
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1728) dev_warn(dev, "Suspend is prevented by Chan %i\n", id);
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1729) return -EBUSY;
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1730) }
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1731) }
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1732)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1733) pm_runtime_put_sync(dev);
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1734)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1735) pm_runtime_force_suspend(dev);
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1736)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1737) return 0;
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1738) }
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1739)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1740) static int stm32_mdma_pm_resume(struct device *dev)
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1741) {
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1742) return pm_runtime_force_resume(dev);
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1743) }
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1744) #endif
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1745)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1746) static const struct dev_pm_ops stm32_mdma_pm_ops = {
7cb819c856d96 (Pierre-Yves MORDRET 2020-01-27 09:53:29 +0100 1747) SET_SYSTEM_SLEEP_PM_OPS(stm32_mdma_pm_suspend, stm32_mdma_pm_resume)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1748) SET_RUNTIME_PM_OPS(stm32_mdma_runtime_suspend,
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1749) stm32_mdma_runtime_resume, NULL)
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1750) };
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1751)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1752) static struct platform_driver stm32_mdma_driver = {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1753) .probe = stm32_mdma_probe,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1754) .driver = {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1755) .name = "stm32-mdma",
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1756) .of_match_table = stm32_mdma_of_match,
89e987e3b4d6b (Pierre-Yves MORDRET 2019-01-03 11:17:10 +0100 1757) .pm = &stm32_mdma_pm_ops,
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1758) },
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1759) };
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1760)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1761) static int __init stm32_mdma_init(void)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1762) {
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1763) return platform_driver_register(&stm32_mdma_driver);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1764) }
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1765)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1766) subsys_initcall(stm32_mdma_init);
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1767)
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1768) MODULE_DESCRIPTION("Driver for STM32 MDMA controller");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1769) MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1770) MODULE_AUTHOR("Pierre-Yves Mordret <pierre-yves.mordret@st.com>");
a4ffb13c8946a (Pierre-Yves MORDRET 2017-09-28 17:36:41 +0200 1771) MODULE_LICENSE("GPL v2");