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

Linus Walleij linus.ml.walleij at gmail.com
Mon Aug 23 13:30:34 EDT 2010


2010/8/23 Sascha Hauer <s.hauer at pengutronix.de>:

> This patch adds support for the Freescale i.MX SDMA engine.

Great progress!

> (...)
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> (...)
> +/* 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)

These macros expand to the local variable "sdma" which must
be present in all functions using them. I don't know what is
considered moste readable, but I would certainly just

#define SDMA_FOO (0x0123)
(...)
u32 foo = readl(sdma->regs + SDMA_FOO);

That is more common I think.

> (...)
> +/*
> + * Channel control Block

Some kerneldoc here describing especially
@unused: padding for register cast
@usused1: padding for register cast

Hm "unused" and "unused1" wrinkles my binary brain,
can you call the first one "unused0" for my perceptions
sake?

> + */
> +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_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;

id1 und id2 oder
id0 und id1 fierleicht?

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

1 and 2, else unnumbered and 1, else unnumbered and 2 X-)

> +       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 */
> +       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;

Picky me, but it's no type, its an enum. I understand that it is
a technical term...

What about just calling is sdma_transfer? Short and nice.
Or sdma_transfer_line?

> (...)
> +/*
> + * Stores the start address of the SDMA scripts
> + */
> +static struct sdma_script_start_addrs __sdma_script_addrs;
> +static struct sdma_script_start_addrs *sdma_script_addrs = &__sdma_script_addrs;

What's the rationale behind prefixing that variable with __?

The same name for struct and variable is perfectly viable.

Apart from these smallies (and it's all minor stuff) it's nice and clean so:

Reviewed-by: Linus Walleij <linus.walleij at stericsson.com>

Yours,
Linus Walleij



More information about the linux-arm-kernel mailing list