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:
Olof Johansson 2013-05-27 20:09:53 -07:00
commit 6f39ef575d
17 changed files with 498 additions and 660 deletions

View 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";
};

View file

@ -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,

View file

@ -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

View file

@ -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();
}

View file

@ -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);

View file

@ -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),
{},
};

View file

@ -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},
};

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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,
},
};

View file

@ -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)

View file

@ -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,

View file

@ -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;