[PATCH 3/3 v2] dmaengine: Add Freescale i.MX SDMA support

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Mon Aug 23 13:48:52 EDT 2010


Hallo Sascha,

On Mon, Aug 23, 2010 at 02:57:04PM +0200, Sascha Hauer wrote:
> 
> This patch adds support for the Freescale i.MX SDMA engine.
> 
> The SDMA engine is a scatter/gather DMA engine which is implemented
> as a seperate coprocessor. SDMA needs its own firmware which is
> requested using the standard request_firmware mechanism. The firmware
> has different entry points for each peripheral type, so drivers
> have to pass the peripheral type to the DMA engine which in turn
> picks the correct firmware entry point from a table contained in
> the firmware image itself.
> The original Freescale code also supports support for transfering
> data to the internal SRAM which needs different entry points to
> the firmware. Support for this is currently not implemented. Also,
> support for the ASRC (asymmetric sample rate converter) is skipped.
> 
> I took a very simple approach to implement dmaengine support. Only
> a single descriptor is statically assigned to a each channel. This
> means that transfers can't be queued up but only a single transfer
> is in progress. This simplifies implementation a lot and is sufficient
> for the usual device/memory transfers.
> 
> Changes since v1:
> 
> - included comments from Linus Walleij
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  arch/arm/mach-imx/include/mach/dma-v1.h |    8 +-
>  arch/arm/mach-mx3/Kconfig               |    2 +
>  arch/arm/plat-mxc/Kconfig               |   10 +
>  arch/arm/plat-mxc/include/mach/dma.h    |   64 ++
>  arch/arm/plat-mxc/include/mach/sdma.h   |   17 +
>  drivers/dma/Kconfig                     |    8 +
>  drivers/dma/Makefile                    |    1 +
>  drivers/dma/imx-sdma.c                  | 1395 +++++++++++++++++++++++++++++++
>  8 files changed, 1499 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm/plat-mxc/include/mach/dma.h
>  create mode 100644 arch/arm/plat-mxc/include/mach/sdma.h
>  create mode 100644 drivers/dma/imx-sdma.c
> 
> diff --git a/arch/arm/mach-imx/include/mach/dma-v1.h b/arch/arm/mach-imx/include/mach/dma-v1.h
> index 287431c..ac6fd71 100644
> --- a/arch/arm/mach-imx/include/mach/dma-v1.h
> +++ b/arch/arm/mach-imx/include/mach/dma-v1.h
> @@ -27,6 +27,8 @@
>  
>  #define imx_has_dma_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
>  
> +#include <mach/dma.h>
> +
>  #define IMX_DMA_CHANNELS  16
>  
>  #define DMA_MODE_READ		0
> @@ -96,12 +98,6 @@ int imx_dma_request(int channel, const char *name);
>  
>  void imx_dma_free(int channel);
>  
> -enum imx_dma_prio {
> -	DMA_PRIO_HIGH = 0,
> -	DMA_PRIO_MEDIUM = 1,
> -	DMA_PRIO_LOW = 2
> -};
> -
>  int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio);
>  
>  #endif	/* __MACH_DMA_V1_H__ */
> diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
> index 85beece..301375c 100644
> --- a/arch/arm/mach-mx3/Kconfig
> +++ b/arch/arm/mach-mx3/Kconfig
> @@ -3,12 +3,14 @@ if ARCH_MX3
>  config ARCH_MX31
>  	select ARCH_HAS_RNGA
>  	select ARCH_MXC_AUDMUX_V2
> +	select IMX_HAVE_SDMA
>  	bool
>  
>  config ARCH_MX35
>  	bool
>  	select ARCH_MXC_IOMUX_V3
>  	select ARCH_MXC_AUDMUX_V2
> +	select IMX_HAVE_SDMA
>  
>  comment "MX3 platforms:"
>  
> diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
> index 0527e65..6741625 100644
> --- a/arch/arm/plat-mxc/Kconfig
> +++ b/arch/arm/plat-mxc/Kconfig
> @@ -109,4 +109,14 @@ config ARCH_MXC_AUDMUX_V1
>  config ARCH_MXC_AUDMUX_V2
>  	bool
>  
> +config IMX_HAVE_SDMA
> +	bool
> +
> +config IMX_SDMA
> +	depends on IMX_HAVE_SDMA
> +	tristate "Enable SDMA support"
> +	help
> +	  Include support for the SDMA engine. The SDMA engine needs additional
> +	  firmware support. SDMA can be compiled as a module to support loading
> +	  the firmware when a rootfs is present.
>  endif
> diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h
> new file mode 100644
> index 0000000..69d181f
> --- /dev/null
> +++ b/arch/arm/plat-mxc/include/mach/dma.h
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __ASM_ARCH_MXC_DMA_H__
> +#define __ASM_ARCH_MXC_DMA_H__
__MACH_DMA_H__ please

> +
> +#include <linux/scatterlist.h>
> +
> +/*
> + * This enumerates peripheral types. Used for SDMA.
> + */
> +enum sdma_peripheral_type {
> +	IMX_DMATYPE_SSI,	/* MCU domain SSI */
> +	IMX_DMATYPE_SSI_SP,	/* Shared SSI */
> +	IMX_DMATYPE_MMC,	/* MMC */
> +	IMX_DMATYPE_SDHC,	/* SDHC */
> +	IMX_DMATYPE_UART,	/* MCU domain UART */
> +	IMX_DMATYPE_UART_SP,	/* Shared UART */
> +	IMX_DMATYPE_FIRI,	/* FIRI */
> +	IMX_DMATYPE_CSPI,	/* MCU domain CSPI */
> +	IMX_DMATYPE_CSPI_SP,	/* Shared CSPI */
> +	IMX_DMATYPE_SIM,	/* SIM */
> +	IMX_DMATYPE_ATA,	/* ATA */
> +	IMX_DMATYPE_CCM,	/* CCM */
> +	IMX_DMATYPE_EXT,	/* External peripheral */
> +	IMX_DMATYPE_MSHC,	/* Memory Stick Host Controller */
> +	IMX_DMATYPE_MSHC_SP,	/* Shared Memory Stick Host Controller */
> +	IMX_DMATYPE_DSP,	/* DSP */
> +	IMX_DMATYPE_MEMORY,	/* Memory */
> +	IMX_DMATYPE_FIFO_MEMORY,/* FIFO type Memory */
> +	IMX_DMATYPE_SPDIF,	/* SPDIF */
> +	IMX_DMATYPE_IPU_MEMORY,	/* IPU Memory */
> +	IMX_DMATYPE_ASRC,	/* ASRC */
> +	IMX_DMATYPE_ESAI,	/* ESAI */
> +};
> +
> +enum imx_dma_prio {
> +	DMA_PRIO_HIGH = 0,
> +	DMA_PRIO_MEDIUM = 1,
> +	DMA_PRIO_LOW = 2
> +};
> +
> +struct imx_dma_data {
> +	int dma_request; /* DMA request line */
> +	enum sdma_peripheral_type peripheral_type;
> +	int priority;
> +};
> +
> +static inline int imx_dma_is_ipu(struct dma_chan *chan)
> +{
> +	return !strcmp(dev_name(chan->device->dev), "ipu-core");
> +}
> +
> +static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
> +{
> +	return !strcmp(dev_name(chan->device->dev), "imx-sdma");
> +}
> +
> +#endif
> diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
> new file mode 100644
> index 0000000..9be1122
> --- /dev/null
> +++ b/arch/arm/plat-mxc/include/mach/sdma.h
> @@ -0,0 +1,17 @@
> +#ifndef __MACH_MXC_SDMA_H__
> +#define __MACH_MXC_SDMA_H__
__MACH_SDMA_H__

> +
> +/**
> + * struct sdma_platform_data - platform specific data for SDMA engine
> + *
> + * @sdma_version	The version of this SDMA engine
> + * @cpu_name		used to generate the firmware name
> + * @to_version		CPU Tape out version
> + */
> +struct sdma_platform_data {
> +	int sdma_version;
> +	char *cpu_name;
> +	int to_version;
> +};
> +
> +#endif /* __MACH_MXC_SDMA_H__ */
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 9520cf0..ff68307 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -195,6 +195,14 @@ config PCH_DMA
>  	help
>  	  Enable support for the Topcliff PCH DMA engine.
>  
> +config IMX_SDMA
> +	tristate "i.MX SDMA support"
> +	depends on ARCH_MXC
> +	select DMA_ENGINE
> +	help
> +	  Support the i.MX SDMA engine. This engine is integrated into
> +	  Freescale i.MX25/31/35/51 chips.
> +
>  config DMA_ENGINE
>  	bool
>  
> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> index 72bd703..14d7a1b 100644
> --- a/drivers/dma/Makefile
> +++ b/drivers/dma/Makefile
> @@ -25,3 +25,4 @@ obj-$(CONFIG_TIMB_DMA) += timb_dma.o
>  obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
>  obj-$(CONFIG_PL330_DMA) += pl330.o
>  obj-$(CONFIG_PCH_DMA) += pch_dma.o
> +obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> new file mode 100644
> index 0000000..c447fc0
> --- /dev/null
> +++ b/drivers/dma/imx-sdma.c
> @@ -0,0 +1,1395 @@
> +/*
> + * drivers/dma/imx-sdma.c
> + *
> + * This file contains a driver for the Freescale Smart DMA engine
> + *
> + * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
> + *
> + * Based on code from Freescale:
> + *
> + * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#include <linux/init.h>
> +#include <linux/types.h>
> +#include <linux/mm.h>
> +#include <linux/interrupt.h>
> +#include <linux/clk.h>
> +#include <linux/wait.h>
> +#include <linux/sched.h>
> +#include <linux/semaphore.h>
> +#include <linux/spinlock.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/firmware.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/dmaengine.h>
> +
> +#include <asm/irq.h>
> +#include <mach/sdma.h>
> +#include <mach/dma.h>
> +#include <mach/hardware.h>
> +
> +/* SDMA registers */
> +#define SDMA_H_C0PTR		(sdma->regs + 0x000)
> +#define SDMA_H_INTR		(sdma->regs + 0x004)
> +#define SDMA_H_STATSTOP		(sdma->regs + 0x008)
> +#define SDMA_H_START		(sdma->regs + 0x00c)
> +#define SDMA_H_EVTOVR		(sdma->regs + 0x010)
> +#define SDMA_H_DSPOVR		(sdma->regs + 0x014)
> +#define SDMA_H_HOSTOVR		(sdma->regs + 0x018)
> +#define SDMA_H_EVTPEND		(sdma->regs + 0x01c)
> +#define SDMA_H_DSPENBL		(sdma->regs + 0x020)
> +#define SDMA_H_RESET		(sdma->regs + 0x024)
> +#define SDMA_H_EVTERR		(sdma->regs + 0x028)
> +#define SDMA_H_INTRMSK		(sdma->regs + 0x02c)
> +#define SDMA_H_PSW		(sdma->regs + 0x030)
> +#define SDMA_H_EVTERRDBG	(sdma->regs + 0x034)
> +#define SDMA_H_CONFIG		(sdma->regs + 0x038)
> +#define SDMA_ONCE_ENB		(sdma->regs + 0x040)
> +#define SDMA_ONCE_DATA		(sdma->regs + 0x044)
> +#define SDMA_ONCE_INSTR		(sdma->regs + 0x048)
> +#define SDMA_ONCE_STAT		(sdma->regs + 0x04c)
> +#define SDMA_ONCE_CMD		(sdma->regs + 0x050)
> +#define SDMA_EVT_MIRROR		(sdma->regs + 0x054)
> +#define SDMA_ILLINSTADDR	(sdma->regs + 0x058)
> +#define SDMA_CHN0ADDR		(sdma->regs + 0x05c)
> +#define SDMA_ONCE_RTB		(sdma->regs + 0x060)
> +#define SDMA_XTRIG_CONF1	(sdma->regs + 0x070)
> +#define SDMA_XTRIG_CONF2	(sdma->regs + 0x074)
> +#define SDMA_CHNENBL_0		(sdma->regs + (sdma->version == 2 ? 0x200 : 0x80))
> +#define SDMA_CHNPRI_0		(sdma->regs + 0x100)
I'd prefer having an accessor function like

	u32 sdma_read(struct whatever *sdma, unsigned offset)
	{
		return __raw_readl(sdma->regs + offset);
	}
	...

> +
> +/*
> + * Buffer descriptor status values.
> + */
> +#define BD_DONE  0x01
> +#define BD_WRAP  0x02
> +#define BD_CONT  0x04
> +#define BD_INTR  0x08
> +#define BD_RROR  0x10
> +#define BD_LAST  0x20
> +#define BD_EXTD  0x80
> +
> +/*
> + * Data Node descriptor status values.
> + */
> +#define DND_END_OF_FRAME  0x80
> +#define DND_END_OF_XFER   0x40
> +#define DND_DONE          0x20
> +#define DND_UNUSED        0x01
> +
> +/*
> + * IPCV2 descriptor status values.
> + */
> +#define BD_IPCV2_END_OF_FRAME  0x40
> +
> +#define IPCV2_MAX_NODES        50
> +/*
> + * Error bit set in the CCB status field by the SDMA,
> + * in setbd routine, in case of a transfer error
> + */
> +#define DATA_ERROR  0x10000000
> +
> +/*
> + * Buffer descriptor commands.
> + */
> +#define C0_ADDR             0x01
> +#define C0_LOAD             0x02
> +#define C0_DUMP             0x03
> +#define C0_SETCTX           0x07
> +#define C0_GETCTX           0x03
> +#define C0_SETDM            0x01
> +#define C0_SETPM            0x04
> +#define C0_GETDM            0x02
> +#define C0_GETPM            0x08
> +/*
> + * Change endianness indicator in the BD command field
> + */
> +#define CHANGE_ENDIANNESS   0x80
> +
> +/*
> + * Mode/Count of data node descriptors - IPCv2
> + */
> +struct sdma_mode_count {
> +	u32 count   : 16; /* size of the buffer pointed by this BD */
> +	u32 status  :  8; /* E,R,I,C,W,D status bits stored here */
> +	u32 command :  8; /* command mostlky used for channel 0 */
s/mostlky/mostly/

> +};
> +
> +/*
> + * Buffer descriptor
> + */
> +struct sdma_buffer_descriptor {
> +	struct sdma_mode_count  mode;
> +	dma_addr_t buffer_addr;    /* address of the buffer described */
> +	dma_addr_t ext_buffer_addr; /* extended buffer address */
> +} __attribute__ ((packed));
> +
> +/*
> + * Channel control Block
> + */
> +struct sdma_channel_control {
> +	dma_addr_t current_bd_ptr; /* current buffer descriptor processed */
> +	dma_addr_t base_bd_ptr;    /* first element of buffer descriptor array */
> +	u32 unused;
> +	u32 unused1;
> +} __attribute__ ((packed));
> +
> +/**
> + * struct sdma_state_registers - SDMA context for a channel
> + *
> + * @pc:		program counter
> + * @t:		test bit: status of arithmetic & test instruction
> + * @rpc:	return program counter
> + * @sf:		source fault while loading data
> + * @spc:	loop start program counter
> + * @df:		destination fault while storing data
> + * @epc:	loop end program counter
> + * @lm:		loop mode
> + */
> +struct sdma_state_registers {
> +	u32 pc     :14;
> +	u32 unused1: 1;
> +	u32 t      : 1;
> +	u32 rpc    :14;
> +	u32 unused0: 1;
> +	u32 sf     : 1;
> +	u32 spc    :14;
> +	u32 unused2: 1;
> +	u32 df     : 1;
> +	u32 epc    :14;
> +	u32 lm     : 2;
> +} __attribute__ ((packed));
I'm not sure what CodingStyle recommends, but I'd not add a space
between __attribute__ and (.
> +
> +/**
> + * struct sdma_context_data - sdma context specific to a channel
> + *
> + * @channel_state:	channel state bits
> + * @gReg:		general registers
> + * @mda:		burst dma destination address register
> + * @msa:		burst dma source address register
> + * @ms:			burst dma status register
> + * @md:			burst dma data register
> + * @pda:		peripheral dma destination address register
> + * @psa:		peripheral dma source address register
> + * @ps:			peripheral dma status register
> + * @pd:			peripheral dma data register
> + * @ca:			CRC polynomial register
> + * @cs:			CRC accumulator register
> + * @dda:		dedicated core destination address register
> + * @dsa:		dedicated core source address register
> + * @ds:			dedicated core status register
> + * @dd:			dedicated core data register
> + */
> +struct sdma_context_data {
> +	struct sdma_state_registers  channel_state;
> +	u32  gReg[8];
> +	u32  mda;
> +	u32  msa;
> +	u32  ms;
> +	u32  md;
> +	u32  pda;
> +	u32  psa;
> +	u32  ps;
> +	u32  pd;
> +	u32  ca;
> +	u32  cs;
> +	u32  dda;
> +	u32  dsa;
> +	u32  ds;
> +	u32  dd;
> +	u32  scratch0;
> +	u32  scratch1;
> +	u32  scratch2;
> +	u32  scratch3;
> +	u32  scratch4;
> +	u32  scratch5;
> +	u32  scratch6;
> +	u32  scratch7;
> +} __attribute__ ((packed));
s/  / /?

> +
> +#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
> +
> +struct sdma_engine;
> +
> +/**
> + * struct sdma_channel - housekeeping for a SDMA channel
> + *
> + * @sdma		pointer to the SDMA engine for this channel
> + * @channel		the channel number, matches dmaengine chan_id
> + * @direction		transfer type. Needed for setting SDMA script
> + * @peripheral_type	Peripheral type. Needed for setting SDMA script
> + * @event_id		aka dma request line
> + * @event_id2		for channels that use 2 events
> + * @word_size		peripheral access size
> + * @buf_tail		ID of the buffer that was processed
> + * @done		channel completion
> + * @num_bd		max NUM_BD. number of descriptors currently handling
> + */
> +struct sdma_channel {
> +	struct sdma_engine		*sdma;
> +	unsigned int			channel;
> +	enum dma_data_direction		direction;
> +	enum sdma_peripheral_type	peripheral_type;
> +	unsigned int			event_id;
> +	unsigned int			event_id2;
> +	enum dma_slave_buswidth		word_size;
> +	unsigned int			buf_tail;
> +	struct completion		done;
> +	unsigned int			num_bd;
> +	struct sdma_buffer_descriptor	*bd;
> +	dma_addr_t			bd_phys;
> +	unsigned int			pc_from_device, pc_to_device;
> +	unsigned long			flags;
> +	dma_addr_t			per_address;
> +	u32				event_mask1, event_mask2;
> +	u32				watermark_level;
> +	u32				shp_addr, per_addr;
> +	struct dma_chan			chan;
> +	spinlock_t			lock;
> +	struct dma_async_tx_descriptor	desc;
> +	dma_cookie_t			last_completed;
> +	enum dma_status			status;
> +};
> +
> +#define IMX_DMA_SG_LOOP		(1 << 0)
> +
> +#define MAX_DMA_CHANNELS 32
> +#define MXC_SDMA_DEFAULT_PRIORITY 1
> +#define MXC_SDMA_MIN_PRIORITY 1
> +#define MXC_SDMA_MAX_PRIORITY 7
> +
> +/*
> + * This enumerates transfer types
> + */
> +enum {
> +	emi_2_per = 0,		/* EMI memory to peripheral */
> +	emi_2_int,		/* EMI memory to internal RAM */
> +	emi_2_emi,		/* EMI memory to EMI memory */
> +	emi_2_dsp,		/* EMI memory to DSP memory */
> +	per_2_int,		/* Peripheral to internal RAM */
s/int/iram/ maybe?

> +	per_2_emi,		/* Peripheral to internal EMI memory */
> +	per_2_dsp,		/* Peripheral to DSP memory */
> +	per_2_per,		/* Peripheral to Peripheral */
> +	int_2_per,		/* Internal RAM to peripheral */
> +	int_2_int,		/* Internal RAM to Internal RAM */
> +	int_2_emi,		/* Internal RAM to EMI memory */
> +	int_2_dsp,		/* Internal RAM to DSP memory */
> +	dsp_2_per,		/* DSP memory to peripheral */
> +	dsp_2_int,		/* DSP memory to internal RAM */
> +	dsp_2_emi,		/* DSP memory to EMI memory */
> +	dsp_2_dsp,		/* DSP memory to DSP memory */
> +	emi_2_dsp_loop,		/* EMI memory to DSP memory loopback */
> +	dsp_2_emi_loop,		/* DSP memory to EMI memory loopback */
> +	dvfs_pll,		/* DVFS script with PLL change       */
> +	dvfs_pdr		/* DVFS script without PLL change    */
> +} sdma_transfer_type;
> +
> +/**
> + * struct sdma_script_start_addrs - SDMA script start pointers
> + *
> + * start addresses of the different functions in the physical
> + * address space of the SDMA engine.
> + */
> +struct sdma_script_start_addrs {
> +	u32 ap_2_ap_addr;
> +	u32 ap_2_bp_addr;
> +	u32 ap_2_ap_fixed_addr;
> +	u32 bp_2_ap_addr;
> +	u32 loopback_on_dsp_side_addr;
> +	u32 mcu_interrupt_only_addr;
> +	u32 firi_2_per_addr;
> +	u32 firi_2_mcu_addr;
> +	u32 per_2_firi_addr;
> +	u32 mcu_2_firi_addr;
> +	u32 uart_2_per_addr;
> +	u32 uart_2_mcu_addr;
> +	u32 per_2_app_addr;
> +	u32 mcu_2_app_addr;
> +	u32 per_2_per_addr;
> +	u32 uartsh_2_per_addr;
> +	u32 uartsh_2_mcu_addr;
> +	u32 per_2_shp_addr;
> +	u32 mcu_2_shp_addr;
> +	u32 ata_2_mcu_addr;
> +	u32 mcu_2_ata_addr;
> +	u32 app_2_per_addr;
> +	u32 app_2_mcu_addr;
> +	u32 shp_2_per_addr;
> +	u32 shp_2_mcu_addr;
> +	u32 mshc_2_mcu_addr;
> +	u32 mcu_2_mshc_addr;
> +	u32 spdif_2_mcu_addr;
> +	u32 mcu_2_spdif_addr;
> +	u32 asrc_2_mcu_addr;
> +	u32 ext_mem_2_ipu_addr;
> +	u32 descrambler_addr;
> +	u32 dptc_dvfs_addr;
> +	u32 utra_addr;
> +	u32 ram_code_start_addr;
> +};
You didn't comment my suggestion to use an array here.  Something like

	struct {
		const char *name;
		u32 addr;
	} start_addr[];
> +
> +#define SDMA_FIRMWARE_MAGIC 0x414d4453
> +
> +/**
> + * struct sdma_firmware_header - Layout of the firmware image
> + *
> + * @magic		"SDMA"
> + * @version_major	increased whenever layout of struct sdma_script_start_addrs
> + *			changes.
> + * @version_minor	firmware minor version (for binary compatible changes)
> + * @script_addrs_start	offset of struct sdma_script_start_addrs in this image
> + * @num_script_addrs	Number of script addresses in this image
> + * @ram_code_start	offset of SDMA ram image in this firmware image
> + * @ram_code_size	size of SDMA ram image
> + */
> +struct sdma_firmware_header {
> +	u32	magic;
> +	u32	version_major;
> +	u32	version_minor;
> +	u32	script_addrs_start;
> +	u32	num_script_addrs;
> +	u32	ram_code_start;
> +	u32	ram_code_size;
> +};
> +
> +struct sdma_engine {
> +	struct device			*dev;
> +	struct sdma_channel		channel[MAX_DMA_CHANNELS];
> +	struct sdma_channel_control	*channel_control;
> +	void __iomem			*regs;
> +	unsigned int			version;
> +	unsigned int			num_events;
> +	struct sdma_context_data	*context;
> +	dma_addr_t			context_phys;
> +	struct dma_device		dma_device;
> +	struct clk			*clk;
> +};
> +
> +#define SDMA_H_CONFIG_DSPDMA	(1 << 12) /* indicates if the DSPDMA is used */
> +#define SDMA_H_CONFIG_RTD_PINS	(1 << 11) /* indicates if Real-Time Debug pins are enabled */
> +#define SDMA_H_CONFIG_ACR	(1 << 4)  /* indicates if AHB freq /core freq = 2 or 1 */
> +#define SDMA_H_CONFIG_CSM	(3)       /* indicates which context switch mode is selected*/
> +
> +static int sdma_config_ownership(struct sdma_channel *sdmac,
> +		bool event_override, bool mcu_verride, bool dsp_override)
> +{
> +	struct sdma_engine *sdma = sdmac->sdma;
> +	int channel = sdmac->channel;
> +	u32 evt, mcu, dsp;
> +
> +	if (event_override && mcu_verride && dsp_override)
> +		return -EINVAL;
> +
> +	evt = readl(SDMA_H_EVTOVR);
> +	mcu = readl(SDMA_H_HOSTOVR);
> +	dsp = readl(SDMA_H_DSPOVR);
__raw_readl?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |



More information about the linux-arm-kernel mailing list