mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
This is a set of patches from Lee Jones to start converting
the ux500 to fetch DMA channels from the device tree: - Full DT support and channel mapping in the DMA40 driver - Dropping of platform data for migrated devices on the DT boot path. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJRnms9AAoJEEEQszewGV1zvAMP/R96pExEBjlf+o61FvPafFpw myZtprUXJvkHphOY+UVHk/gv+1EUFbNwcQzu5k3Ah14DOmv7qtjusylMDbJoFPar dDVU8PtsT+4qmCzgLRd+ATkZEBMOAaJFscD7UV1qtY0AIpz8jS1gJpOO08qqQBg1 unEj7szVEfs1eCrcDnvfMmeBM7gqZMTFkWmGkpuNqH5MdN3HLMKgAFJEc+GafP4d saaX3fCdiif5OYkD9DyQO7I4zsSaAs8OcpYbQKyRmWhm/wuLGPDoFsfBjOXGgFRr V/XwJD74lNgGduC8bCRsgj4LDEdRDO0s1NlqRWpiX/W1GX2lo4wraLdPmd16AaTQ LUb34o10sN4/0mJnbweWxmFPyzGNfw/Kl+ea4gA0vOQ9QDtTIrtnjHOtowGAdhBJ lDob3vAd5huCU287p8me+nc6Y4eJaJS0LjcsU1yy7U4O9mLsZnubPaVPiQu2gUGe GUKYd5J40aslxRuyP/MCA0bnCBhjyH62YfN9omw0Cmt/VQvyKXFF4JWdQuS/Dn3s 29JQfOWCf8xGYwZaQYSzluczP+wokfWnx8wrQ7c1Kb9G2NcDlv6f2/mbDRG9pmXV 2xs8v/fxONDfSCrPVCiBiHH4sYtcbD6UMjiTB76etygOmb3oeSK/Aqx0Sm90MG6Q xL9gkP14kNTaZBGCDNLN =RTiI -----END PGP SIGNATURE----- Merge tag 'ux500-dma40-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into next/drivers From Linus Walleij: This is a set of patches from Lee Jones to start converting the ux500 to fetch DMA channels from the device tree: - Full DT support and channel mapping in the DMA40 driver - Dropping of platform data for migrated devices on the DT boot path. * tag 'ux500-dma40-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson: (36 commits) ARM: ux500: Register Cryp and Hash platform drivers on Snowball crypto: ux500/[cryp|hash] - Show successful start-up in the bootlog ARM: ux500: Stop passing Cryp DMA channel config information though pdata crypto: ux500/cryp - Set DMA configuration though dma_slave_config() crypto: ux500/cryp - Prepare clock before enabling it ARM: ux500: Stop passing Hash DMA channel config information though pdata crypto: ux500/hash - Set DMA configuration though dma_slave_config() crypto: ux500/hash - Prepare clock before enabling it ARM: ux500: Remove unnecessary attributes from DMA channel request pdata dmaengine: ste_dma40: Correct copy/paste error ARM: ux500: Remove DMA address look-up table dmaengine: ste_dma40: Remove redundant address fetching function dmaengine: ste_dma40: Only use addresses passed as configuration information ARM: ux500: Stop passing UART's platform data for Device Tree boots dmaengine: ste_dma40: Don't configure runtime configurable setup during allocate dmaengine: ste_dma40: Remove unnecessary call to d40_phy_cfg() dmaengine: ste_dma40: Separate Logical Global Interrupt Mask (GIM) unmasking ARM: ux500: Pass remnant platform data though to DMA40 driver dmaengine: ste_dma40: Supply full Device Tree parsing support dmaengine: ste_dma40: Allow driver to be probe()able when DT is enabled ... Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
6f39ef575d
17 changed files with 498 additions and 660 deletions
62
Documentation/devicetree/bindings/dma/ste-dma40.txt
Normal file
62
Documentation/devicetree/bindings/dma/ste-dma40.txt
Normal file
|
@ -0,0 +1,62 @@
|
|||
* DMA40 DMA Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "stericsson,dma40"
|
||||
- reg: Address range of the DMAC registers
|
||||
- reg-names: Names of the above areas to use during resource look-up
|
||||
- interrupt: Should contain the DMAC interrupt number
|
||||
- #dma-cells: must be <3>
|
||||
|
||||
Optional properties:
|
||||
- dma-channels: Number of channels supported by hardware - if not present
|
||||
the driver will attempt to obtain the information from H/W
|
||||
|
||||
Example:
|
||||
|
||||
dma: dma-controller@801C0000 {
|
||||
compatible = "stericsson,db8500-dma40", "stericsson,dma40";
|
||||
reg = <0x801C0000 0x1000 0x40010000 0x800>;
|
||||
reg-names = "base", "lcpa";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 25 0x4>;
|
||||
|
||||
#dma-cells = <2>;
|
||||
dma-channels = <8>;
|
||||
};
|
||||
|
||||
Clients
|
||||
Required properties:
|
||||
- dmas: Comma separated list of dma channel requests
|
||||
- dma-names: Names of the aforementioned requested channels
|
||||
|
||||
Each dmas request consists of 4 cells:
|
||||
1. A phandle pointing to the DMA controller
|
||||
2. Device Type
|
||||
3. The DMA request line number (only when 'use fixed channel' is set)
|
||||
4. A 32bit mask specifying; mode, direction and endianess [NB: This list will grow]
|
||||
0x00000001: Mode:
|
||||
Logical channel when unset
|
||||
Physical channel when set
|
||||
0x00000002: Direction:
|
||||
Memory to Device when unset
|
||||
Device to Memory when set
|
||||
0x00000004: Endianess:
|
||||
Little endian when unset
|
||||
Big endian when set
|
||||
0x00000008: Use fixed channel:
|
||||
Use automatic channel selection when unset
|
||||
Use DMA request line number when set
|
||||
|
||||
Example:
|
||||
|
||||
uart@80120000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x80120000 0x1000>;
|
||||
interrupts = <0 11 0x4>;
|
||||
|
||||
dmas = <&dma 13 0 0x2>, /* Logical - DevToMem */
|
||||
<&dma 13 0 0x0>; /* Logical - MemToDev */
|
||||
dma-names = "rx", "rx";
|
||||
|
||||
status = "disabled";
|
||||
};
|
|
@ -22,27 +22,13 @@
|
|||
static struct stedma40_chan_cfg msp0_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
|
||||
.src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
|
||||
/* data_width is set during configuration */
|
||||
.dev_type = DB8500_DMA_DEV31_MSP0_SLIM0_CH0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp0_dma_tx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
|
||||
.src_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX,
|
||||
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
|
||||
/* data_width is set during configuration */
|
||||
.dev_type = DB8500_DMA_DEV31_MSP0_SLIM0_CH0,
|
||||
};
|
||||
|
||||
struct msp_i2s_platform_data msp0_platform_data = {
|
||||
|
@ -54,27 +40,13 @@ struct msp_i2s_platform_data msp0_platform_data = {
|
|||
static struct stedma40_chan_cfg msp1_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
|
||||
.src_dev_type = DB8500_DMA_DEV30_MSP3_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
|
||||
/* data_width is set during configuration */
|
||||
.dev_type = DB8500_DMA_DEV30_MSP3,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp1_dma_tx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
|
||||
.src_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV30_MSP1_TX,
|
||||
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
|
||||
/* data_width is set during configuration */
|
||||
.dev_type = DB8500_DMA_DEV30_MSP1,
|
||||
};
|
||||
|
||||
struct msp_i2s_platform_data msp1_platform_data = {
|
||||
|
@ -86,31 +58,15 @@ struct msp_i2s_platform_data msp1_platform_data = {
|
|||
static struct stedma40_chan_cfg msp2_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
|
||||
.src_dev_type = DB8500_DMA_DEV14_MSP2_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
|
||||
/* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_1,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_1,
|
||||
|
||||
/* data_width is set during configuration */
|
||||
.dev_type = DB8500_DMA_DEV14_MSP2,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp2_dma_tx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
|
||||
.src_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV14_MSP2_TX,
|
||||
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
|
||||
.dev_type = DB8500_DMA_DEV14_MSP2,
|
||||
.use_fixed_channel = true,
|
||||
.phy_channel = 1,
|
||||
|
||||
/* data_width is set during configuration */
|
||||
};
|
||||
|
||||
static struct platform_device *db8500_add_msp_i2s(struct device *parent,
|
||||
|
|
|
@ -35,19 +35,13 @@
|
|||
struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV29_SD_MM0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV29_SD_MM0,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -88,19 +82,13 @@ void mop500_sdi_tc35892_init(struct device *parent)
|
|||
static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV32_SD_MM1_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV32_SD_MM1,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV32_SD_MM1,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -125,19 +113,13 @@ struct mmci_platform_data mop500_sdi1_data = {
|
|||
struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV28_SD_MM2,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV28_SD_MM2,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -163,19 +145,13 @@ struct mmci_platform_data mop500_sdi2_data = {
|
|||
struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV42_SD_MM4,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV42_SD_MM4,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -425,35 +425,20 @@ void mop500_snowball_ethernet_clock_enable(void)
|
|||
static struct cryp_platform_data u8500_cryp1_platform_data = {
|
||||
.mem_to_engine = {
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV48_CAC1_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV48_CAC1,
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
},
|
||||
.engine_to_mem = {
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV48_CAC1_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV48_CAC1,
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_4,
|
||||
}
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg u8500_hash_dma_cfg_tx = {
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV50_HAC1_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV50_HAC1_TX,
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_16,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_16,
|
||||
};
|
||||
|
||||
static struct hash_platform_data u8500_hash1_platform_data = {
|
||||
|
@ -471,19 +456,13 @@ static struct platform_device *mop500_platform_devs[] __initdata = {
|
|||
static struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV8_SSP0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV8_SSP0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV8_SSP0_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV8_SSP0,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -512,55 +491,37 @@ static void __init mop500_spi_init(struct device *parent)
|
|||
static struct stedma40_chan_cfg uart0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV13_UART0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV13_UART0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV13_UART0_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV13_UART0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart1_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV12_UART1_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV12_UART1,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart1_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV12_UART1_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV12_UART1,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart2_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV11_UART2_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV11_UART2,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV11_UART2_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dev_type = DB8500_DMA_DEV11_UART2,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -676,6 +637,8 @@ static void __init snowball_init_machine(void)
|
|||
|
||||
mop500_snowball_ethernet_clock_enable();
|
||||
|
||||
u8500_cryp1_hash1_init(parent);
|
||||
|
||||
/* This board has full regulator constraints */
|
||||
regulator_has_full_constraints();
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ extern struct amba_pl011_data uart0_plat;
|
|||
extern struct amba_pl011_data uart1_plat;
|
||||
extern struct amba_pl011_data uart2_plat;
|
||||
extern struct pl022_ssp_controller ssp0_plat;
|
||||
extern struct stedma40_platform_data dma40_plat_data;
|
||||
|
||||
extern void mop500_sdi_init(struct device *parent);
|
||||
extern void snowball_sdi_init(struct device *parent);
|
||||
|
|
|
@ -162,26 +162,15 @@ static void __init db8500_add_gpios(struct device *parent)
|
|||
dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE);
|
||||
}
|
||||
|
||||
static int usb_db8500_rx_dma_cfg[] = {
|
||||
DB8500_DMA_DEV38_USB_OTG_IEP_1_9,
|
||||
DB8500_DMA_DEV37_USB_OTG_IEP_2_10,
|
||||
DB8500_DMA_DEV36_USB_OTG_IEP_3_11,
|
||||
DB8500_DMA_DEV19_USB_OTG_IEP_4_12,
|
||||
DB8500_DMA_DEV18_USB_OTG_IEP_5_13,
|
||||
DB8500_DMA_DEV17_USB_OTG_IEP_6_14,
|
||||
DB8500_DMA_DEV16_USB_OTG_IEP_7_15,
|
||||
DB8500_DMA_DEV39_USB_OTG_IEP_8
|
||||
};
|
||||
|
||||
static int usb_db8500_tx_dma_cfg[] = {
|
||||
DB8500_DMA_DEV38_USB_OTG_OEP_1_9,
|
||||
DB8500_DMA_DEV37_USB_OTG_OEP_2_10,
|
||||
DB8500_DMA_DEV36_USB_OTG_OEP_3_11,
|
||||
DB8500_DMA_DEV19_USB_OTG_OEP_4_12,
|
||||
DB8500_DMA_DEV18_USB_OTG_OEP_5_13,
|
||||
DB8500_DMA_DEV17_USB_OTG_OEP_6_14,
|
||||
DB8500_DMA_DEV16_USB_OTG_OEP_7_15,
|
||||
DB8500_DMA_DEV39_USB_OTG_OEP_8
|
||||
static int usb_db8500_dma_cfg[] = {
|
||||
DB8500_DMA_DEV38_USB_OTG_IEP_AND_OEP_1_9,
|
||||
DB8500_DMA_DEV37_USB_OTG_IEP_AND_OEP_2_10,
|
||||
DB8500_DMA_DEV36_USB_OTG_IEP_AND_OEP_3_11,
|
||||
DB8500_DMA_DEV19_USB_OTG_IEP_AND_OEP_4_12,
|
||||
DB8500_DMA_DEV18_USB_OTG_IEP_AND_OEP_5_13,
|
||||
DB8500_DMA_DEV17_USB_OTG_IEP_AND_OEP_6_14,
|
||||
DB8500_DMA_DEV16_USB_OTG_IEP_AND_OEP_7_15,
|
||||
DB8500_DMA_DEV39_USB_OTG_IEP_AND_OEP_8
|
||||
};
|
||||
|
||||
static const char *db8500_read_soc_id(void)
|
||||
|
@ -215,7 +204,7 @@ struct device * __init u8500_init_devices(void)
|
|||
|
||||
db8500_add_rtc(parent);
|
||||
db8500_add_gpios(parent);
|
||||
db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
|
||||
db8500_add_usb(parent, usb_db8500_dma_cfg, usb_db8500_dma_cfg);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
|
||||
platform_devs[i]->dev.parent = parent;
|
||||
|
@ -232,17 +221,7 @@ static struct device * __init u8500_of_init_devices(void)
|
|||
{
|
||||
struct device *parent = db8500_soc_device_init();
|
||||
|
||||
db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
|
||||
|
||||
u8500_dma40_device.dev.parent = parent;
|
||||
|
||||
/*
|
||||
* Devices to be DT:ed:
|
||||
* u8500_dma40_device = todo
|
||||
* db8500_pmu_device = done
|
||||
* db8500_prcmu_device = done
|
||||
*/
|
||||
platform_device_register(&u8500_dma40_device);
|
||||
db8500_add_usb(parent, usb_db8500_dma_cfg, usb_db8500_dma_cfg);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
@ -251,9 +230,9 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
|
|||
/* Requires call-back bindings. */
|
||||
OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
|
||||
/* Requires DMA bindings. */
|
||||
OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
|
||||
OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
|
||||
OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
|
||||
OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat),
|
||||
OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0", &mop500_sdi0_data),
|
||||
OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1", &mop500_sdi1_data),
|
||||
|
@ -289,6 +268,9 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
|
|||
"ux500-msp-i2s.2", &msp2_platform_data),
|
||||
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
|
||||
"ux500-msp-i2s.3", &msp3_platform_data),
|
||||
/* Requires clock name bindings and channel address lookup table. */
|
||||
OF_DEV_AUXDATA("stericsson,db8500-dma40", 0x801C0000,
|
||||
"dma40.0", &dma40_plat_data),
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -42,128 +42,7 @@ static struct resource dma40_resources[] = {
|
|||
}
|
||||
};
|
||||
|
||||
/* Default configuration for physcial memcpy */
|
||||
struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
|
||||
.mode = STEDMA40_MODE_PHYSICAL,
|
||||
.dir = STEDMA40_MEM_TO_MEM,
|
||||
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.src_info.psize = STEDMA40_PSIZE_PHY_1,
|
||||
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.psize = STEDMA40_PSIZE_PHY_1,
|
||||
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
};
|
||||
/* Default configuration for logical memcpy */
|
||||
struct stedma40_chan_cfg dma40_memcpy_conf_log = {
|
||||
.dir = STEDMA40_MEM_TO_MEM,
|
||||
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_1,
|
||||
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_1,
|
||||
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Mapping between destination event lines and physical device address.
|
||||
* The event line is tied to a device and therefore the address is constant.
|
||||
* When the address comes from a primecell it will be configured in runtime
|
||||
* and we set the address to -1 as a placeholder.
|
||||
*/
|
||||
static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = {
|
||||
/* MUSB - these will be runtime-reconfigured */
|
||||
[DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1,
|
||||
[DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1,
|
||||
[DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1,
|
||||
[DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1,
|
||||
[DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1,
|
||||
[DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1,
|
||||
[DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1,
|
||||
[DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1,
|
||||
/* PrimeCells - run-time configured */
|
||||
[DB8500_DMA_DEV0_SPI0_TX] = -1,
|
||||
[DB8500_DMA_DEV1_SD_MMC0_TX] = -1,
|
||||
[DB8500_DMA_DEV2_SD_MMC1_TX] = -1,
|
||||
[DB8500_DMA_DEV3_SD_MMC2_TX] = -1,
|
||||
[DB8500_DMA_DEV8_SSP0_TX] = -1,
|
||||
[DB8500_DMA_DEV9_SSP1_TX] = -1,
|
||||
[DB8500_DMA_DEV11_UART2_TX] = -1,
|
||||
[DB8500_DMA_DEV12_UART1_TX] = -1,
|
||||
[DB8500_DMA_DEV13_UART0_TX] = -1,
|
||||
[DB8500_DMA_DEV28_SD_MM2_TX] = -1,
|
||||
[DB8500_DMA_DEV29_SD_MM0_TX] = -1,
|
||||
[DB8500_DMA_DEV32_SD_MM1_TX] = -1,
|
||||
[DB8500_DMA_DEV33_SPI2_TX] = -1,
|
||||
[DB8500_DMA_DEV35_SPI1_TX] = -1,
|
||||
[DB8500_DMA_DEV40_SPI3_TX] = -1,
|
||||
[DB8500_DMA_DEV41_SD_MM3_TX] = -1,
|
||||
[DB8500_DMA_DEV42_SD_MM4_TX] = -1,
|
||||
[DB8500_DMA_DEV43_SD_MM5_TX] = -1,
|
||||
[DB8500_DMA_DEV14_MSP2_TX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV30_MSP1_TX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV48_CAC1_TX] = U8500_CRYP1_BASE + CRYP1_TX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV50_HAC1_TX] = U8500_HASH1_BASE + HASH1_TX_REG_OFFSET,
|
||||
};
|
||||
|
||||
/* Mapping between source event lines and physical device address */
|
||||
static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = {
|
||||
/* MUSB - these will be runtime-reconfigured */
|
||||
[DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1,
|
||||
[DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1,
|
||||
[DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1,
|
||||
[DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1,
|
||||
[DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1,
|
||||
[DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1,
|
||||
[DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1,
|
||||
[DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1,
|
||||
/* PrimeCells */
|
||||
[DB8500_DMA_DEV0_SPI0_RX] = -1,
|
||||
[DB8500_DMA_DEV1_SD_MMC0_RX] = -1,
|
||||
[DB8500_DMA_DEV2_SD_MMC1_RX] = -1,
|
||||
[DB8500_DMA_DEV3_SD_MMC2_RX] = -1,
|
||||
[DB8500_DMA_DEV8_SSP0_RX] = -1,
|
||||
[DB8500_DMA_DEV9_SSP1_RX] = -1,
|
||||
[DB8500_DMA_DEV11_UART2_RX] = -1,
|
||||
[DB8500_DMA_DEV12_UART1_RX] = -1,
|
||||
[DB8500_DMA_DEV13_UART0_RX] = -1,
|
||||
[DB8500_DMA_DEV28_SD_MM2_RX] = -1,
|
||||
[DB8500_DMA_DEV29_SD_MM0_RX] = -1,
|
||||
[DB8500_DMA_DEV32_SD_MM1_RX] = -1,
|
||||
[DB8500_DMA_DEV33_SPI2_RX] = -1,
|
||||
[DB8500_DMA_DEV35_SPI1_RX] = -1,
|
||||
[DB8500_DMA_DEV40_SPI3_RX] = -1,
|
||||
[DB8500_DMA_DEV41_SD_MM3_RX] = -1,
|
||||
[DB8500_DMA_DEV42_SD_MM4_RX] = -1,
|
||||
[DB8500_DMA_DEV43_SD_MM5_RX] = -1,
|
||||
[DB8500_DMA_DEV14_MSP2_RX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV30_MSP3_RX] = U8500_MSP3_BASE + MSP_TX_RX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
|
||||
[DB8500_DMA_DEV48_CAC1_RX] = U8500_CRYP1_BASE + CRYP1_RX_REG_OFFSET,
|
||||
};
|
||||
|
||||
/* Reserved event lines for memcpy only */
|
||||
static int dma40_memcpy_event[] = {
|
||||
DB8500_DMA_MEMCPY_TX_0,
|
||||
DB8500_DMA_MEMCPY_TX_1,
|
||||
DB8500_DMA_MEMCPY_TX_2,
|
||||
DB8500_DMA_MEMCPY_TX_3,
|
||||
DB8500_DMA_MEMCPY_TX_4,
|
||||
DB8500_DMA_MEMCPY_TX_5,
|
||||
};
|
||||
|
||||
static struct stedma40_platform_data dma40_plat_data = {
|
||||
.dev_len = DB8500_DMA_NR_DEV,
|
||||
.dev_rx = dma40_rx_map,
|
||||
.dev_tx = dma40_tx_map,
|
||||
.memcpy = dma40_memcpy_event,
|
||||
.memcpy_len = ARRAY_SIZE(dma40_memcpy_event),
|
||||
.memcpy_conf_phy = &dma40_memcpy_conf_phy,
|
||||
.memcpy_conf_log = &dma40_memcpy_conf_log,
|
||||
struct stedma40_platform_data dma40_plat_data = {
|
||||
.disabled_channels = {-1},
|
||||
};
|
||||
|
||||
|
|
|
@ -12,133 +12,74 @@
|
|||
|
||||
#define DB8500_DMA_NR_DEV 64
|
||||
|
||||
enum dma_src_dev_type {
|
||||
DB8500_DMA_DEV0_SPI0_RX = 0,
|
||||
DB8500_DMA_DEV1_SD_MMC0_RX = 1,
|
||||
DB8500_DMA_DEV2_SD_MMC1_RX = 2,
|
||||
DB8500_DMA_DEV3_SD_MMC2_RX = 3,
|
||||
DB8500_DMA_DEV4_I2C1_RX = 4,
|
||||
DB8500_DMA_DEV5_I2C3_RX = 5,
|
||||
DB8500_DMA_DEV6_I2C2_RX = 6,
|
||||
DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */
|
||||
DB8500_DMA_DEV8_SSP0_RX = 8,
|
||||
DB8500_DMA_DEV9_SSP1_RX = 9,
|
||||
DB8500_DMA_DEV10_MCDE_RX = 10,
|
||||
DB8500_DMA_DEV11_UART2_RX = 11,
|
||||
DB8500_DMA_DEV12_UART1_RX = 12,
|
||||
DB8500_DMA_DEV13_UART0_RX = 13,
|
||||
DB8500_DMA_DEV14_MSP2_RX = 14,
|
||||
DB8500_DMA_DEV15_I2C0_RX = 15,
|
||||
DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16,
|
||||
DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17,
|
||||
DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18,
|
||||
DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19,
|
||||
DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
|
||||
DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
|
||||
DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
|
||||
DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
|
||||
DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24,
|
||||
DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25,
|
||||
DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26,
|
||||
DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27,
|
||||
DB8500_DMA_DEV28_SD_MM2_RX = 28,
|
||||
DB8500_DMA_DEV29_SD_MM0_RX = 29,
|
||||
DB8500_DMA_DEV30_MSP1_RX = 30,
|
||||
/*
|
||||
* Unless otherwise specified, all channels numbers are used for
|
||||
* TX & RX, and can be used for either source or destination
|
||||
* channels.
|
||||
*/
|
||||
enum dma_dev_type {
|
||||
DB8500_DMA_DEV0_SPI0 = 0,
|
||||
DB8500_DMA_DEV1_SD_MMC0 = 1,
|
||||
DB8500_DMA_DEV2_SD_MMC1 = 2,
|
||||
DB8500_DMA_DEV3_SD_MMC2 = 3,
|
||||
DB8500_DMA_DEV4_I2C1 = 4,
|
||||
DB8500_DMA_DEV5_I2C3 = 5,
|
||||
DB8500_DMA_DEV6_I2C2 = 6,
|
||||
DB8500_DMA_DEV7_I2C4 = 7, /* Only on V1 and later */
|
||||
DB8500_DMA_DEV8_SSP0 = 8,
|
||||
DB8500_DMA_DEV9_SSP1 = 9,
|
||||
DB8500_DMA_DEV10_MCDE_RX = 10, /* RX only */
|
||||
DB8500_DMA_DEV11_UART2 = 11,
|
||||
DB8500_DMA_DEV12_UART1 = 12,
|
||||
DB8500_DMA_DEV13_UART0 = 13,
|
||||
DB8500_DMA_DEV14_MSP2 = 14,
|
||||
DB8500_DMA_DEV15_I2C0 = 15,
|
||||
DB8500_DMA_DEV16_USB_OTG_IEP_AND_OEP_7_15 = 16,
|
||||
DB8500_DMA_DEV17_USB_OTG_IEP_AND_OEP_6_14 = 17,
|
||||
DB8500_DMA_DEV18_USB_OTG_IEP_AND_OEP_5_13 = 18,
|
||||
DB8500_DMA_DEV19_USB_OTG_IEP_AND_OEP_4_12 = 19,
|
||||
DB8500_DMA_DEV20_SLIM0_CH0_HSI_CH0 = 20,
|
||||
DB8500_DMA_DEV21_SLIM0_CH1_HSI_CH1 = 21,
|
||||
DB8500_DMA_DEV22_SLIM0_CH2_HSI_CH2 = 22,
|
||||
DB8500_DMA_DEV23_SLIM0_CH3_HSI_CH3 = 23,
|
||||
DB8500_DMA_DEV24_SXA0 = 24,
|
||||
DB8500_DMA_DEV25_SXA1 = 25,
|
||||
DB8500_DMA_DEV26_SXA2 = 26,
|
||||
DB8500_DMA_DEV27_SXA3 = 27,
|
||||
DB8500_DMA_DEV28_SD_MM2 = 28,
|
||||
DB8500_DMA_DEV29_SD_MM0 = 29,
|
||||
DB8500_DMA_DEV30_MSP1 = 30,
|
||||
/* On DB8500v2, MSP3 RX replaces MSP1 RX */
|
||||
DB8500_DMA_DEV30_MSP3_RX = 30,
|
||||
DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31,
|
||||
DB8500_DMA_DEV32_SD_MM1_RX = 32,
|
||||
DB8500_DMA_DEV33_SPI2_RX = 33,
|
||||
DB8500_DMA_DEV34_I2C3_RX2 = 34,
|
||||
DB8500_DMA_DEV35_SPI1_RX = 35,
|
||||
DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36,
|
||||
DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37,
|
||||
DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38,
|
||||
DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39,
|
||||
DB8500_DMA_DEV40_SPI3_RX = 40,
|
||||
DB8500_DMA_DEV41_SD_MM3_RX = 41,
|
||||
DB8500_DMA_DEV42_SD_MM4_RX = 42,
|
||||
DB8500_DMA_DEV43_SD_MM5_RX = 43,
|
||||
DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44,
|
||||
DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45,
|
||||
DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46,
|
||||
DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47,
|
||||
DB8500_DMA_DEV48_CAC1_RX = 48,
|
||||
/* 49, 50 and 51 are not used */
|
||||
DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52,
|
||||
DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53,
|
||||
DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54,
|
||||
DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55,
|
||||
/* 56, 57, 58, 59 and 60 are not used */
|
||||
DB8500_DMA_DEV61_CAC0_RX = 61,
|
||||
/* 62 and 63 are not used */
|
||||
};
|
||||
|
||||
enum dma_dest_dev_type {
|
||||
DB8500_DMA_DEV0_SPI0_TX = 0,
|
||||
DB8500_DMA_DEV1_SD_MMC0_TX = 1,
|
||||
DB8500_DMA_DEV2_SD_MMC1_TX = 2,
|
||||
DB8500_DMA_DEV3_SD_MMC2_TX = 3,
|
||||
DB8500_DMA_DEV4_I2C1_TX = 4,
|
||||
DB8500_DMA_DEV5_I2C3_TX = 5,
|
||||
DB8500_DMA_DEV6_I2C2_TX = 6,
|
||||
DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */
|
||||
DB8500_DMA_DEV8_SSP0_TX = 8,
|
||||
DB8500_DMA_DEV9_SSP1_TX = 9,
|
||||
/* 10 is not used*/
|
||||
DB8500_DMA_DEV11_UART2_TX = 11,
|
||||
DB8500_DMA_DEV12_UART1_TX = 12,
|
||||
DB8500_DMA_DEV13_UART0_TX = 13,
|
||||
DB8500_DMA_DEV14_MSP2_TX = 14,
|
||||
DB8500_DMA_DEV15_I2C0_TX = 15,
|
||||
DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16,
|
||||
DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17,
|
||||
DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18,
|
||||
DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19,
|
||||
DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
|
||||
DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
|
||||
DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
|
||||
DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
|
||||
DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24,
|
||||
DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25,
|
||||
DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26,
|
||||
DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27,
|
||||
DB8500_DMA_DEV28_SD_MM2_TX = 28,
|
||||
DB8500_DMA_DEV29_SD_MM0_TX = 29,
|
||||
DB8500_DMA_DEV30_MSP1_TX = 30,
|
||||
DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31,
|
||||
DB8500_DMA_DEV32_SD_MM1_TX = 32,
|
||||
DB8500_DMA_DEV33_SPI2_TX = 33,
|
||||
DB8500_DMA_DEV34_I2C3_TX2 = 34,
|
||||
DB8500_DMA_DEV35_SPI1_TX = 35,
|
||||
DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36,
|
||||
DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37,
|
||||
DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38,
|
||||
DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39,
|
||||
DB8500_DMA_DEV40_SPI3_TX = 40,
|
||||
DB8500_DMA_DEV41_SD_MM3_TX = 41,
|
||||
DB8500_DMA_DEV42_SD_MM4_TX = 42,
|
||||
DB8500_DMA_DEV43_SD_MM5_TX = 43,
|
||||
DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44,
|
||||
DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45,
|
||||
DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46,
|
||||
DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47,
|
||||
DB8500_DMA_DEV48_CAC1_TX = 48,
|
||||
DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49,
|
||||
DB8500_DMA_DEV50_HAC1_TX = 50,
|
||||
DB8500_DMA_MEMCPY_TX_0 = 51,
|
||||
DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52,
|
||||
DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53,
|
||||
DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54,
|
||||
DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55,
|
||||
DB8500_DMA_MEMCPY_TX_1 = 56,
|
||||
DB8500_DMA_MEMCPY_TX_2 = 57,
|
||||
DB8500_DMA_MEMCPY_TX_3 = 58,
|
||||
DB8500_DMA_MEMCPY_TX_4 = 59,
|
||||
DB8500_DMA_MEMCPY_TX_5 = 60,
|
||||
DB8500_DMA_DEV61_CAC0_TX = 61,
|
||||
DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62,
|
||||
DB8500_DMA_DEV63_HAC0_TX = 63,
|
||||
DB8500_DMA_DEV30_MSP3 = 30,
|
||||
DB8500_DMA_DEV31_MSP0_SLIM0_CH0 = 31,
|
||||
DB8500_DMA_DEV32_SD_MM1 = 32,
|
||||
DB8500_DMA_DEV33_SPI2 = 33,
|
||||
DB8500_DMA_DEV34_I2C3_RX2_TX2 = 34,
|
||||
DB8500_DMA_DEV35_SPI1 = 35,
|
||||
DB8500_DMA_DEV36_USB_OTG_IEP_AND_OEP_3_11 = 36,
|
||||
DB8500_DMA_DEV37_USB_OTG_IEP_AND_OEP_2_10 = 37,
|
||||
DB8500_DMA_DEV38_USB_OTG_IEP_AND_OEP_1_9 = 38,
|
||||
DB8500_DMA_DEV39_USB_OTG_IEP_AND_OEP_8 = 39,
|
||||
DB8500_DMA_DEV40_SPI3 = 40,
|
||||
DB8500_DMA_DEV41_SD_MM3 = 41,
|
||||
DB8500_DMA_DEV42_SD_MM4 = 42,
|
||||
DB8500_DMA_DEV43_SD_MM5 = 43,
|
||||
DB8500_DMA_DEV44_SXA4 = 44,
|
||||
DB8500_DMA_DEV45_SXA5 = 45,
|
||||
DB8500_DMA_DEV46_SLIM0_CH8_SRC_SXA6 = 46,
|
||||
DB8500_DMA_DEV47_SLIM0_CH9_SRC_SXA7 = 47,
|
||||
DB8500_DMA_DEV48_CAC1 = 48,
|
||||
DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49, /* TX only */
|
||||
DB8500_DMA_DEV50_HAC1_TX = 50, /* TX only */
|
||||
DB8500_DMA_MEMCPY_TX_0 = 51, /* TX only */
|
||||
DB8500_DMA_DEV52_SLIM0_CH4_HSI_CH4 = 52,
|
||||
DB8500_DMA_DEV53_SLIM0_CH5_HSI_CH5 = 53,
|
||||
DB8500_DMA_DEV54_SLIM0_CH6_HSI_CH6 = 54,
|
||||
DB8500_DMA_DEV55_SLIM0_CH7_HSI_CH7 = 55,
|
||||
/* 56 -> 60 are channels reserved for memcpy only */
|
||||
DB8500_DMA_DEV61_CAC0 = 61,
|
||||
DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62, /* TX only */
|
||||
DB8500_DMA_DEV63_HAC0_TX = 63, /* TX only */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,21 +15,11 @@
|
|||
#define MUSB_DMA40_RX_CH { \
|
||||
.mode = STEDMA40_MODE_LOGICAL, \
|
||||
.dir = STEDMA40_PERIPH_TO_MEM, \
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY, \
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
}
|
||||
|
||||
#define MUSB_DMA40_TX_CH { \
|
||||
.mode = STEDMA40_MODE_LOGICAL, \
|
||||
.dir = STEDMA40_MEM_TO_PERIPH, \
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY, \
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
}
|
||||
|
||||
static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS]
|
||||
|
@ -125,20 +115,20 @@ struct platform_device ux500_musb_device = {
|
|||
.resource = usb_resources,
|
||||
};
|
||||
|
||||
static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type)
|
||||
static inline void ux500_usb_dma_update_rx_ch_config(int *dev_type)
|
||||
{
|
||||
u32 idx;
|
||||
|
||||
for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++)
|
||||
musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx];
|
||||
musb_dma_rx_ch[idx].dev_type = dev_type[idx];
|
||||
}
|
||||
|
||||
static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type)
|
||||
static inline void ux500_usb_dma_update_tx_ch_config(int *dev_type)
|
||||
{
|
||||
u32 idx;
|
||||
|
||||
for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++)
|
||||
musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx];
|
||||
musb_dma_tx_ch[idx].dev_type = dev_type[idx];
|
||||
}
|
||||
|
||||
void ux500_add_usb(struct device *parent, resource_size_t base, int irq,
|
||||
|
|
|
@ -114,6 +114,9 @@ enum cryp_status_id {
|
|||
};
|
||||
|
||||
/* Cryp DMA interface */
|
||||
#define CRYP_DMA_TX_FIFO 0x08
|
||||
#define CRYP_DMA_RX_FIFO 0x10
|
||||
|
||||
enum cryp_dma_req_type {
|
||||
CRYP_DMA_DISABLE_BOTH,
|
||||
CRYP_DMA_ENABLE_IN_DATA,
|
||||
|
@ -217,7 +220,8 @@ struct cryp_dma {
|
|||
|
||||
/**
|
||||
* struct cryp_device_data - structure for a cryp device.
|
||||
* @base: Pointer to the hardware base address.
|
||||
* @base: Pointer to virtual base address of the cryp device.
|
||||
* @phybase: Pointer to physical memory location of the cryp device.
|
||||
* @dev: Pointer to the devices dev structure.
|
||||
* @clk: Pointer to the device's clock control.
|
||||
* @pwr_regulator: Pointer to the device's power control.
|
||||
|
@ -232,6 +236,7 @@ struct cryp_dma {
|
|||
*/
|
||||
struct cryp_device_data {
|
||||
struct cryp_register __iomem *base;
|
||||
phys_addr_t phybase;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct regulator *pwr_regulator;
|
||||
|
|
|
@ -475,6 +475,19 @@ static int cryp_get_device_data(struct cryp_ctx *ctx,
|
|||
static void cryp_dma_setup_channel(struct cryp_device_data *device_data,
|
||||
struct device *dev)
|
||||
{
|
||||
struct dma_slave_config mem2cryp = {
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.dst_addr = device_data->phybase + CRYP_DMA_TX_FIFO,
|
||||
.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
|
||||
.dst_maxburst = 4,
|
||||
};
|
||||
struct dma_slave_config cryp2mem = {
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.src_addr = device_data->phybase + CRYP_DMA_RX_FIFO,
|
||||
.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
|
||||
.src_maxburst = 4,
|
||||
};
|
||||
|
||||
dma_cap_zero(device_data->dma.mask);
|
||||
dma_cap_set(DMA_SLAVE, device_data->dma.mask);
|
||||
|
||||
|
@ -490,6 +503,9 @@ static void cryp_dma_setup_channel(struct cryp_device_data *device_data,
|
|||
stedma40_filter,
|
||||
device_data->dma.cfg_cryp2mem);
|
||||
|
||||
dmaengine_slave_config(device_data->dma.chan_mem2cryp, &mem2cryp);
|
||||
dmaengine_slave_config(device_data->dma.chan_cryp2mem, &cryp2mem);
|
||||
|
||||
init_completion(&device_data->dma.cryp_dma_complete);
|
||||
}
|
||||
|
||||
|
@ -1431,6 +1447,7 @@ static int ux500_cryp_probe(struct platform_device *pdev)
|
|||
goto out_kfree;
|
||||
}
|
||||
|
||||
device_data->phybase = res->start;
|
||||
device_data->base = ioremap(res->start, resource_size(res));
|
||||
if (!device_data->base) {
|
||||
dev_err(dev, "[%s]: ioremap failed!", __func__);
|
||||
|
@ -1458,11 +1475,17 @@ static int ux500_cryp_probe(struct platform_device *pdev)
|
|||
goto out_regulator;
|
||||
}
|
||||
|
||||
ret = clk_prepare(device_data->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "[%s]: clk_prepare() failed!", __func__);
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
/* Enable device power (and clock) */
|
||||
ret = cryp_enable_power(device_data->dev, device_data, false);
|
||||
if (ret) {
|
||||
dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__);
|
||||
goto out_clk;
|
||||
goto out_clk_unprepare;
|
||||
}
|
||||
|
||||
cryp_error = cryp_check(device_data);
|
||||
|
@ -1518,11 +1541,16 @@ static int ux500_cryp_probe(struct platform_device *pdev)
|
|||
goto out_power;
|
||||
}
|
||||
|
||||
dev_info(dev, "successfully registered\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_power:
|
||||
cryp_disable_power(device_data->dev, device_data, false);
|
||||
|
||||
out_clk_unprepare:
|
||||
clk_unprepare(device_data->clk);
|
||||
|
||||
out_clk:
|
||||
clk_put(device_data->clk);
|
||||
|
||||
|
@ -1593,6 +1621,7 @@ static int ux500_cryp_remove(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed",
|
||||
__func__);
|
||||
|
||||
clk_unprepare(device_data->clk);
|
||||
clk_put(device_data->clk);
|
||||
regulator_put(device_data->pwr_regulator);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/bitops.h>
|
||||
|
||||
#define HASH_BLOCK_SIZE 64
|
||||
#define HASH_DMA_FIFO 4
|
||||
#define HASH_DMA_ALIGN_SIZE 4
|
||||
#define HASH_DMA_PERFORMANCE_MIN_SIZE 1024
|
||||
#define HASH_BYTES_PER_WORD 4
|
||||
|
@ -347,7 +348,8 @@ struct hash_req_ctx {
|
|||
|
||||
/**
|
||||
* struct hash_device_data - structure for a hash device.
|
||||
* @base: Pointer to the hardware base address.
|
||||
* @base: Pointer to virtual base address of the hash device.
|
||||
* @phybase: Pointer to physical memory location of the hash device.
|
||||
* @list_node: For inclusion in klist.
|
||||
* @dev: Pointer to the device dev structure.
|
||||
* @ctx_lock: Spinlock for current_ctx.
|
||||
|
@ -361,6 +363,7 @@ struct hash_req_ctx {
|
|||
*/
|
||||
struct hash_device_data {
|
||||
struct hash_register __iomem *base;
|
||||
phys_addr_t phybase;
|
||||
struct klist_node list_node;
|
||||
struct device *dev;
|
||||
struct spinlock ctx_lock;
|
||||
|
|
|
@ -122,6 +122,13 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data,
|
|||
struct device *dev)
|
||||
{
|
||||
struct hash_platform_data *platform_data = dev->platform_data;
|
||||
struct dma_slave_config conf = {
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
.dst_addr = device_data->phybase + HASH_DMA_FIFO,
|
||||
.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
|
||||
.dst_maxburst = 16,
|
||||
};
|
||||
|
||||
dma_cap_zero(device_data->dma.mask);
|
||||
dma_cap_set(DMA_SLAVE, device_data->dma.mask);
|
||||
|
||||
|
@ -131,6 +138,8 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data,
|
|||
platform_data->dma_filter,
|
||||
device_data->dma.cfg_mem2hash);
|
||||
|
||||
dmaengine_slave_config(device_data->dma.chan_mem2hash, &conf);
|
||||
|
||||
init_completion(&device_data->dma.complete);
|
||||
}
|
||||
|
||||
|
@ -1699,6 +1708,7 @@ static int ux500_hash_probe(struct platform_device *pdev)
|
|||
goto out_kfree;
|
||||
}
|
||||
|
||||
device_data->phybase = res->start;
|
||||
device_data->base = ioremap(res->start, resource_size(res));
|
||||
if (!device_data->base) {
|
||||
dev_err(dev, "[%s] ioremap() failed!",
|
||||
|
@ -1726,11 +1736,17 @@ static int ux500_hash_probe(struct platform_device *pdev)
|
|||
goto out_regulator;
|
||||
}
|
||||
|
||||
ret = clk_prepare(device_data->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "[%s] clk_prepare() failed!", __func__);
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
/* Enable device power (and clock) */
|
||||
ret = hash_enable_power(device_data, false);
|
||||
if (ret) {
|
||||
dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
|
||||
goto out_clk;
|
||||
goto out_clk_unprepare;
|
||||
}
|
||||
|
||||
ret = hash_check_hw(device_data);
|
||||
|
@ -1756,12 +1772,15 @@ static int ux500_hash_probe(struct platform_device *pdev)
|
|||
goto out_power;
|
||||
}
|
||||
|
||||
dev_info(dev, "[%s] successfully probed\n", __func__);
|
||||
dev_info(dev, "successfully registered\n");
|
||||
return 0;
|
||||
|
||||
out_power:
|
||||
hash_disable_power(device_data, false);
|
||||
|
||||
out_clk_unprepare:
|
||||
clk_unprepare(device_data->clk);
|
||||
|
||||
out_clk:
|
||||
clk_put(device_data->clk);
|
||||
|
||||
|
@ -1826,6 +1845,7 @@ static int ux500_hash_remove(struct platform_device *pdev)
|
|||
dev_err(dev, "[%s]: hash_disable_power() failed",
|
||||
__func__);
|
||||
|
||||
clk_unprepare(device_data->clk);
|
||||
clk_put(device_data->clk);
|
||||
regulator_put(device_data->regulator);
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/platform_data/dma-ste-dma40.h>
|
||||
|
@ -45,6 +47,9 @@
|
|||
#define D40_LCLA_LINK_PER_EVENT_GRP 128
|
||||
#define D40_LCLA_END D40_LCLA_LINK_PER_EVENT_GRP
|
||||
|
||||
/* Max number of logical channels per physical channel */
|
||||
#define D40_MAX_LOG_CHAN_PER_PHY 32
|
||||
|
||||
/* Attempts before giving up to trying to get pages that are aligned */
|
||||
#define MAX_LCLA_ALLOC_ATTEMPTS 256
|
||||
|
||||
|
@ -53,7 +58,50 @@
|
|||
#define D40_ALLOC_PHY (1 << 30)
|
||||
#define D40_ALLOC_LOG_FREE 0
|
||||
|
||||
#define MAX(a, b) (((a) < (b)) ? (b) : (a))
|
||||
/* Reserved event lines for memcpy only. */
|
||||
#define DB8500_DMA_MEMCPY_EV_0 51
|
||||
#define DB8500_DMA_MEMCPY_EV_1 56
|
||||
#define DB8500_DMA_MEMCPY_EV_2 57
|
||||
#define DB8500_DMA_MEMCPY_EV_3 58
|
||||
#define DB8500_DMA_MEMCPY_EV_4 59
|
||||
#define DB8500_DMA_MEMCPY_EV_5 60
|
||||
|
||||
static int dma40_memcpy_channels[] = {
|
||||
DB8500_DMA_MEMCPY_EV_0,
|
||||
DB8500_DMA_MEMCPY_EV_1,
|
||||
DB8500_DMA_MEMCPY_EV_2,
|
||||
DB8500_DMA_MEMCPY_EV_3,
|
||||
DB8500_DMA_MEMCPY_EV_4,
|
||||
DB8500_DMA_MEMCPY_EV_5,
|
||||
};
|
||||
|
||||
/* Default configuration for physcial memcpy */
|
||||
struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
|
||||
.mode = STEDMA40_MODE_PHYSICAL,
|
||||
.dir = STEDMA40_MEM_TO_MEM,
|
||||
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.src_info.psize = STEDMA40_PSIZE_PHY_1,
|
||||
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.psize = STEDMA40_PSIZE_PHY_1,
|
||||
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
};
|
||||
|
||||
/* Default configuration for logical memcpy */
|
||||
struct stedma40_chan_cfg dma40_memcpy_conf_log = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_MEM,
|
||||
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_1,
|
||||
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_1,
|
||||
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum 40_command - The different commands and/or statuses.
|
||||
|
@ -171,6 +219,9 @@ static u32 d40_backup_regs_chan[] = {
|
|||
D40_CHAN_REG_SDLNK,
|
||||
};
|
||||
|
||||
#define BACKUP_REGS_SZ_MAX ((BACKUP_REGS_SZ_V4A > BACKUP_REGS_SZ_V4B) ? \
|
||||
BACKUP_REGS_SZ_V4A : BACKUP_REGS_SZ_V4B)
|
||||
|
||||
/**
|
||||
* struct d40_interrupt_lookup - lookup table for interrupt handler
|
||||
*
|
||||
|
@ -534,7 +585,7 @@ struct d40_base {
|
|||
resource_size_t lcpa_size;
|
||||
struct kmem_cache *desc_slab;
|
||||
u32 reg_val_backup[BACKUP_REGS_SZ];
|
||||
u32 reg_val_backup_v4[MAX(BACKUP_REGS_SZ_V4A, BACKUP_REGS_SZ_V4B)];
|
||||
u32 reg_val_backup_v4[BACKUP_REGS_SZ_MAX];
|
||||
u32 *reg_val_backup_chan;
|
||||
u16 gcc_pwr_off_mask;
|
||||
bool initialized;
|
||||
|
@ -1257,21 +1308,17 @@ static void __d40_config_set_event(struct d40_chan *d40c,
|
|||
static void d40_config_set_event(struct d40_chan *d40c,
|
||||
enum d40_events event_type)
|
||||
{
|
||||
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type);
|
||||
|
||||
/* Enable event line connected to device (or memcpy) */
|
||||
if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) ||
|
||||
(d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) {
|
||||
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
|
||||
|
||||
(d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
|
||||
__d40_config_set_event(d40c, event_type, event,
|
||||
D40_CHAN_REG_SSLNK);
|
||||
}
|
||||
|
||||
if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) {
|
||||
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
|
||||
|
||||
if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM)
|
||||
__d40_config_set_event(d40c, event_type, event,
|
||||
D40_CHAN_REG_SDLNK);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 d40_chan_has_events(struct d40_chan *d40c)
|
||||
|
@ -1713,8 +1760,6 @@ static int d40_validate_conf(struct d40_chan *d40c,
|
|||
struct stedma40_chan_cfg *conf)
|
||||
{
|
||||
int res = 0;
|
||||
u32 dst_event_group = D40_TYPE_TO_GROUP(conf->dst_dev_type);
|
||||
u32 src_event_group = D40_TYPE_TO_GROUP(conf->src_dev_type);
|
||||
bool is_log = conf->mode == STEDMA40_MODE_LOGICAL;
|
||||
|
||||
if (!conf->dir) {
|
||||
|
@ -1722,44 +1767,10 @@ static int d40_validate_conf(struct d40_chan *d40c,
|
|||
res = -EINVAL;
|
||||
}
|
||||
|
||||
if (conf->dst_dev_type != STEDMA40_DEV_DST_MEMORY &&
|
||||
d40c->base->plat_data->dev_tx[conf->dst_dev_type] == 0 &&
|
||||
d40c->runtime_addr == 0) {
|
||||
|
||||
chan_err(d40c, "Invalid TX channel address (%d)\n",
|
||||
conf->dst_dev_type);
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
if (conf->src_dev_type != STEDMA40_DEV_SRC_MEMORY &&
|
||||
d40c->base->plat_data->dev_rx[conf->src_dev_type] == 0 &&
|
||||
d40c->runtime_addr == 0) {
|
||||
chan_err(d40c, "Invalid RX channel address (%d)\n",
|
||||
conf->src_dev_type);
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
if (conf->dir == STEDMA40_MEM_TO_PERIPH &&
|
||||
dst_event_group == STEDMA40_DEV_DST_MEMORY) {
|
||||
chan_err(d40c, "Invalid dst\n");
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
if (conf->dir == STEDMA40_PERIPH_TO_MEM &&
|
||||
src_event_group == STEDMA40_DEV_SRC_MEMORY) {
|
||||
chan_err(d40c, "Invalid src\n");
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
if (src_event_group == STEDMA40_DEV_SRC_MEMORY &&
|
||||
dst_event_group == STEDMA40_DEV_DST_MEMORY && is_log) {
|
||||
chan_err(d40c, "No event line\n");
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
if (conf->dir == STEDMA40_PERIPH_TO_PERIPH &&
|
||||
(src_event_group != dst_event_group)) {
|
||||
chan_err(d40c, "Invalid event group\n");
|
||||
if ((is_log && conf->dev_type > d40c->base->num_log_chans) ||
|
||||
(!is_log && conf->dev_type > d40c->base->num_phy_chans) ||
|
||||
(conf->dev_type < 0)) {
|
||||
chan_err(d40c, "Invalid device type (%d)\n", conf->dev_type);
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1880,7 +1891,7 @@ static bool d40_alloc_mask_free(struct d40_phy_res *phy, bool is_src,
|
|||
|
||||
static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
|
||||
{
|
||||
int dev_type;
|
||||
int dev_type = d40c->dma_cfg.dev_type;
|
||||
int event_group;
|
||||
int event_line;
|
||||
struct d40_phy_res *phys;
|
||||
|
@ -1895,13 +1906,11 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
|
|||
num_phy_chans = d40c->base->num_phy_chans;
|
||||
|
||||
if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
|
||||
dev_type = d40c->dma_cfg.src_dev_type;
|
||||
log_num = 2 * dev_type;
|
||||
is_src = true;
|
||||
} else if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH ||
|
||||
d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
|
||||
/* dst event lines are used for logical memcpy */
|
||||
dev_type = d40c->dma_cfg.dst_dev_type;
|
||||
log_num = 2 * dev_type + 1;
|
||||
is_src = false;
|
||||
} else
|
||||
|
@ -2012,14 +2021,23 @@ static int d40_config_memcpy(struct d40_chan *d40c)
|
|||
dma_cap_mask_t cap = d40c->chan.device->cap_mask;
|
||||
|
||||
if (dma_has_cap(DMA_MEMCPY, cap) && !dma_has_cap(DMA_SLAVE, cap)) {
|
||||
d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_log;
|
||||
d40c->dma_cfg.src_dev_type = STEDMA40_DEV_SRC_MEMORY;
|
||||
d40c->dma_cfg.dst_dev_type = d40c->base->plat_data->
|
||||
memcpy[d40c->chan.chan_id];
|
||||
d40c->dma_cfg = dma40_memcpy_conf_log;
|
||||
d40c->dma_cfg.dev_type = dma40_memcpy_channels[d40c->chan.chan_id];
|
||||
|
||||
d40_log_cfg(&d40c->dma_cfg,
|
||||
&d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
|
||||
|
||||
} else if (dma_has_cap(DMA_MEMCPY, cap) &&
|
||||
dma_has_cap(DMA_SLAVE, cap)) {
|
||||
d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_phy;
|
||||
d40c->dma_cfg = dma40_memcpy_conf_phy;
|
||||
|
||||
/* Generate interrrupt at end of transfer or relink. */
|
||||
d40c->dst_def_cfg |= BIT(D40_SREG_CFG_TIM_POS);
|
||||
|
||||
/* Generate interrupt on error. */
|
||||
d40c->src_def_cfg |= BIT(D40_SREG_CFG_EIM_POS);
|
||||
d40c->dst_def_cfg |= BIT(D40_SREG_CFG_EIM_POS);
|
||||
|
||||
} else {
|
||||
chan_err(d40c, "No memcpy\n");
|
||||
return -EINVAL;
|
||||
|
@ -2032,7 +2050,7 @@ static int d40_free_dma(struct d40_chan *d40c)
|
|||
{
|
||||
|
||||
int res = 0;
|
||||
u32 event;
|
||||
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type);
|
||||
struct d40_phy_res *phy = d40c->phy_chan;
|
||||
bool is_src;
|
||||
|
||||
|
@ -2051,13 +2069,11 @@ static int d40_free_dma(struct d40_chan *d40c)
|
|||
}
|
||||
|
||||
if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH ||
|
||||
d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
|
||||
event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
|
||||
d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM)
|
||||
is_src = false;
|
||||
} else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
|
||||
event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
|
||||
else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)
|
||||
is_src = true;
|
||||
} else {
|
||||
else {
|
||||
chan_err(d40c, "Unknown direction\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -2098,7 +2114,7 @@ static bool d40_is_paused(struct d40_chan *d40c)
|
|||
unsigned long flags;
|
||||
void __iomem *active_reg;
|
||||
u32 status;
|
||||
u32 event;
|
||||
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type);
|
||||
|
||||
spin_lock_irqsave(&d40c->lock, flags);
|
||||
|
||||
|
@ -2119,10 +2135,8 @@ static bool d40_is_paused(struct d40_chan *d40c)
|
|||
|
||||
if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH ||
|
||||
d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
|
||||
event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
|
||||
status = readl(chanbase + D40_CHAN_REG_SDLNK);
|
||||
} else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
|
||||
event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
|
||||
status = readl(chanbase + D40_CHAN_REG_SSLNK);
|
||||
} else {
|
||||
chan_err(d40c, "Unknown direction\n");
|
||||
|
@ -2253,24 +2267,6 @@ d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static dma_addr_t
|
||||
d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction)
|
||||
{
|
||||
struct stedma40_platform_data *plat = chan->base->plat_data;
|
||||
struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
|
||||
dma_addr_t addr = 0;
|
||||
|
||||
if (chan->runtime_addr)
|
||||
return chan->runtime_addr;
|
||||
|
||||
if (direction == DMA_DEV_TO_MEM)
|
||||
addr = plat->dev_rx[cfg->src_dev_type];
|
||||
else if (direction == DMA_MEM_TO_DEV)
|
||||
addr = plat->dev_tx[cfg->dst_dev_type];
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static struct dma_async_tx_descriptor *
|
||||
d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
|
||||
struct scatterlist *sg_dst, unsigned int sg_len,
|
||||
|
@ -2297,14 +2293,10 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
|
|||
if (sg_next(&sg_src[sg_len - 1]) == sg_src)
|
||||
desc->cyclic = true;
|
||||
|
||||
if (direction != DMA_TRANS_NONE) {
|
||||
dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
|
||||
|
||||
if (direction == DMA_DEV_TO_MEM)
|
||||
src_dev_addr = dev_addr;
|
||||
else if (direction == DMA_MEM_TO_DEV)
|
||||
dst_dev_addr = dev_addr;
|
||||
}
|
||||
if (direction == DMA_DEV_TO_MEM)
|
||||
src_dev_addr = chan->runtime_addr;
|
||||
else if (direction == DMA_MEM_TO_DEV)
|
||||
dst_dev_addr = chan->runtime_addr;
|
||||
|
||||
if (chan_is_logical(chan))
|
||||
ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst,
|
||||
|
@ -2397,11 +2389,55 @@ static void d40_set_prio_realtime(struct d40_chan *d40c)
|
|||
|
||||
if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) ||
|
||||
(d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
|
||||
__d40_set_prio_rt(d40c, d40c->dma_cfg.src_dev_type, true);
|
||||
__d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, true);
|
||||
|
||||
if ((d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH) ||
|
||||
(d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
|
||||
__d40_set_prio_rt(d40c, d40c->dma_cfg.dst_dev_type, false);
|
||||
__d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, false);
|
||||
}
|
||||
|
||||
#define D40_DT_FLAGS_MODE(flags) ((flags >> 0) & 0x1)
|
||||
#define D40_DT_FLAGS_DIR(flags) ((flags >> 1) & 0x1)
|
||||
#define D40_DT_FLAGS_BIG_ENDIAN(flags) ((flags >> 2) & 0x1)
|
||||
#define D40_DT_FLAGS_FIXED_CHAN(flags) ((flags >> 3) & 0x1)
|
||||
|
||||
static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct stedma40_chan_cfg cfg;
|
||||
dma_cap_mask_t cap;
|
||||
u32 flags;
|
||||
|
||||
memset(&cfg, 0, sizeof(struct stedma40_chan_cfg));
|
||||
|
||||
dma_cap_zero(cap);
|
||||
dma_cap_set(DMA_SLAVE, cap);
|
||||
|
||||
cfg.dev_type = dma_spec->args[0];
|
||||
flags = dma_spec->args[2];
|
||||
|
||||
switch (D40_DT_FLAGS_MODE(flags)) {
|
||||
case 0: cfg.mode = STEDMA40_MODE_LOGICAL; break;
|
||||
case 1: cfg.mode = STEDMA40_MODE_PHYSICAL; break;
|
||||
}
|
||||
|
||||
switch (D40_DT_FLAGS_DIR(flags)) {
|
||||
case 0:
|
||||
cfg.dir = STEDMA40_MEM_TO_PERIPH;
|
||||
cfg.dst_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags);
|
||||
break;
|
||||
case 1:
|
||||
cfg.dir = STEDMA40_PERIPH_TO_MEM;
|
||||
cfg.src_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags);
|
||||
break;
|
||||
}
|
||||
|
||||
if (D40_DT_FLAGS_FIXED_CHAN(flags)) {
|
||||
cfg.phy_channel = dma_spec->args[1];
|
||||
cfg.use_fixed_channel = true;
|
||||
}
|
||||
|
||||
return dma_request_channel(cap, stedma40_filter, &cfg);
|
||||
}
|
||||
|
||||
/* DMA ENGINE functions */
|
||||
|
@ -2433,23 +2469,21 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
|
|||
}
|
||||
|
||||
pm_runtime_get_sync(d40c->base->dev);
|
||||
/* Fill in basic CFG register values */
|
||||
d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg,
|
||||
&d40c->dst_def_cfg, chan_is_logical(d40c));
|
||||
|
||||
d40_set_prio_realtime(d40c);
|
||||
|
||||
if (chan_is_logical(d40c)) {
|
||||
d40_log_cfg(&d40c->dma_cfg,
|
||||
&d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
|
||||
|
||||
if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)
|
||||
d40c->lcpa = d40c->base->lcpa_base +
|
||||
d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE;
|
||||
d40c->dma_cfg.dev_type * D40_LCPA_CHAN_SIZE;
|
||||
else
|
||||
d40c->lcpa = d40c->base->lcpa_base +
|
||||
d40c->dma_cfg.dst_dev_type *
|
||||
d40c->dma_cfg.dev_type *
|
||||
D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
|
||||
|
||||
/* Unmask the Global Interrupt Mask. */
|
||||
d40c->src_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS);
|
||||
d40c->dst_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS);
|
||||
}
|
||||
|
||||
dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n",
|
||||
|
@ -2710,15 +2744,8 @@ static int d40_set_runtime_config(struct dma_chan *chan,
|
|||
dst_maxburst = config->dst_maxburst;
|
||||
|
||||
if (config->direction == DMA_DEV_TO_MEM) {
|
||||
dma_addr_t dev_addr_rx =
|
||||
d40c->base->plat_data->dev_rx[cfg->src_dev_type];
|
||||
|
||||
config_addr = config->src_addr;
|
||||
if (dev_addr_rx)
|
||||
dev_dbg(d40c->base->dev,
|
||||
"channel has a pre-wired RX address %08x "
|
||||
"overriding with %08x\n",
|
||||
dev_addr_rx, config_addr);
|
||||
|
||||
if (cfg->dir != STEDMA40_PERIPH_TO_MEM)
|
||||
dev_dbg(d40c->base->dev,
|
||||
"channel was not configured for peripheral "
|
||||
|
@ -2733,15 +2760,8 @@ static int d40_set_runtime_config(struct dma_chan *chan,
|
|||
dst_maxburst = src_maxburst;
|
||||
|
||||
} else if (config->direction == DMA_MEM_TO_DEV) {
|
||||
dma_addr_t dev_addr_tx =
|
||||
d40c->base->plat_data->dev_tx[cfg->dst_dev_type];
|
||||
|
||||
config_addr = config->dst_addr;
|
||||
if (dev_addr_tx)
|
||||
dev_dbg(d40c->base->dev,
|
||||
"channel has a pre-wired TX address %08x "
|
||||
"overriding with %08x\n",
|
||||
dev_addr_tx, config_addr);
|
||||
|
||||
if (cfg->dir != STEDMA40_MEM_TO_PERIPH)
|
||||
dev_dbg(d40c->base->dev,
|
||||
"channel was not configured for memory "
|
||||
|
@ -2761,6 +2781,11 @@ static int d40_set_runtime_config(struct dma_chan *chan,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (config_addr <= 0) {
|
||||
dev_err(d40c->base->dev, "no address supplied\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src_maxburst * src_addr_width != dst_maxburst * dst_addr_width) {
|
||||
dev_err(d40c->base->dev,
|
||||
"src/dst width/maxburst mismatch: %d*%d != %d*%d\n",
|
||||
|
@ -2795,8 +2820,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
|
|||
if (chan_is_logical(d40c))
|
||||
d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
|
||||
else
|
||||
d40_phy_cfg(cfg, &d40c->src_def_cfg,
|
||||
&d40c->dst_def_cfg, false);
|
||||
d40_phy_cfg(cfg, &d40c->src_def_cfg, &d40c->dst_def_cfg);
|
||||
|
||||
/* These settings will take precedence later */
|
||||
d40c->runtime_addr = config_addr;
|
||||
|
@ -2927,7 +2951,7 @@ static int __init d40_dmaengine_init(struct d40_base *base,
|
|||
}
|
||||
|
||||
d40_chan_init(base, &base->dma_memcpy, base->log_chans,
|
||||
base->num_log_chans, base->plat_data->memcpy_len);
|
||||
base->num_log_chans, ARRAY_SIZE(dma40_memcpy_channels));
|
||||
|
||||
dma_cap_zero(base->dma_memcpy.cap_mask);
|
||||
dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
|
||||
|
@ -3121,7 +3145,7 @@ static int __init d40_phy_res_init(struct d40_base *base)
|
|||
|
||||
static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
|
||||
{
|
||||
struct stedma40_platform_data *plat_data;
|
||||
struct stedma40_platform_data *plat_data = pdev->dev.platform_data;
|
||||
struct clk *clk = NULL;
|
||||
void __iomem *virtbase = NULL;
|
||||
struct resource *res = NULL;
|
||||
|
@ -3187,8 +3211,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
|
|||
* DB8540v1 has revision 4
|
||||
*/
|
||||
rev = AMBA_REV_BITS(pid);
|
||||
|
||||
plat_data = pdev->dev.platform_data;
|
||||
if (rev < 2) {
|
||||
d40_err(&pdev->dev, "hardware revision: %d is not supported", rev);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* The number of physical channels on this HW */
|
||||
if (plat_data->num_of_phy_chans)
|
||||
|
@ -3196,26 +3222,14 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
|
|||
else
|
||||
num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
|
||||
|
||||
dev_info(&pdev->dev, "hardware revision: %d @ 0x%x with %d physical channels\n",
|
||||
rev, res->start, num_phy_chans);
|
||||
num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY;
|
||||
|
||||
if (rev < 2) {
|
||||
d40_err(&pdev->dev, "hardware revision: %d is not supported",
|
||||
rev);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Count the number of logical channels in use */
|
||||
for (i = 0; i < plat_data->dev_len; i++)
|
||||
if (plat_data->dev_rx[i] != 0)
|
||||
num_log_chans++;
|
||||
|
||||
for (i = 0; i < plat_data->dev_len; i++)
|
||||
if (plat_data->dev_tx[i] != 0)
|
||||
num_log_chans++;
|
||||
dev_info(&pdev->dev,
|
||||
"hardware rev: %d @ 0x%x with %d physical and %d logical channels\n",
|
||||
rev, res->start, num_phy_chans, num_log_chans);
|
||||
|
||||
base = kzalloc(ALIGN(sizeof(struct d40_base), 4) +
|
||||
(num_phy_chans + num_log_chans + plat_data->memcpy_len) *
|
||||
(num_phy_chans + num_log_chans + ARRAY_SIZE(dma40_memcpy_channels)) *
|
||||
sizeof(struct d40_chan), GFP_KERNEL);
|
||||
|
||||
if (base == NULL) {
|
||||
|
@ -3276,17 +3290,11 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
|
|||
if (!base->lookup_phy_chans)
|
||||
goto failure;
|
||||
|
||||
if (num_log_chans + plat_data->memcpy_len) {
|
||||
/*
|
||||
* The max number of logical channels are event lines for all
|
||||
* src devices and dst devices
|
||||
*/
|
||||
base->lookup_log_chans = kzalloc(plat_data->dev_len * 2 *
|
||||
sizeof(struct d40_chan *),
|
||||
GFP_KERNEL);
|
||||
if (!base->lookup_log_chans)
|
||||
goto failure;
|
||||
}
|
||||
base->lookup_log_chans = kzalloc(num_log_chans *
|
||||
sizeof(struct d40_chan *),
|
||||
GFP_KERNEL);
|
||||
if (!base->lookup_log_chans)
|
||||
goto failure;
|
||||
|
||||
base->reg_val_backup_chan = kmalloc(base->num_phy_chans *
|
||||
sizeof(d40_backup_regs_chan),
|
||||
|
@ -3470,17 +3478,52 @@ static int __init d40_lcla_allocate(struct d40_base *base)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __init d40_of_probe(struct platform_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct stedma40_platform_data *pdata;
|
||||
|
||||
/*
|
||||
* FIXME: Fill in this routine as more support is added.
|
||||
* First platform enabled (u8500) doens't need any extra
|
||||
* properties to run, so this is fairly sparce currently.
|
||||
*/
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct stedma40_platform_data),
|
||||
GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev->dev.platform_data = pdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init d40_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct stedma40_platform_data *plat_data = pdev->dev.platform_data;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int err;
|
||||
int ret = -ENOENT;
|
||||
struct d40_base *base;
|
||||
struct d40_base *base = NULL;
|
||||
struct resource *res = NULL;
|
||||
int num_reserved_chans;
|
||||
u32 val;
|
||||
|
||||
base = d40_hw_detect_init(pdev);
|
||||
if (!plat_data) {
|
||||
if (np) {
|
||||
if(d40_of_probe(pdev, np)) {
|
||||
ret = -ENOMEM;
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
d40_err(&pdev->dev, "No pdata or Device Tree provided\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
base = d40_hw_detect_init(pdev);
|
||||
if (!base)
|
||||
goto failure;
|
||||
|
||||
|
@ -3601,6 +3644,13 @@ static int __init d40_probe(struct platform_device *pdev)
|
|||
|
||||
d40_hw_init(base);
|
||||
|
||||
if (np) {
|
||||
err = of_dma_controller_register(np, d40_xlate, NULL);
|
||||
if (err && err != -ENODEV)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register of_dma_controller\n");
|
||||
}
|
||||
|
||||
dev_info(base->dev, "initialized\n");
|
||||
return 0;
|
||||
|
||||
|
@ -3654,11 +3704,17 @@ static int __init d40_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id d40_match[] = {
|
||||
{ .compatible = "stericsson,dma40", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver d40_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = D40_NAME,
|
||||
.pm = DMA40_PM_OPS,
|
||||
.of_match_table = d40_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -50,68 +50,58 @@ void d40_log_cfg(struct stedma40_chan_cfg *cfg,
|
|||
|
||||
}
|
||||
|
||||
/* Sets up SRC and DST CFG register for both logical and physical channels */
|
||||
void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
|
||||
u32 *src_cfg, u32 *dst_cfg, bool is_log)
|
||||
void d40_phy_cfg(struct stedma40_chan_cfg *cfg, u32 *src_cfg, u32 *dst_cfg)
|
||||
{
|
||||
u32 src = 0;
|
||||
u32 dst = 0;
|
||||
|
||||
if (!is_log) {
|
||||
/* Physical channel */
|
||||
if ((cfg->dir == STEDMA40_PERIPH_TO_MEM) ||
|
||||
(cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) {
|
||||
/* Set master port to 1 */
|
||||
src |= 1 << D40_SREG_CFG_MST_POS;
|
||||
src |= D40_TYPE_TO_EVENT(cfg->src_dev_type);
|
||||
if ((cfg->dir == STEDMA40_PERIPH_TO_MEM) ||
|
||||
(cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) {
|
||||
/* Set master port to 1 */
|
||||
src |= 1 << D40_SREG_CFG_MST_POS;
|
||||
src |= D40_TYPE_TO_EVENT(cfg->dev_type);
|
||||
|
||||
if (cfg->src_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL)
|
||||
src |= 1 << D40_SREG_CFG_PHY_TM_POS;
|
||||
else
|
||||
src |= 3 << D40_SREG_CFG_PHY_TM_POS;
|
||||
}
|
||||
if ((cfg->dir == STEDMA40_MEM_TO_PERIPH) ||
|
||||
(cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) {
|
||||
/* Set master port to 1 */
|
||||
dst |= 1 << D40_SREG_CFG_MST_POS;
|
||||
dst |= D40_TYPE_TO_EVENT(cfg->dst_dev_type);
|
||||
if (cfg->src_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL)
|
||||
src |= 1 << D40_SREG_CFG_PHY_TM_POS;
|
||||
else
|
||||
src |= 3 << D40_SREG_CFG_PHY_TM_POS;
|
||||
}
|
||||
if ((cfg->dir == STEDMA40_MEM_TO_PERIPH) ||
|
||||
(cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) {
|
||||
/* Set master port to 1 */
|
||||
dst |= 1 << D40_SREG_CFG_MST_POS;
|
||||
dst |= D40_TYPE_TO_EVENT(cfg->dev_type);
|
||||
|
||||
if (cfg->dst_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL)
|
||||
dst |= 1 << D40_SREG_CFG_PHY_TM_POS;
|
||||
else
|
||||
dst |= 3 << D40_SREG_CFG_PHY_TM_POS;
|
||||
}
|
||||
/* Interrupt on end of transfer for destination */
|
||||
dst |= 1 << D40_SREG_CFG_TIM_POS;
|
||||
if (cfg->dst_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL)
|
||||
dst |= 1 << D40_SREG_CFG_PHY_TM_POS;
|
||||
else
|
||||
dst |= 3 << D40_SREG_CFG_PHY_TM_POS;
|
||||
}
|
||||
/* Interrupt on end of transfer for destination */
|
||||
dst |= 1 << D40_SREG_CFG_TIM_POS;
|
||||
|
||||
/* Generate interrupt on error */
|
||||
src |= 1 << D40_SREG_CFG_EIM_POS;
|
||||
dst |= 1 << D40_SREG_CFG_EIM_POS;
|
||||
/* Generate interrupt on error */
|
||||
src |= 1 << D40_SREG_CFG_EIM_POS;
|
||||
dst |= 1 << D40_SREG_CFG_EIM_POS;
|
||||
|
||||
/* PSIZE */
|
||||
if (cfg->src_info.psize != STEDMA40_PSIZE_PHY_1) {
|
||||
src |= 1 << D40_SREG_CFG_PHY_PEN_POS;
|
||||
src |= cfg->src_info.psize << D40_SREG_CFG_PSIZE_POS;
|
||||
}
|
||||
if (cfg->dst_info.psize != STEDMA40_PSIZE_PHY_1) {
|
||||
dst |= 1 << D40_SREG_CFG_PHY_PEN_POS;
|
||||
dst |= cfg->dst_info.psize << D40_SREG_CFG_PSIZE_POS;
|
||||
}
|
||||
/* PSIZE */
|
||||
if (cfg->src_info.psize != STEDMA40_PSIZE_PHY_1) {
|
||||
src |= 1 << D40_SREG_CFG_PHY_PEN_POS;
|
||||
src |= cfg->src_info.psize << D40_SREG_CFG_PSIZE_POS;
|
||||
}
|
||||
if (cfg->dst_info.psize != STEDMA40_PSIZE_PHY_1) {
|
||||
dst |= 1 << D40_SREG_CFG_PHY_PEN_POS;
|
||||
dst |= cfg->dst_info.psize << D40_SREG_CFG_PSIZE_POS;
|
||||
}
|
||||
|
||||
/* Element size */
|
||||
src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS;
|
||||
dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS;
|
||||
/* Element size */
|
||||
src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS;
|
||||
dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS;
|
||||
|
||||
/* Set the priority bit to high for the physical channel */
|
||||
if (cfg->high_priority) {
|
||||
src |= 1 << D40_SREG_CFG_PRI_POS;
|
||||
dst |= 1 << D40_SREG_CFG_PRI_POS;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Logical channel */
|
||||
dst |= 1 << D40_SREG_CFG_LOG_GIM_POS;
|
||||
src |= 1 << D40_SREG_CFG_LOG_GIM_POS;
|
||||
/* Set the priority bit to high for the physical channel */
|
||||
if (cfg->high_priority) {
|
||||
src |= 1 << D40_SREG_CFG_PRI_POS;
|
||||
dst |= 1 << D40_SREG_CFG_PRI_POS;
|
||||
}
|
||||
|
||||
if (cfg->src_info.big_endian)
|
||||
|
|
|
@ -432,8 +432,7 @@ enum d40_lli_flags {
|
|||
|
||||
void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
|
||||
u32 *src_cfg,
|
||||
u32 *dst_cfg,
|
||||
bool is_log);
|
||||
u32 *dst_cfg);
|
||||
|
||||
void d40_log_cfg(struct stedma40_chan_cfg *cfg,
|
||||
u32 *lcsp1,
|
||||
|
|
|
@ -86,7 +86,7 @@ enum stedma40_xfer_dir {
|
|||
|
||||
|
||||
/**
|
||||
* struct stedma40_chan_cfg - dst/src channel configuration
|
||||
* struct stedma40_half_channel_info - dst/src channel configuration
|
||||
*
|
||||
* @big_endian: true if the src/dst should be read as big endian
|
||||
* @data_width: Data width of the src/dst hardware
|
||||
|
@ -109,8 +109,7 @@ struct stedma40_half_channel_info {
|
|||
* version 3+, i.e DB8500v2+
|
||||
* @mode: channel mode: physical, logical, or operation
|
||||
* @mode_opt: options for the chosen channel mode
|
||||
* @src_dev_type: Src device type
|
||||
* @dst_dev_type: Dst device type
|
||||
* @dev_type: src/dst device type (driver uses dir to figure out which)
|
||||
* @src_info: Parameters for dst half channel
|
||||
* @dst_info: Parameters for dst half channel
|
||||
* @use_fixed_channel: if true, use physical channel specified by phy_channel
|
||||
|
@ -126,8 +125,7 @@ struct stedma40_chan_cfg {
|
|||
bool realtime;
|
||||
enum stedma40_mode mode;
|
||||
enum stedma40_mode_opt mode_opt;
|
||||
int src_dev_type;
|
||||
int dst_dev_type;
|
||||
int dev_type;
|
||||
struct stedma40_half_channel_info src_info;
|
||||
struct stedma40_half_channel_info dst_info;
|
||||
|
||||
|
@ -138,13 +136,8 @@ struct stedma40_chan_cfg {
|
|||
/**
|
||||
* struct stedma40_platform_data - Configuration struct for the dma device.
|
||||
*
|
||||
* @dev_len: length of dev_tx and dev_rx
|
||||
* @dev_tx: mapping between destination event line and io address
|
||||
* @dev_rx: mapping between source event line and io address
|
||||
* @memcpy: list of memcpy event lines
|
||||
* @memcpy_len: length of memcpy
|
||||
* @memcpy_conf_phy: default configuration of physical channel memcpy
|
||||
* @memcpy_conf_log: default configuration of logical channel memcpy
|
||||
* @disabled_channels: A vector, ending with -1, that marks physical channels
|
||||
* that are for different reasons not available for the driver.
|
||||
* @soft_lli_chans: A vector, that marks physical channels will use LLI by SW
|
||||
|
@ -159,13 +152,6 @@ struct stedma40_chan_cfg {
|
|||
* for 'multiple of 4' channels, like 8.
|
||||
*/
|
||||
struct stedma40_platform_data {
|
||||
u32 dev_len;
|
||||
const dma_addr_t *dev_tx;
|
||||
const dma_addr_t *dev_rx;
|
||||
int *memcpy;
|
||||
u32 memcpy_len;
|
||||
struct stedma40_chan_cfg *memcpy_conf_phy;
|
||||
struct stedma40_chan_cfg *memcpy_conf_log;
|
||||
int disabled_channels[STEDMA40_MAX_PHYS];
|
||||
int *soft_lli_chans;
|
||||
int num_of_soft_lli_chans;
|
||||
|
|
Loading…
Reference in a new issue