* [PATCH v8 1/2] sDMA: descriptor autoloading feature
@ 2010-04-29 17:35 Venkatraman S
2010-05-05 9:32 ` Shilimkar, Santosh
2010-05-05 10:05 ` Adrian Hunter
0 siblings, 2 replies; 9+ messages in thread
From: Venkatraman S @ 2010-04-29 17:35 UTC (permalink / raw)
To: linux-arm-kernel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-04-29 17:35 [PATCH v8 1/2] sDMA: descriptor autoloading feature Venkatraman S
@ 2010-05-05 9:32 ` Shilimkar, Santosh
2010-05-05 11:50 ` Venkatraman S
2010-05-05 10:05 ` Adrian Hunter
1 sibling, 1 reply; 9+ messages in thread
From: Shilimkar, Santosh @ 2010-05-05 9:32 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
> Sent: Thursday, April 29, 2010 11:05 PM
> To: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Cc: Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren; Shilimkar, Santosh
> Subject: [PATCH v8 1/2] sDMA: descriptor autoloading feature
>
> From d46f8a00728cc6c1fbdfce69435759c8cc49f25c Mon Sep 17 00:00:00 2001
> From: Venkatraman S <svenkatr@ti.com>
> Date: Thu, 29 Apr 2010 22:34:04 +0530
> Subject: [PATCH 1/2] sDMA: descriptor autoloading feature
>
> Add sDMA driver support for descriptor autoloading feature.
> Descriptor autoloading is OMAP sDMA v5 hardware capability that can
> be exploited for scatter gather
> scenarios, currently available in OMAP3630 and OMAP4430.
>
> The feature works as described below.
> 1) A sDMA channel is programmed to be in 'linked list' mode.
> 2) The client (sDMA user) provides a list of descriptors in a linked
> list format.
> 3) Each of the 'descriptor' (element in the linked list) contains an
> updated set of DMA
> configuration register values.
> 4) Client starts DMA transfer.
> 5) sDMA controller loads the first element to its register
> configuration memory and executes the
> transfer.
> 6) After completion, loads the next element (in linked list) to
> configuration memory and executes
> the transfer, without MCU intervention.
> 7) Interrupt is generated after all transfers are completed; this
> can be configured to be done
> differently.
>
> Configurations and additional features
> 1) Fast mode & non-fast mode
> Fast mode/non-fast decides on how the first transfer begins.
> In non-fast mode, the first
> element in the linked list is loaded only after completing the
> transfer according to the
> configurations already in the sDMA channel registers. In fast mode,
> the loading of the first
> element precedes the transfer.
>
> 2) Pause / resume of transfers
> A transfer can be paused after a descriptor set has been loaded,
> provided the 'pause
> bit' is set in the linked list element.
> An ongoing transfer cannot be paused. If the 'pause bit' is set,
> transfer is not
> started after loading the register set from memory.
> Such a transfer can be resumed later.
>
> 3) Descriptor types
> 3 possible configurations of descriptors (initialized as linked list elements)
> are possible. Type 1 provides the maximum flexibility, which contains most
> register definitions of a DMA logical channel. Fewer options are
> present in type
> 2. Type 3 can just modify source/destinations address of transfers. In all
> transfers, unmodified registers settings are maintained for the next transfer.
>
> Patch provides options / API for
> 1) Setting up a descriptor loading for DMA channel for sg type transfers
> 2) configuration with linked list elements
> 3) Starting / pause and resume of the said transfers, query state
> 4) Clearing the sglist mode
>
> Signed-off-by: Venkatraman S <svenkatr@ti.com>
> CC: Adrian Hunter <adrian.hunter@nokia.com>
> CC: Madhusudhan C <madhu.cr@ti.com>
> CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
> CC: Tony Lindgren <tony@atomide.com>
> ---
> Changes from v7:
> * Added wmb() calls between descriptor data structure update and
> start/resume of transfer
> * Added proper commit log about the feature
>
> arch/arm/plat-omap/dma.c | 289 ++++++++++++++++++++++++++++++++-
> arch/arm/plat-omap/include/plat/dma.h | 170 +++++++++++++++++++
> 2 files changed, 458 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
> index f6c9bdc..d8d4df8 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -46,12 +46,40 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE,
> DMA_CH_STARTED,
> enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
> #endif
>
> +/* CDP Register bitmaps */
> +#define DMA_LIST_CDP_DST_VALID (BIT(0))
> +#define DMA_LIST_CDP_SRC_VALID (BIT(2))
> +#define DMA_LIST_CDP_TYPE1 (BIT(4))
> +#define DMA_LIST_CDP_TYPE2 (BIT(5))
> +#define DMA_LIST_CDP_TYPE3 (BIT(4) | BIT(5))
> +#define DMA_LIST_CDP_PAUSEMODE (BIT(7))
> +#define DMA_LIST_CDP_LISTMODE (BIT(8))
> +#define DMA_LIST_CDP_FASTMODE (BIT(10))
> +/* CAPS register bitmaps */
> +#define DMA_CAPS_SGLIST_SUPPORT (BIT(20))
> +
> +#define DMA_LIST_DESC_PAUSE (BIT(0))
> +#define DMA_LIST_DESC_SRC_VALID (BIT(24))
> +#define DMA_LIST_DESC_DST_VALID (BIT(26))
> +#define DMA_LIST_DESC_BLK_END (BIT(28))
> +
> #define OMAP_DMA_ACTIVE 0x01
> #define OMAP2_DMA_CSR_CLEAR_MASK 0xffe
>
> #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
> +#define OMAP_DMA_INVALID_FRAME_COUNT (0xffff)
> +#define OMAP_DMA_INVALID_ELEM_COUNT (0xffffff)
> +#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER (0xfffffffc)
>
> static int enable_1510_mode;
> +static int dma_caps0_status;
> +
> +struct omap_dma_list_config_params {
> + unsigned int num_elem;
> + struct omap_dma_sglist_node *sghead;
> + dma_addr_t sgheadphy;
> + unsigned int pausenode;
> +};
>
> static struct omap_dma_global_context_registers {
> u32 dma_irqenable_l0;
> @@ -74,9 +102,10 @@ struct omap_dma_lch {
> int next_linked_ch;
> int state;
> int chain_id;
> -
> int status;
> + struct omap_dma_list_config_params list_config;
> #endif
> +
> long flags;
> };
>
> @@ -214,6 +243,76 @@ static void clear_lch_regs(int lch)
> __raw_writew(0, lch_base + i);
> }
>
> +static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node,
> + int value)
> +{
> + node->num_of_elem |= ((value) << 29);
> +}
> +
> +static void omap_set_dma_sglist_pausebit(
> + struct omap_dma_list_config_params *lcfg, int nelem, int set)
> +{
> + struct omap_dma_sglist_node *sgn = lcfg->sghead;
> +
> + if (nelem > 0 && nelem < lcfg->num_elem) {
> + lcfg->pausenode = nelem;
> + sgn += nelem;
> +
> + if (set)
> + sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
> + else
> + sgn->next_desc_add_ptr &= ~(DMA_LIST_DESC_PAUSE);
> + }
> +}
> +
> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
> + dma_addr_t phyaddr, int nelem)
> +{
> + struct omap_dma_sglist_node *sgcurr, *sgprev;
> + dma_addr_t elem_paddr = phyaddr;
> +
> + for (sgprev = sghead;
> + sgprev < sghead + nelem;
> + sgprev++) {
> +
> + sgcurr = sgprev + 1;
> + sgprev->next = sgcurr;
> + elem_paddr += (int)sizeof(*sgcurr);
> + sgprev->next_desc_add_ptr = elem_paddr;
> +
> + switch (sgcurr->desc_type) {
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
> + omap_dma_list_set_ntype(sgprev, 1);
> + break;
> +
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
> + /* intentional no break */
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
> + omap_dma_list_set_ntype(sgprev, 2);
> + break;
> +
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
> + /* intentional no break */
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
> + omap_dma_list_set_ntype(sgprev, 3);
> + break;
> +
> + default:
> + return -EINVAL;
> +
> + }
Are we supporting all the descriptor types. I think only type2a is
supported. In that case please add FIXME, or WARN message here.
> + if (sgcurr->flags & OMAP_DMA_LIST_SRC_VALID)
> + sgprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID;
> + if (sgcurr->flags & OMAP_DMA_LIST_DST_VALID)
> + sgprev->num_of_elem |= DMA_LIST_DESC_DST_VALID;
> + if (sgcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END)
> + sgprev->num_of_elem |= DMA_LIST_DESC_BLK_END;
> + }
> + sgprev--;
> + sgprev->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER;
> + return 0;
> +}
> +
> void omap_set_dma_priority(int lch, int dst_port, int priority)
> {
> unsigned long reg;
> @@ -825,6 +924,7 @@ void omap_free_dma(int lch)
> /* Make sure the DMA transfer is stopped. */
> dma_write(0, CCR(lch));
> omap_clear_dma(lch);
> + omap_clear_dma_sglist_mode(lch);
> }
>
> spin_lock_irqsave(&dma_chan_lock, flags);
> @@ -1818,6 +1918,192 @@ int omap_get_dma_chain_src_pos(int chain_id)
> EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
> #endif /* ifndef CONFIG_ARCH_OMAP1 */
>
> +int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams,
> + dma_addr_t padd, int nelem, struct omap_dma_channel_params *chparams)
> +{
> + struct omap_dma_list_config_params *lcfg;
> + int l = DMA_LIST_CDP_LISTMODE; /* Enable Linked list mode in CDP */
> +
> + if ((dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT) == 0) {
> + printk(KERN_ERR "omap DMA: sglist feature not supported\n");
> + return -EPERM;
> + }
> + if (dma_chan[lch].flags & OMAP_DMA_ACTIVE) {
> + printk(KERN_ERR "omap DMA: configuring active DMA channel\n");
> + return -EPERM;
> + }
> +
> + if (padd == 0) {
> + printk(KERN_ERR "omap DMA: sglist invalid dma_addr\n");
> + return -EINVAL;
> + }
> + lcfg = &dma_chan[lch].list_config;
> +
> + lcfg->sghead = sgparams;
> + lcfg->num_elem = nelem;
> + lcfg->sgheadphy = padd;
> + lcfg->pausenode = -1;
> +
> +
> + if (NULL == chparams)
Minute point really. Better readability "ch_params"
> + l |= DMA_LIST_CDP_FASTMODE;
> + else
> + omap_set_dma_params(lch, chparams);
> +
> + dma_write(l, CDP(lch));
> + dma_write(0, CCDN(lch)); /* Reset List index numbering */
> + /* Initialize frame and element counters to invalid values */
> + dma_write(OMAP_DMA_INVALID_FRAME_COUNT, CCFN(lch));
> + dma_write(OMAP_DMA_INVALID_ELEM_COUNT, CCEN(lch));
> +
> + return dma_sglist_set_phy_params(sgparams, lcfg->sgheadphy, nelem);
> +
> +}
> +EXPORT_SYMBOL(omap_set_dma_sglist_mode);
> +
> +void omap_clear_dma_sglist_mode(int lch)
> +{
> + /* Clear entire CDP which is related to sglist handling */
> + dma_write(0, CDP(lch));
> + dma_write(0, CCDN(lch));
> + /**
> + * Put back the original enabled irqs, which
> + * could have been overwritten by type 1 or type 2
> + * descriptors
> + */
> + dma_write(dma_chan[lch].enabled_irqs, CICR(lch));
> + return;
> +}
> +EXPORT_SYMBOL(omap_clear_dma_sglist_mode);
> +
> +int omap_start_dma_sglist_transfers(int lch, int pauseafter)
> +{
> + struct omap_dma_list_config_params *lcfg;
> + struct omap_dma_sglist_node *sgn;
> + unsigned int l, type_id;
> +
> + lcfg = &dma_chan[lch].list_config;
> + sgn = lcfg->sghead;
> +
> + lcfg->pausenode = 0;
> + omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
> +
> + /* Program the head descriptor's properties into CDP */
> + switch (lcfg->sghead->desc_type) {
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
> + type_id = DMA_LIST_CDP_TYPE1;
> + break;
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
> + type_id = DMA_LIST_CDP_TYPE2;
> + break;
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
> + type_id = DMA_LIST_CDP_TYPE3;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + l = dma_read(CDP(lch));
> + l |= type_id;
> + if (lcfg->sghead->flags & OMAP_DMA_LIST_SRC_VALID)
> + l |= DMA_LIST_CDP_SRC_VALID;
> + if (lcfg->sghead->flags & OMAP_DMA_LIST_DST_VALID)
> + l |= DMA_LIST_CDP_DST_VALID;
> +
> + dma_write(l, CDP(lch));
> + dma_write((lcfg->sgheadphy), CNDP(lch));
> + /**
> + * Barrier needed as writes to the
> + * descriptor memory needs to be flushed
> + * before it's used by DMA controller
> + */
Little bit of re-wording if you can.
Also you don't wanted the double **
/*
* Memory barrier is needed because data may still be
* in the write buffer. The barrier drains write buffers and
* ensures that DMA sees correct descriptors
*/
> + wmb();
> + omap_start_dma(lch);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(omap_start_dma_sglist_transfers);
> +
> +int omap_resume_dma_sglist_transfers(int lch, int pauseafter)
> +{
> + struct omap_dma_list_config_params *lcfg;
> + struct omap_dma_sglist_node *sgn;
> + int l, sys_cf;
> +
> + lcfg = &dma_chan[lch].list_config;
> + sgn = lcfg->sghead;
> +
> + /* Maintain the pause state in descriptor */
> + omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0);
> + omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
> +
> + /**
> + * Barrier needed as writes to the
> + * descriptor memory needs to be flushed
> + * before it's used by DMA controller
> + */
Description change if possible
> + wmb();
> +
> + /* Errata i557 - pausebit should be cleared in no standby mode */
This should have been
> + sys_cf = dma_read(OCP_SYSCONFIG);
> + l = sys_cf;
> + /* Middle mode reg set no Standby */
> + l &= ~(BIT(12) | BIT(13));
> + dma_write(l, OCP_SYSCONFIG);
> +
> + /* Clear pause bit in CDP */
> + l = dma_read(CDP(lch));
> + l &= ~(DMA_LIST_CDP_PAUSEMODE);
> + dma_write(l, CDP(lch));
> +
> + omap_start_dma(lch);
> +
> + /* Errata i557 - put in the old value */
> + dma_write(sys_cf, OCP_SYSCONFIG);
> + return 0;
> +}
> +EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
> +
> +void omap_release_dma_sglist(int lch)
> +{
> + omap_clear_dma_sglist_mode(lch);
> + omap_free_dma(lch);
> +
> + return;
> +}
> +EXPORT_SYMBOL(omap_release_dma_sglist);
> +
> +int omap_get_completed_sglist_nodes(int lch)
> +{
> + int list_count;
> +
> + list_count = dma_read(CCDN(lch));
> + return list_count & 0xffff; /* only 16 LSB bits are valid */
> +}
> +EXPORT_SYMBOL(omap_get_completed_sglist_nodes);
> +
> +int omap_dma_sglist_is_paused(int lch)
> +{
> + int list_state;
> + list_state = dma_read(CDP(lch));
> + return (list_state & DMA_LIST_CDP_PAUSEMODE) ? 1 : 0;
> +}
> +EXPORT_SYMBOL(omap_dma_sglist_is_paused);
> +
> +void omap_dma_set_sglist_fastmode(int lch, int fastmode)
> +{
> + int l = dma_read(CDP(lch));
> +
> + if (fastmode)
> + l |= DMA_LIST_CDP_FASTMODE;
> + else
> + l &= ~(DMA_LIST_CDP_FASTMODE);
> + dma_write(l, CDP(lch));
> +}
> +EXPORT_SYMBOL(omap_dma_set_sglist_fastmode);
> +
> /*----------------------------------------------------------------------------*/
>
> #ifdef CONFIG_ARCH_OMAP1
> @@ -2066,6 +2352,7 @@ static int __init omap_init_dma(void)
> r = -ENOMEM;
> goto out_free;
> }
> + dma_caps0_status = dma_read(CAPS_0);
> }
>
> if (cpu_is_omap15xx()) {
> diff --git a/arch/arm/plat-omap/include/plat/dma.h
> b/arch/arm/plat-omap/include/plat/dma.h
> index 02232ca..7490df9 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -115,8 +115,12 @@
> #define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22)
> #define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24)
> #define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */
> +#define OMAP1_DMA_COLOR(n) 0
> #define OMAP1_DMA_CCEN(n) 0
> #define OMAP1_DMA_CCFN(n) 0
> +#define OMAP1_DMA_CDP(n) 0
> +#define OMAP1_DMA_CNDP(n) 0
> +#define OMAP1_DMA_CCDN(n) 0
>
> /* Channel specific registers only on omap2 */
> #define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c)
> @@ -135,6 +139,8 @@
> #define OMAP1_DMA_IRQSTATUS_L0 0
> #define OMAP1_DMA_IRQENABLE_L0 0
> #define OMAP1_DMA_OCP_SYSCONFIG 0
> +#define OMAP1_DMA_CAPS_0 0
> +
> #define OMAP_DMA4_HW_ID 0
> #define OMAP_DMA4_CAPS_0_L 0
> #define OMAP_DMA4_CAPS_0_U 0
> @@ -463,6 +469,83 @@ struct omap_dma_channel_params {
> #endif
> };
>
> +struct omap_dma_sglist_type1_params {
> + u32 src_addr;
> + u32 dst_addr;
> + u16 cfn_fn;
> + u16 cicr;
> + u16 dst_elem_idx;
> + u16 src_elem_idx;
> + u32 dst_frame_idx_or_pkt_size;
> + u32 src_frame_idx_or_pkt_size;
> + u32 color;
> + u32 csdp;
> + u32 clnk_ctrl;
> + u32 ccr;
> +};
> +
> +struct omap_dma_sglist_type2a_params {
> + u32 src_addr;
> + u32 dst_addr;
> + u16 cfn_fn;
> + u16 cicr;
> + u16 dst_elem_idx;
> + u16 src_elem_idx;
> + u32 dst_frame_idx_or_pkt_size;
> + u32 src_frame_idx_or_pkt_size;
> +};
> +
> +struct omap_dma_sglist_type2b_params {
> + u32 src_or_dest_addr;
> + u16 cfn_fn;
> + u16 cicr;
> + u16 dst_elem_idx;
> + u16 src_elem_idx;
> + u32 dst_frame_idx_or_pkt_size;
> + u32 src_frame_idx_or_pkt_size;
> +};
> +
> +struct omap_dma_sglist_type3a_params {
> + u32 src_addr;
> + u32 dst_addr;
> +};
> +
> +struct omap_dma_sglist_type3b_params {
> + u32 src_or_dest_addr;
> +};
> +
> +enum omap_dma_sglist_descriptor_select {
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b,
> +};
> +
> +union omap_dma_sglist_node_type{
> + struct omap_dma_sglist_type1_params t1;
> + struct omap_dma_sglist_type2a_params t2a;
> + struct omap_dma_sglist_type2b_params t2b;
> + struct omap_dma_sglist_type3a_params t3a;
> + struct omap_dma_sglist_type3b_params t3b;
> +};
> +
> +struct omap_dma_sglist_node {
> +
> + /* Common elements for all descriptors */
> + dma_addr_t next_desc_add_ptr;
> + u32 num_of_elem;
> + /* Type specific elements */
> + union omap_dma_sglist_node_type sg_node;
> + /* Control fields */
> + unsigned short flags;
> + /* Fields that can be set in flags variable */
> + #define OMAP_DMA_LIST_SRC_VALID BIT(0)
> + #define OMAP_DMA_LIST_DST_VALID BIT(1)
> + #define OMAP_DMA_LIST_NOTIFY_BLOCK_END BIT(2)
> + enum omap_dma_sglist_descriptor_select desc_type;
> + struct omap_dma_sglist_node *next;
> +};
>
> extern void omap_set_dma_priority(int lch, int dst_port, int priority);
> extern int omap_request_dma(int dev_id, const char *dev_name,
> @@ -548,6 +631,93 @@ extern int omap_modify_dma_chain_params(int chain_id,
> extern int omap_dma_chain_status(int chain_id);
> #endif
>
> +/**
> + * omap_set_dma_sglist_mode() Switch channel to scatter gather mode
> + * @lch: Logical channel to switch to sglist mode
> + * @sghead: Contains the descriptor elements to be executed
> + * Should be allocated using dma_alloc_coherent
> + * @padd: The dma address of sghead, as returned by dma_alloc_coherent
> + * @nelem: Number of elements in sghead
> + * @chparams: DMA channel transfer parameters. Can be NULL
> + */
> +extern int omap_set_dma_sglist_mode(int lch,
> + struct omap_dma_sglist_node *sghead, dma_addr_t padd,
> + int nelem, struct omap_dma_channel_params *chparams);
> +
> +/**
> + * omap_clear_dma_sglist_mode() Switch from scatter gather mode
> + * to normal mode
> + * @lch: The logical channel to be switched to normal mode
> + *
> + * Switches the requested logical channel to normal mode
> + * from scatter gather mode
> + */
> +extern void omap_clear_dma_sglist_mode(int lch);
> +
> +/**
> + * omap_start_dma_sglist_transfers() Starts the sglist transfer
> + * @lch: logical channel on which sglist transfer to be started
> + * @pauseafter: index of the element on which to pause the transfer
> + * set to -1 if no pause is needed till end of transfer
> + *
> + * Start the dma transfer in list mode
> + * The index (in pauseafter) is absolute (from the head of the list)
> + * User should have previously called omap_set_dma_sglist_mode()
> + */
> +extern int omap_start_dma_sglist_transfers(int lch, int pauseafter);
> +
> +/**
> + * omap_resume_dma_sglist_transfers() Resumes a previously paused
> + * sglist transfer
> + * @lch: The logical channel to be resumed
> + * @pauseafter: The index of sglist to be paused again
> + * set to -1 if no pause is needed till end of transfer
> + *
> + * Resume the previously paused transfer
> + * The index (in pauseafter) is absolute (from the head of the list)
> + */
> +extern int omap_resume_dma_sglist_transfers(int lch, int pauseafter);
> +
> +/**
> + * omap_release_dma_sglist() Releases a previously requested
> + * DMA channel which is in sglist mode
> + * @lch: The logical channel to be released
> + */
> +extern void omap_release_dma_sglist(int lch);
> +
> +/**
> + * omap_get_completed_sglist_nodes() Returns a list of completed
> + * sglist nodes
> + * @lch: The logical on which the query is to be made
> + *
> + * Returns the number of completed elements in the linked list
> + * The value is transient if the API is invoked for an ongoing transfer
> + */
> +int omap_get_completed_sglist_nodes(int lch);
> +
> +/**
> + * omap_dma_sglist_is_paused() Query is the logical channel in
> + * sglist mode is paused or note
> + * @lch: The logical on which the query is to be made
> + *
> + * Returns non zero if the linked list is currently in pause state
> + */
> +int omap_dma_sglist_is_paused(int lch);
> +
> +/**
> + * omap_dma_set_sglist_fastmode() Set the sglist transfer to fastmode
> + * @lch: The logical channel which is to be changed to fastmode
> + * @fastmode: Set or clear the fastmode status
> + * 1 = set fastmode
> + * 0 = clear fastmode
> + *
> + * In fastmode, DMA register settings are updated from the first element
> + * of the linked list, before initiating the tranfer.
> + * In non-fastmode, the first element is used only after completing the
> + * transfer as already configured in the registers
> + */
> +void omap_dma_set_sglist_fastmode(int lch, int fastmode);
> +
> #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
> #include <mach/lcd_dma.h>
> #else
> --
> 1.6.3.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-04-29 17:35 [PATCH v8 1/2] sDMA: descriptor autoloading feature Venkatraman S
2010-05-05 9:32 ` Shilimkar, Santosh
@ 2010-05-05 10:05 ` Adrian Hunter
2010-05-05 11:51 ` Venkatraman S
1 sibling, 1 reply; 9+ messages in thread
From: Adrian Hunter @ 2010-05-05 10:05 UTC (permalink / raw)
To: linux-arm-kernel
Venkatraman S wrote:
>>From d46f8a00728cc6c1fbdfce69435759c8cc49f25c Mon Sep 17 00:00:00 2001
> From: Venkatraman S <svenkatr@ti.com>
> Date: Thu, 29 Apr 2010 22:34:04 +0530
> Subject: [PATCH 1/2] sDMA: descriptor autoloading feature
>
> Add sDMA driver support for descriptor autoloading feature.
> Descriptor autoloading is OMAP sDMA v5 hardware capability that can
> be exploited for scatter gather
> scenarios, currently available in OMAP3630 and OMAP4430.
>
> The feature works as described below.
> 1) A sDMA channel is programmed to be in 'linked list' mode.
> 2) The client (sDMA user) provides a list of descriptors in a linked
> list format.
> 3) Each of the 'descriptor' (element in the linked list) contains an
> updated set of DMA
> configuration register values.
> 4) Client starts DMA transfer.
> 5) sDMA controller loads the first element to its register
> configuration memory and executes the
> transfer.
> 6) After completion, loads the next element (in linked list) to
> configuration memory and executes
> the transfer, without MCU intervention.
> 7) Interrupt is generated after all transfers are completed; this
> can be configured to be done
> differently.
>
> Configurations and additional features
> 1) Fast mode & non-fast mode
> Fast mode/non-fast decides on how the first transfer begins.
> In non-fast mode, the first
> element in the linked list is loaded only after completing the
> transfer according to the
> configurations already in the sDMA channel registers. In fast mode,
> the loading of the first
> element precedes the transfer.
>
> 2) Pause / resume of transfers
> A transfer can be paused after a descriptor set has been loaded,
> provided the 'pause
> bit' is set in the linked list element.
> An ongoing transfer cannot be paused. If the 'pause bit' is set,
> transfer is not
> started after loading the register set from memory.
> Such a transfer can be resumed later.
>
> 3) Descriptor types
> 3 possible configurations of descriptors (initialized as linked list elements)
> are possible. Type 1 provides the maximum flexibility, which contains most
> register definitions of a DMA logical channel. Fewer options are
> present in type
> 2. Type 3 can just modify source/destinations address of transfers. In all
> transfers, unmodified registers settings are maintained for the next transfer.
>
> Patch provides options / API for
> 1) Setting up a descriptor loading for DMA channel for sg type transfers
> 2) configuration with linked list elements
> 3) Starting / pause and resume of the said transfers, query state
> 4) Clearing the sglist mode
>
> Signed-off-by: Venkatraman S <svenkatr@ti.com>
> CC: Adrian Hunter <adrian.hunter@nokia.com>
> CC: Madhusudhan C <madhu.cr@ti.com>
> CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
> CC: Tony Lindgren <tony@atomide.com>
> ---
> Changes from v7:
> * Added wmb() calls between descriptor data structure update and
> start/resume of transfer
> * Added proper commit log about the feature
>
> arch/arm/plat-omap/dma.c | 289 ++++++++++++++++++++++++++++++++-
> arch/arm/plat-omap/include/plat/dma.h | 170 +++++++++++++++++++
> 2 files changed, 458 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
> index f6c9bdc..d8d4df8 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -46,12 +46,40 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE,
> DMA_CH_STARTED,
> enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
> #endif
>
> +/* CDP Register bitmaps */
> +#define DMA_LIST_CDP_DST_VALID (BIT(0))
> +#define DMA_LIST_CDP_SRC_VALID (BIT(2))
> +#define DMA_LIST_CDP_TYPE1 (BIT(4))
> +#define DMA_LIST_CDP_TYPE2 (BIT(5))
> +#define DMA_LIST_CDP_TYPE3 (BIT(4) | BIT(5))
> +#define DMA_LIST_CDP_PAUSEMODE (BIT(7))
> +#define DMA_LIST_CDP_LISTMODE (BIT(8))
> +#define DMA_LIST_CDP_FASTMODE (BIT(10))
> +/* CAPS register bitmaps */
> +#define DMA_CAPS_SGLIST_SUPPORT (BIT(20))
> +
> +#define DMA_LIST_DESC_PAUSE (BIT(0))
> +#define DMA_LIST_DESC_SRC_VALID (BIT(24))
> +#define DMA_LIST_DESC_DST_VALID (BIT(26))
> +#define DMA_LIST_DESC_BLK_END (BIT(28))
> +
The () are not needed around BIT()
> #define OMAP_DMA_ACTIVE 0x01
> #define OMAP2_DMA_CSR_CLEAR_MASK 0xffe
>
> #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
> +#define OMAP_DMA_INVALID_FRAME_COUNT (0xffff)
> +#define OMAP_DMA_INVALID_ELEM_COUNT (0xffffff)
> +#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER (0xfffffffc)
The () are not needed around literals
>
> static int enable_1510_mode;
> +static int dma_caps0_status;
> +
> +struct omap_dma_list_config_params {
> + unsigned int num_elem;
> + struct omap_dma_sglist_node *sghead;
> + dma_addr_t sgheadphy;
> + unsigned int pausenode;
> +};
>
> static struct omap_dma_global_context_registers {
> u32 dma_irqenable_l0;
> @@ -74,9 +102,10 @@ struct omap_dma_lch {
> int next_linked_ch;
> int state;
> int chain_id;
> -
> int status;
> + struct omap_dma_list_config_params list_config;
> #endif
> +
> long flags;
> };
>
> @@ -214,6 +243,76 @@ static void clear_lch_regs(int lch)
> __raw_writew(0, lch_base + i);
> }
>
> +static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node,
> + int value)
> +{
> + node->num_of_elem |= ((value) << 29);
> +}
> +
> +static void omap_set_dma_sglist_pausebit(
> + struct omap_dma_list_config_params *lcfg, int nelem, int set)
> +{
> + struct omap_dma_sglist_node *sgn = lcfg->sghead;
> +
> + if (nelem > 0 && nelem < lcfg->num_elem) {
> + lcfg->pausenode = nelem;
> + sgn += nelem;
> +
> + if (set)
> + sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
> + else
> + sgn->next_desc_add_ptr &= ~(DMA_LIST_DESC_PAUSE);
> + }
> +}
> +
> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
> + dma_addr_t phyaddr, int nelem)
> +{
> + struct omap_dma_sglist_node *sgcurr, *sgprev;
> + dma_addr_t elem_paddr = phyaddr;
> +
> + for (sgprev = sghead;
> + sgprev < sghead + nelem;
> + sgprev++) {
> +
> + sgcurr = sgprev + 1;
> + sgprev->next = sgcurr;
> + elem_paddr += (int)sizeof(*sgcurr);
> + sgprev->next_desc_add_ptr = elem_paddr;
> +
> + switch (sgcurr->desc_type) {
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
> + omap_dma_list_set_ntype(sgprev, 1);
> + break;
> +
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
> + /* intentional no break */
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
> + omap_dma_list_set_ntype(sgprev, 2);
> + break;
> +
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
> + /* intentional no break */
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
> + omap_dma_list_set_ntype(sgprev, 3);
> + break;
> +
> + default:
> + return -EINVAL;
> +
> + }
> + if (sgcurr->flags & OMAP_DMA_LIST_SRC_VALID)
> + sgprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID;
> + if (sgcurr->flags & OMAP_DMA_LIST_DST_VALID)
> + sgprev->num_of_elem |= DMA_LIST_DESC_DST_VALID;
> + if (sgcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END)
> + sgprev->num_of_elem |= DMA_LIST_DESC_BLK_END;
> + }
> + sgprev--;
> + sgprev->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER;
> + return 0;
> +}
> +
> void omap_set_dma_priority(int lch, int dst_port, int priority)
> {
> unsigned long reg;
> @@ -825,6 +924,7 @@ void omap_free_dma(int lch)
> /* Make sure the DMA transfer is stopped. */
> dma_write(0, CCR(lch));
> omap_clear_dma(lch);
> + omap_clear_dma_sglist_mode(lch);
> }
>
> spin_lock_irqsave(&dma_chan_lock, flags);
> @@ -1818,6 +1918,192 @@ int omap_get_dma_chain_src_pos(int chain_id)
> EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
> #endif /* ifndef CONFIG_ARCH_OMAP1 */
>
> +int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams,
> + dma_addr_t padd, int nelem, struct omap_dma_channel_params *chparams)
> +{
> + struct omap_dma_list_config_params *lcfg;
> + int l = DMA_LIST_CDP_LISTMODE; /* Enable Linked list mode in CDP */
> +
> + if ((dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT) == 0) {
> + printk(KERN_ERR "omap DMA: sglist feature not supported\n");
> + return -EPERM;
> + }
> + if (dma_chan[lch].flags & OMAP_DMA_ACTIVE) {
> + printk(KERN_ERR "omap DMA: configuring active DMA channel\n");
> + return -EPERM;
> + }
> +
> + if (padd == 0) {
> + printk(KERN_ERR "omap DMA: sglist invalid dma_addr\n");
> + return -EINVAL;
> + }
> + lcfg = &dma_chan[lch].list_config;
> +
> + lcfg->sghead = sgparams;
> + lcfg->num_elem = nelem;
> + lcfg->sgheadphy = padd;
> + lcfg->pausenode = -1;
> +
> +
> + if (NULL == chparams)
> + l |= DMA_LIST_CDP_FASTMODE;
> + else
> + omap_set_dma_params(lch, chparams);
> +
> + dma_write(l, CDP(lch));
> + dma_write(0, CCDN(lch)); /* Reset List index numbering */
> + /* Initialize frame and element counters to invalid values */
> + dma_write(OMAP_DMA_INVALID_FRAME_COUNT, CCFN(lch));
> + dma_write(OMAP_DMA_INVALID_ELEM_COUNT, CCEN(lch));
> +
> + return dma_sglist_set_phy_params(sgparams, lcfg->sgheadphy, nelem);
> +
> +}
> +EXPORT_SYMBOL(omap_set_dma_sglist_mode);
> +
> +void omap_clear_dma_sglist_mode(int lch)
> +{
> + /* Clear entire CDP which is related to sglist handling */
> + dma_write(0, CDP(lch));
> + dma_write(0, CCDN(lch));
> + /**
> + * Put back the original enabled irqs, which
> + * could have been overwritten by type 1 or type 2
> + * descriptors
> + */
> + dma_write(dma_chan[lch].enabled_irqs, CICR(lch));
> + return;
> +}
> +EXPORT_SYMBOL(omap_clear_dma_sglist_mode);
> +
> +int omap_start_dma_sglist_transfers(int lch, int pauseafter)
> +{
> + struct omap_dma_list_config_params *lcfg;
> + struct omap_dma_sglist_node *sgn;
> + unsigned int l, type_id;
> +
> + lcfg = &dma_chan[lch].list_config;
> + sgn = lcfg->sghead;
> +
> + lcfg->pausenode = 0;
> + omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
> +
> + /* Program the head descriptor's properties into CDP */
> + switch (lcfg->sghead->desc_type) {
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
> + type_id = DMA_LIST_CDP_TYPE1;
> + break;
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
> + type_id = DMA_LIST_CDP_TYPE2;
> + break;
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
> + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
> + type_id = DMA_LIST_CDP_TYPE3;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + l = dma_read(CDP(lch));
> + l |= type_id;
> + if (lcfg->sghead->flags & OMAP_DMA_LIST_SRC_VALID)
> + l |= DMA_LIST_CDP_SRC_VALID;
> + if (lcfg->sghead->flags & OMAP_DMA_LIST_DST_VALID)
> + l |= DMA_LIST_CDP_DST_VALID;
> +
> + dma_write(l, CDP(lch));
> + dma_write((lcfg->sgheadphy), CNDP(lch));
> + /**
> + * Barrier needed as writes to the
> + * descriptor memory needs to be flushed
> + * before it's used by DMA controller
> + */
> + wmb();
> + omap_start_dma(lch);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(omap_start_dma_sglist_transfers);
> +
> +int omap_resume_dma_sglist_transfers(int lch, int pauseafter)
> +{
> + struct omap_dma_list_config_params *lcfg;
> + struct omap_dma_sglist_node *sgn;
> + int l, sys_cf;
> +
> + lcfg = &dma_chan[lch].list_config;
> + sgn = lcfg->sghead;
> +
> + /* Maintain the pause state in descriptor */
> + omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0);
> + omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
> +
> + /**
> + * Barrier needed as writes to the
> + * descriptor memory needs to be flushed
> + * before it's used by DMA controller
> + */
> + wmb();
> +
> + /* Errata i557 - pausebit should be cleared in no standby mode */
> + sys_cf = dma_read(OCP_SYSCONFIG);
> + l = sys_cf;
> + /* Middle mode reg set no Standby */
> + l &= ~(BIT(12) | BIT(13));
> + dma_write(l, OCP_SYSCONFIG);
> +
> + /* Clear pause bit in CDP */
> + l = dma_read(CDP(lch));
> + l &= ~(DMA_LIST_CDP_PAUSEMODE);
> + dma_write(l, CDP(lch));
> +
> + omap_start_dma(lch);
> +
> + /* Errata i557 - put in the old value */
> + dma_write(sys_cf, OCP_SYSCONFIG);
> + return 0;
> +}
> +EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
> +
> +void omap_release_dma_sglist(int lch)
> +{
> + omap_clear_dma_sglist_mode(lch);
> + omap_free_dma(lch);
> +
> + return;
> +}
> +EXPORT_SYMBOL(omap_release_dma_sglist);
> +
> +int omap_get_completed_sglist_nodes(int lch)
> +{
> + int list_count;
> +
> + list_count = dma_read(CCDN(lch));
> + return list_count & 0xffff; /* only 16 LSB bits are valid */
> +}
> +EXPORT_SYMBOL(omap_get_completed_sglist_nodes);
> +
> +int omap_dma_sglist_is_paused(int lch)
> +{
> + int list_state;
> + list_state = dma_read(CDP(lch));
> + return (list_state & DMA_LIST_CDP_PAUSEMODE) ? 1 : 0;
> +}
> +EXPORT_SYMBOL(omap_dma_sglist_is_paused);
> +
> +void omap_dma_set_sglist_fastmode(int lch, int fastmode)
> +{
> + int l = dma_read(CDP(lch));
> +
> + if (fastmode)
> + l |= DMA_LIST_CDP_FASTMODE;
> + else
> + l &= ~(DMA_LIST_CDP_FASTMODE);
> + dma_write(l, CDP(lch));
> +}
> +EXPORT_SYMBOL(omap_dma_set_sglist_fastmode);
> +
> /*----------------------------------------------------------------------------*/
>
> #ifdef CONFIG_ARCH_OMAP1
> @@ -2066,6 +2352,7 @@ static int __init omap_init_dma(void)
> r = -ENOMEM;
> goto out_free;
> }
> + dma_caps0_status = dma_read(CAPS_0);
> }
>
> if (cpu_is_omap15xx()) {
> diff --git a/arch/arm/plat-omap/include/plat/dma.h
> b/arch/arm/plat-omap/include/plat/dma.h
> index 02232ca..7490df9 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -115,8 +115,12 @@
> #define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22)
> #define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24)
> #define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */
> +#define OMAP1_DMA_COLOR(n) 0
> #define OMAP1_DMA_CCEN(n) 0
> #define OMAP1_DMA_CCFN(n) 0
> +#define OMAP1_DMA_CDP(n) 0
> +#define OMAP1_DMA_CNDP(n) 0
> +#define OMAP1_DMA_CCDN(n) 0
>
> /* Channel specific registers only on omap2 */
> #define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c)
> @@ -135,6 +139,8 @@
> #define OMAP1_DMA_IRQSTATUS_L0 0
> #define OMAP1_DMA_IRQENABLE_L0 0
> #define OMAP1_DMA_OCP_SYSCONFIG 0
> +#define OMAP1_DMA_CAPS_0 0
> +
> #define OMAP_DMA4_HW_ID 0
> #define OMAP_DMA4_CAPS_0_L 0
> #define OMAP_DMA4_CAPS_0_U 0
> @@ -463,6 +469,83 @@ struct omap_dma_channel_params {
> #endif
> };
>
> +struct omap_dma_sglist_type1_params {
> + u32 src_addr;
> + u32 dst_addr;
> + u16 cfn_fn;
> + u16 cicr;
> + u16 dst_elem_idx;
> + u16 src_elem_idx;
> + u32 dst_frame_idx_or_pkt_size;
> + u32 src_frame_idx_or_pkt_size;
> + u32 color;
> + u32 csdp;
> + u32 clnk_ctrl;
> + u32 ccr;
> +};
> +
> +struct omap_dma_sglist_type2a_params {
> + u32 src_addr;
> + u32 dst_addr;
> + u16 cfn_fn;
> + u16 cicr;
> + u16 dst_elem_idx;
> + u16 src_elem_idx;
> + u32 dst_frame_idx_or_pkt_size;
> + u32 src_frame_idx_or_pkt_size;
> +};
> +
> +struct omap_dma_sglist_type2b_params {
> + u32 src_or_dest_addr;
> + u16 cfn_fn;
> + u16 cicr;
> + u16 dst_elem_idx;
> + u16 src_elem_idx;
> + u32 dst_frame_idx_or_pkt_size;
> + u32 src_frame_idx_or_pkt_size;
> +};
> +
> +struct omap_dma_sglist_type3a_params {
> + u32 src_addr;
> + u32 dst_addr;
> +};
> +
> +struct omap_dma_sglist_type3b_params {
> + u32 src_or_dest_addr;
> +};
> +
> +enum omap_dma_sglist_descriptor_select {
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a,
> + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b,
> +};
> +
> +union omap_dma_sglist_node_type{
> + struct omap_dma_sglist_type1_params t1;
> + struct omap_dma_sglist_type2a_params t2a;
> + struct omap_dma_sglist_type2b_params t2b;
> + struct omap_dma_sglist_type3a_params t3a;
> + struct omap_dma_sglist_type3b_params t3b;
> +};
> +
> +struct omap_dma_sglist_node {
> +
> + /* Common elements for all descriptors */
> + dma_addr_t next_desc_add_ptr;
> + u32 num_of_elem;
> + /* Type specific elements */
> + union omap_dma_sglist_node_type sg_node;
> + /* Control fields */
> + unsigned short flags;
> + /* Fields that can be set in flags variable */
> + #define OMAP_DMA_LIST_SRC_VALID BIT(0)
> + #define OMAP_DMA_LIST_DST_VALID BIT(1)
> + #define OMAP_DMA_LIST_NOTIFY_BLOCK_END BIT(2)
> + enum omap_dma_sglist_descriptor_select desc_type;
> + struct omap_dma_sglist_node *next;
> +};
>
> extern void omap_set_dma_priority(int lch, int dst_port, int priority);
> extern int omap_request_dma(int dev_id, const char *dev_name,
> @@ -548,6 +631,93 @@ extern int omap_modify_dma_chain_params(int chain_id,
> extern int omap_dma_chain_status(int chain_id);
> #endif
>
> +/**
> + * omap_set_dma_sglist_mode() Switch channel to scatter gather mode
> + * @lch: Logical channel to switch to sglist mode
> + * @sghead: Contains the descriptor elements to be executed
> + * Should be allocated using dma_alloc_coherent
> + * @padd: The dma address of sghead, as returned by dma_alloc_coherent
> + * @nelem: Number of elements in sghead
> + * @chparams: DMA channel transfer parameters. Can be NULL
> + */
> +extern int omap_set_dma_sglist_mode(int lch,
> + struct omap_dma_sglist_node *sghead, dma_addr_t padd,
> + int nelem, struct omap_dma_channel_params *chparams);
> +
> +/**
> + * omap_clear_dma_sglist_mode() Switch from scatter gather mode
> + * to normal mode
> + * @lch: The logical channel to be switched to normal mode
> + *
> + * Switches the requested logical channel to normal mode
> + * from scatter gather mode
> + */
> +extern void omap_clear_dma_sglist_mode(int lch);
> +
> +/**
> + * omap_start_dma_sglist_transfers() Starts the sglist transfer
> + * @lch: logical channel on which sglist transfer to be started
> + * @pauseafter: index of the element on which to pause the transfer
> + * set to -1 if no pause is needed till end of transfer
> + *
> + * Start the dma transfer in list mode
> + * The index (in pauseafter) is absolute (from the head of the list)
> + * User should have previously called omap_set_dma_sglist_mode()
> + */
> +extern int omap_start_dma_sglist_transfers(int lch, int pauseafter);
> +
> +/**
> + * omap_resume_dma_sglist_transfers() Resumes a previously paused
> + * sglist transfer
> + * @lch: The logical channel to be resumed
> + * @pauseafter: The index of sglist to be paused again
> + * set to -1 if no pause is needed till end of transfer
> + *
> + * Resume the previously paused transfer
> + * The index (in pauseafter) is absolute (from the head of the list)
> + */
> +extern int omap_resume_dma_sglist_transfers(int lch, int pauseafter);
> +
> +/**
> + * omap_release_dma_sglist() Releases a previously requested
> + * DMA channel which is in sglist mode
> + * @lch: The logical channel to be released
> + */
> +extern void omap_release_dma_sglist(int lch);
> +
> +/**
> + * omap_get_completed_sglist_nodes() Returns a list of completed
> + * sglist nodes
> + * @lch: The logical on which the query is to be made
> + *
> + * Returns the number of completed elements in the linked list
> + * The value is transient if the API is invoked for an ongoing transfer
> + */
> +int omap_get_completed_sglist_nodes(int lch);
> +
> +/**
> + * omap_dma_sglist_is_paused() Query is the logical channel in
> + * sglist mode is paused or note
> + * @lch: The logical on which the query is to be made
> + *
> + * Returns non zero if the linked list is currently in pause state
> + */
> +int omap_dma_sglist_is_paused(int lch);
> +
> +/**
> + * omap_dma_set_sglist_fastmode() Set the sglist transfer to fastmode
> + * @lch: The logical channel which is to be changed to fastmode
> + * @fastmode: Set or clear the fastmode status
> + * 1 = set fastmode
> + * 0 = clear fastmode
> + *
> + * In fastmode, DMA register settings are updated from the first element
> + * of the linked list, before initiating the tranfer.
> + * In non-fastmode, the first element is used only after completing the
> + * transfer as already configured in the registers
> + */
> +void omap_dma_set_sglist_fastmode(int lch, int fastmode);
> +
> #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
> #include <mach/lcd_dma.h>
> #else
> --
> 1.6.3.3
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-05-05 9:32 ` Shilimkar, Santosh
@ 2010-05-05 11:50 ` Venkatraman S
2010-05-05 12:01 ` Shilimkar, Santosh
0 siblings, 1 reply; 9+ messages in thread
From: Venkatraman S @ 2010-05-05 11:50 UTC (permalink / raw)
To: linux-arm-kernel
[Long sections have been trimmed to the context of the discussion]
On Wed, May 5, 2010 at 3:02 PM, Shilimkar, Santosh
<santosh.shilimkar@ti.com> wrote:
>> -----Original Message-----
>> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
>> + ? ? ? ? ? ? dma_addr_t phyaddr, int nelem)
>> +{
>> + ? ? struct omap_dma_sglist_node *sgcurr, *sgprev;
>> + ? ? dma_addr_t elem_paddr = phyaddr;
>> +
>> + ? ? for (sgprev = sghead;
>> + ? ? ? ? ? ? sgprev < sghead + nelem;
>> + ? ? ? ? ? ? sgprev++) {
>> +
>> + ? ? ? ? ? ? sgcurr = sgprev + 1;
>> + ? ? ? ? ? ? sgprev->next = sgcurr;
>> + ? ? ? ? ? ? elem_paddr += (int)sizeof(*sgcurr);
>> + ? ? ? ? ? ? sgprev->next_desc_add_ptr = elem_paddr;
>> +
>> + ? ? ? ? ? ? switch (sgcurr->desc_type) {
>> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
>> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 1);
>> + ? ? ? ? ? ? ? ? ? ? break;
>> +
>> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
>> + ? ? ? ? ? ? /* intentional no break */
>> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
>> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 2);
>> + ? ? ? ? ? ? ? ? ? ? break;
>> +
>> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
>> + ? ? ? ? ? ? ? ? ? ? /* intentional no break */
>> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
>> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 3);
>> + ? ? ? ? ? ? ? ? ? ? break;
>> +
>> + ? ? ? ? ? ? default:
>> + ? ? ? ? ? ? ? ? ? ? return -EINVAL;
>> +
>> + ? ? ? ? ? ? }
> Are we supporting all the descriptor types. I think only type2a is
> supported. In that case please add FIXME, or WARN message here.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-05-05 10:05 ` Adrian Hunter
@ 2010-05-05 11:51 ` Venkatraman S
0 siblings, 0 replies; 9+ messages in thread
From: Venkatraman S @ 2010-05-05 11:51 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, May 5, 2010 at 3:35 PM, Adrian Hunter <adrian.hunter@nokia.com> wrote:
> Venkatraman S wrote:
>>>
>>> From d46f8a00728cc6c1fbdfce69435759c8cc49f25c Mon Sep 17 00:00:00 2001
>>
>> From: Venkatraman S <svenkatr@ti.com>
>> Date: Thu, 29 Apr 2010 22:34:04 +0530
>> Subject: [PATCH 1/2] sDMA: descriptor autoloading feature
>>
>> Add sDMA driver support for descriptor autoloading feature.
>> ?Descriptor autoloading is OMAP sDMA v5 hardware capability that can
>> be exploited for scatter gather
>> ?scenarios, currently available in OMAP3630 and OMAP4430.
>>
>> ?The feature works as described below.
>> ?1) A sDMA channel is programmed to be in 'linked list' mode.
>> ?2) The client (sDMA user) provides a list of descriptors in a linked
>> list format.
>> ?3) Each of the 'descriptor' (element in the linked list) contains an
>> updated set of DMA
>> ?configuration register values.
>> ?4) Client starts DMA transfer.
>> ?5) sDMA controller loads the first element to its register
>> configuration memory and executes the
>> ?transfer.
>> ?6) After completion, loads the next element (in linked list) to
>> configuration memory and executes
>> ?the transfer, without MCU intervention.
>> ?7) Interrupt is generated after all transfers are completed; this
>> can be configured to be done
>> ?differently.
>>
>> ?Configurations and additional features
>> ?1) Fast mode & non-fast mode
>> ? ? ? ?Fast mode/non-fast decides on how the first transfer begins.
>> In non-fast mode, the first
>> ? ? ? ?element in the linked list is loaded only after completing the
>> transfer according to the
>> ? ? ? ?configurations already in the sDMA channel registers. In fast mode,
>> the loading of the first
>> ? ? ? ?element precedes the transfer.
>>
>> ?2) Pause / resume of transfers
>> ? ? ? ?A transfer can be paused after a descriptor set has been loaded,
>> provided the 'pause
>> ? ? ? ?bit' is set in the linked list element.
>> ? ? ? ?An ongoing transfer cannot be paused. If the 'pause bit' is set,
>> transfer is not
>> ? ? ? ?started after loading the register set from memory.
>> ? ? ? ?Such a transfer can be resumed later.
>>
>> ?3) Descriptor types
>> ? ? ? ?3 possible configurations of descriptors (initialized as linked
>> list elements)
>> ? ? ? ?are possible. Type 1 provides the maximum flexibility, which
>> contains most
>> ? ? ? ?register definitions of a DMA logical channel. Fewer options are
>> present in type
>> ? ? ? ?2. Type 3 can just modify source/destinations address of transfers.
>> In all
>> ? ? ? ?transfers, unmodified registers settings are maintained for the
>> next transfer.
>>
>> ? ? ? ?Patch provides options / API for
>> ? ? ? ? ? ?1) Setting up a descriptor loading for DMA channel for sg type
>> transfers
>> ? ? ? ? ? ?2) configuration with linked list elements
>> ? ? ? ? ? ?3) Starting / pause and resume of the said transfers, query
>> state
>> ? ? ? ? ? ?4) Clearing the sglist mode
>>
>> Signed-off-by: Venkatraman S <svenkatr@ti.com>
>> CC: Adrian Hunter <adrian.hunter@nokia.com>
>> CC: Madhusudhan C <madhu.cr@ti.com>
>> CC: Shilimkar Santosh <santosh.shilimkar@ti.com>
>> CC: Tony Lindgren <tony@atomide.com>
>> ---
>> ?Changes from v7:
>> ? * Added wmb() calls between descriptor data structure update and
>> start/resume of transfer
>> ? * Added proper commit log about the feature
>>
>> ?arch/arm/plat-omap/dma.c ? ? ? ? ? ? ?| ?289
>> ++++++++++++++++++++++++++++++++-
>> ?arch/arm/plat-omap/include/plat/dma.h | ?170 +++++++++++++++++++
>> ?2 files changed, 458 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
>> index f6c9bdc..d8d4df8 100644
>> --- a/arch/arm/plat-omap/dma.c
>> +++ b/arch/arm/plat-omap/dma.c
>> @@ -46,12 +46,40 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE,
>> DMA_CH_STARTED,
>> ?enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
>> ?#endif
>>
>> +/* CDP Register bitmaps */
>> +#define DMA_LIST_CDP_DST_VALID (BIT(0))
>> +#define DMA_LIST_CDP_SRC_VALID (BIT(2))
>> +#define DMA_LIST_CDP_TYPE1 ? ? (BIT(4))
>> +#define DMA_LIST_CDP_TYPE2 ? ? (BIT(5))
>> +#define DMA_LIST_CDP_TYPE3 ? ? (BIT(4) | BIT(5))
>> +#define DMA_LIST_CDP_PAUSEMODE (BIT(7))
>> +#define DMA_LIST_CDP_LISTMODE ?(BIT(8))
>> +#define DMA_LIST_CDP_FASTMODE ?(BIT(10))
>> +/* CAPS register bitmaps */
>> +#define DMA_CAPS_SGLIST_SUPPORT ? ? ? ?(BIT(20))
>> +
>> +#define DMA_LIST_DESC_PAUSE ? ?(BIT(0))
>> +#define DMA_LIST_DESC_SRC_VALID ? ? ? ?(BIT(24))
>> +#define DMA_LIST_DESC_DST_VALID ? ? ? ?(BIT(26))
>> +#define DMA_LIST_DESC_BLK_END ?(BIT(28))
>> +
>
> The () are not needed around BIT()
OK
>
>> ?#define OMAP_DMA_ACTIVE ? ? ? ? ? ? ? ? ? ? ? ?0x01
>> ?#define OMAP2_DMA_CSR_CLEAR_MASK ? ? ? 0xffe
>>
>> ?#define OMAP_FUNC_MUX_ARM_BASE ? ? ? ? (0xfffe1000 + 0xec)
>> +#define OMAP_DMA_INVALID_FRAME_COUNT ? (0xffff)
>> +#define OMAP_DMA_INVALID_ELEM_COUNT ? ?(0xffffff)
>> +#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER ? ?(0xfffffffc)
>
> The () are not needed around literals
>
OK
>>
>> ?static int enable_1510_mode;
>> +static int dma_caps0_status;
>> +
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-05-05 11:50 ` Venkatraman S
@ 2010-05-05 12:01 ` Shilimkar, Santosh
2010-05-05 16:25 ` Venkatraman S
0 siblings, 1 reply; 9+ messages in thread
From: Shilimkar, Santosh @ 2010-05-05 12:01 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
> Sent: Wednesday, May 05, 2010 5:20 PM
> To: Shilimkar, Santosh
> Cc: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren
> Subject: Re: [PATCH v8 1/2] sDMA: descriptor autoloading feature
>
> [Long sections have been trimmed to the context of the discussion]
> On Wed, May 5, 2010 at 3:02 PM, Shilimkar, Santosh
> <santosh.shilimkar@ti.com> wrote:
> >> -----Original Message-----
> >> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
> >> + ? ? ? ? ? ? dma_addr_t phyaddr, int nelem)
> >> +{
> >> + ? ? struct omap_dma_sglist_node *sgcurr, *sgprev;
> >> + ? ? dma_addr_t elem_paddr = phyaddr;
> >> +
> >> + ? ? for (sgprev = sghead;
> >> + ? ? ? ? ? ? sgprev < sghead + nelem;
> >> + ? ? ? ? ? ? sgprev++) {
> >> +
> >> + ? ? ? ? ? ? sgcurr = sgprev + 1;
> >> + ? ? ? ? ? ? sgprev->next = sgcurr;
> >> + ? ? ? ? ? ? elem_paddr += (int)sizeof(*sgcurr);
> >> + ? ? ? ? ? ? sgprev->next_desc_add_ptr = elem_paddr;
> >> +
> >> + ? ? ? ? ? ? switch (sgcurr->desc_type) {
> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 1);
> >> + ? ? ? ? ? ? ? ? ? ? break;
> >> +
> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
> >> + ? ? ? ? ? ? /* intentional no break */
> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 2);
> >> + ? ? ? ? ? ? ? ? ? ? break;
> >> +
> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
> >> + ? ? ? ? ? ? ? ? ? ? /* intentional no break */
> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 3);
> >> + ? ? ? ? ? ? ? ? ? ? break;
> >> +
> >> + ? ? ? ? ? ? default:
> >> + ? ? ? ? ? ? ? ? ? ? return -EINVAL;
> >> +
> >> + ? ? ? ? ? ? }
> > Are we supporting all the descriptor types. I think only type2a is
> > supported. In that case please add FIXME, or WARN message here.
>
> From DMA perspective, all are supported - no restrictions. Only I have
> not figured
> out how to use type 2b and type 3b descriptors. It's not the fault of
> DMA driver or
> specification :-) It's actually upto the client to select the right type.
OK. Then the question which I wanted to ask.
For TX, 2b should have been better choice than 2a isn't it?
>
> >> +
> >> + ? ? lcfg->sghead = sgparams;
> >> + ? ? lcfg->num_elem = nelem;
> >> + ? ? lcfg->sgheadphy = padd;
> >> + ? ? lcfg->pausenode = -1;
> >> +
> >> +
> >> + ? ? if (NULL == chparams)
> > Minute point really. Better readability "ch_params"
> OK
>
> >> + ? ? dma_write(l, CDP(lch));
> >> + ? ? dma_write((lcfg->sgheadphy), CNDP(lch));
> >> + ? ? /**
> >> + ? ? ?* Barrier needed as writes to the
> >> + ? ? ?* descriptor memory needs to be flushed
> >> + ? ? ?* before it's used by DMA controller
> >> + ? ? ?*/
> > Little bit of re-wording if you can.
> > Also you don't wanted the double **
> > ? ? ? ?/*
> > ? ? ? ? * Memory barrier is needed because data may still be
> > ? ? ? ? * in the write buffer. The barrier drains write buffers and
> > ? ? ? ? * ensures that DMA sees correct descriptors
> > ? ? ? ? */
> OK
>
> >> + ? ? wmb();
> >> + ? ? omap_start_dma(lch);
> >> +
> >> + ? ? /* Maintain the pause state in descriptor */
> >> + ? ? omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0);
> >> + ? ? omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
> >> +
> >> + ? ? /**
> >> + ? ? ?* Barrier needed as writes to the
> >> + ? ? ?* descriptor memory needs to be flushed
> >> + ? ? ?* before it's used by DMA controller
> >> + ? ? ?*/
> > Description change if possible
> OK
>
> >> + ? ? wmb();
> >> +
> >> + ? ? /* Errata i557 - pausebit should be cleared in no standby mode */
> > This should have been
>
> I couldn't understand this comment.
This should have been a separate patch since it's an errata.
>
> >> + ? ? sys_cf = dma_read(OCP_SYSCONFIG);
> >> + ? ? l = sys_cf;
> >> + ? ? /* Middle mode reg set no Standby */
> >> + ? ? l &= ~(BIT(12) | BIT(13));
> >> + ? ? dma_write(l, OCP_SYSCONFIG);
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-05-05 12:01 ` Shilimkar, Santosh
@ 2010-05-05 16:25 ` Venkatraman S
2010-05-06 7:51 ` Shilimkar, Santosh
0 siblings, 1 reply; 9+ messages in thread
From: Venkatraman S @ 2010-05-05 16:25 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, May 5, 2010 at 5:31 PM, Shilimkar, Santosh
<santosh.shilimkar@ti.com> wrote:
>
>
>> -----Original Message-----
>> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
>> Sent: Wednesday, May 05, 2010 5:20 PM
>> To: Shilimkar, Santosh
>> Cc: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>> Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren
>> Subject: Re: [PATCH v8 1/2] sDMA: descriptor autoloading feature
>>
>> [Long sections have been trimmed to the context of the discussion]
>> On Wed, May 5, 2010 at 3:02 PM, Shilimkar, Santosh
>> <santosh.shilimkar@ti.com> wrote:
>> >> -----Original Message-----
>> >> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
>> >> + ? ? ? ? ? ? dma_addr_t phyaddr, int nelem)
>> >> +{
>> >> + ? ? struct omap_dma_sglist_node *sgcurr, *sgprev;
>> >> + ? ? dma_addr_t elem_paddr = phyaddr;
>> >> +
>> >> + ? ? for (sgprev = sghead;
>> >> + ? ? ? ? ? ? sgprev < sghead + nelem;
>> >> + ? ? ? ? ? ? sgprev++) {
>> >> +
>> >> + ? ? ? ? ? ? sgcurr = sgprev + 1;
>> >> + ? ? ? ? ? ? sgprev->next = sgcurr;
>> >> + ? ? ? ? ? ? elem_paddr += (int)sizeof(*sgcurr);
>> >> + ? ? ? ? ? ? sgprev->next_desc_add_ptr = elem_paddr;
>> >> +
>> >> + ? ? ? ? ? ? switch (sgcurr->desc_type) {
>> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
>> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 1);
>> >> + ? ? ? ? ? ? ? ? ? ? break;
>> >> +
>> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
>> >> + ? ? ? ? ? ? /* intentional no break */
>> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
>> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 2);
>> >> + ? ? ? ? ? ? ? ? ? ? break;
>> >> +
>> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
>> >> + ? ? ? ? ? ? ? ? ? ? /* intentional no break */
>> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
>> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 3);
>> >> + ? ? ? ? ? ? ? ? ? ? break;
>> >> +
>> >> + ? ? ? ? ? ? default:
>> >> + ? ? ? ? ? ? ? ? ? ? return -EINVAL;
>> >> +
>> >> + ? ? ? ? ? ? }
>> > Are we supporting all the descriptor types. I think only type2a is
>> > supported. In that case please add FIXME, or WARN message here.
>>
>> From DMA perspective, all are supported - no restrictions. Only I have
>> not figured
>> out how to use type 2b and type 3b descriptors. It's not the fault of
>> DMA driver or
>> specification :-) It's actually upto the client to select the right type.
> OK. Then the question which I wanted to ask.
> For TX, 2b should have been better choice than 2a isn't it?
Not much of a difference (as the space allocation is common), but I
couldn't get 2b working correctly.
Will try that once I get some clarification from hardware team.
>>
>> >> +
>> >> + ? ? lcfg->sghead = sgparams;
>> >> + ? ? lcfg->num_elem = nelem;
>> >> + ? ? lcfg->sgheadphy = padd;
>> >> + ? ? lcfg->pausenode = -1;
>> >> +
>> >> +
>> >> + ? ? if (NULL == chparams)
>> > Minute point really. Better readability "ch_params"
>> OK
>>
>> >> + ? ? dma_write(l, CDP(lch));
>> >> + ? ? dma_write((lcfg->sgheadphy), CNDP(lch));
>> >> + ? ? /**
>> >> + ? ? ?* Barrier needed as writes to the
>> >> + ? ? ?* descriptor memory needs to be flushed
>> >> + ? ? ?* before it's used by DMA controller
>> >> + ? ? ?*/
>> > Little bit of re-wording if you can.
>> > Also you don't wanted the double **
>> > ? ? ? ?/*
>> > ? ? ? ? * Memory barrier is needed because data may still be
>> > ? ? ? ? * in the write buffer. The barrier drains write buffers and
>> > ? ? ? ? * ensures that DMA sees correct descriptors
>> > ? ? ? ? */
>> OK
>>
>> >> + ? ? wmb();
>> >> + ? ? omap_start_dma(lch);
>> >> +
>> >> + ? ? /* Maintain the pause state in descriptor */
>> >> + ? ? omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0);
>> >> + ? ? omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
>> >> +
>> >> + ? ? /**
>> >> + ? ? ?* Barrier needed as writes to the
>> >> + ? ? ?* descriptor memory needs to be flushed
>> >> + ? ? ?* before it's used by DMA controller
>> >> + ? ? ?*/
>> > Description change if possible
>> OK
>>
>> >> + ? ? wmb();
>> >> +
>> >> + ? ? /* Errata i557 - pausebit should be cleared in no standby mode */
>> > This should have been
>>
>> I couldn't understand this comment.
> This should have been a separate patch since it's an errata.
OK.
>>
>> >> + ? ? sys_cf = dma_read(OCP_SYSCONFIG);
>> >> + ? ? l = sys_cf;
>> >> + ? ? /* Middle mode reg set no Standby */
>> >> + ? ? l &= ~(BIT(12) | BIT(13));
>> >> + ? ? dma_write(l, OCP_SYSCONFIG);
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-05-05 16:25 ` Venkatraman S
@ 2010-05-06 7:51 ` Shilimkar, Santosh
2010-05-06 8:59 ` Venkatraman S
0 siblings, 1 reply; 9+ messages in thread
From: Shilimkar, Santosh @ 2010-05-06 7:51 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
> Sent: Wednesday, May 05, 2010 9:56 PM
> To: Shilimkar, Santosh
> Cc: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren
> Subject: Re: [PATCH v8 1/2] sDMA: descriptor autoloading feature
>
> On Wed, May 5, 2010 at 5:31 PM, Shilimkar, Santosh
> <santosh.shilimkar@ti.com> wrote:
> >
> >
> >> -----Original Message-----
> >> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
> >> Sent: Wednesday, May 05, 2010 5:20 PM
> >> To: Shilimkar, Santosh
> >> Cc: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> >> Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren
> >> Subject: Re: [PATCH v8 1/2] sDMA: descriptor autoloading feature
> >>
> >> [Long sections have been trimmed to the context of the discussion]
> >> On Wed, May 5, 2010 at 3:02 PM, Shilimkar, Santosh
> >> <santosh.shilimkar@ti.com> wrote:
> >> >> -----Original Message-----
> >> >> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
> >> >> + ? ? ? ? ? ? dma_addr_t phyaddr, int nelem)
> >> >> +{
> >> >> + ? ? struct omap_dma_sglist_node *sgcurr, *sgprev;
> >> >> + ? ? dma_addr_t elem_paddr = phyaddr;
> >> >> +
> >> >> + ? ? for (sgprev = sghead;
> >> >> + ? ? ? ? ? ? sgprev < sghead + nelem;
> >> >> + ? ? ? ? ? ? sgprev++) {
> >> >> +
> >> >> + ? ? ? ? ? ? sgcurr = sgprev + 1;
> >> >> + ? ? ? ? ? ? sgprev->next = sgcurr;
> >> >> + ? ? ? ? ? ? elem_paddr += (int)sizeof(*sgcurr);
> >> >> + ? ? ? ? ? ? sgprev->next_desc_add_ptr = elem_paddr;
> >> >> +
> >> >> + ? ? ? ? ? ? switch (sgcurr->desc_type) {
> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
> >> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 1);
> >> >> + ? ? ? ? ? ? ? ? ? ? break;
> >> >> +
> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
> >> >> + ? ? ? ? ? ? /* intentional no break */
> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
> >> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 2);
> >> >> + ? ? ? ? ? ? ? ? ? ? break;
> >> >> +
> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
> >> >> + ? ? ? ? ? ? ? ? ? ? /* intentional no break */
> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
> >> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 3);
> >> >> + ? ? ? ? ? ? ? ? ? ? break;
> >> >> +
> >> >> + ? ? ? ? ? ? default:
> >> >> + ? ? ? ? ? ? ? ? ? ? return -EINVAL;
> >> >> +
> >> >> + ? ? ? ? ? ? }
> >> > Are we supporting all the descriptor types. I think only type2a is
> >> > supported. In that case please add FIXME, or WARN message here.
> >>
> >> From DMA perspective, all are supported - no restrictions. Only I have
> >> not figured
> >> out how to use type 2b and type 3b descriptors. It's not the fault of
> >> DMA driver or
> >> specification :-) It's actually upto the client to select the right type.
> > OK. Then the question which I wanted to ask.
> > For TX, 2b should have been better choice than 2a isn't it?
>
> Not much of a difference (as the space allocation is common), but I
> couldn't get 2b working correctly.
> Will try that once I get some clarification from hardware team.
Add a FIXME then with description in the code so that it's not forgotten once the code
is merged.
>
> >>
> >> >> +
> >> >> + ? ? lcfg->sghead = sgparams;
> >> >> + ? ? lcfg->num_elem = nelem;
> >> >> + ? ? lcfg->sgheadphy = padd;
> >> >> + ? ? lcfg->pausenode = -1;
> >> >> +
> >> >> +
> >> >> + ? ? if (NULL == chparams)
> >> > Minute point really. Better readability "ch_params"
> >> OK
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 1/2] sDMA: descriptor autoloading feature
2010-05-06 7:51 ` Shilimkar, Santosh
@ 2010-05-06 8:59 ` Venkatraman S
0 siblings, 0 replies; 9+ messages in thread
From: Venkatraman S @ 2010-05-06 8:59 UTC (permalink / raw)
To: linux-arm-kernel
Shilimkar, Santosh <santosh.shilimkar@ti.com> wrote:
>> -----Original Message-----
>> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
>> Sent: Wednesday, May 05, 2010 9:56 PM
>> To: Shilimkar, Santosh
>> Cc: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>> Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren
>> Subject: Re: [PATCH v8 1/2] sDMA: descriptor autoloading feature
>>
>> On Wed, May 5, 2010 at 5:31 PM, Shilimkar, Santosh
>> <santosh.shilimkar@ti.com> wrote:
>> >
>> >
>> >> -----Original Message-----
>> >> From: svenkatr at gmail.com [mailto:svenkatr at gmail.com] On Behalf Of Venkatraman S
>> >> Sent: Wednesday, May 05, 2010 5:20 PM
>> >> To: Shilimkar, Santosh
>> >> Cc: linux-omap at vger.kernel.org; linux-mmc at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>> >> Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren
>> >> Subject: Re: [PATCH v8 1/2] sDMA: descriptor autoloading feature
>> >>
>> >> [Long sections have been trimmed to the context of the discussion]
>> >> On Wed, May 5, 2010 at 3:02 PM, Shilimkar, Santosh
>> >> <santosh.shilimkar@ti.com> wrote:
>> >> >> -----Original Message-----
>> >> >> +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
>> >> >> + ? ? ? ? ? ? dma_addr_t phyaddr, int nelem)
>> >> >> +{
>> >> >> + ? ? struct omap_dma_sglist_node *sgcurr, *sgprev;
>> >> >> + ? ? dma_addr_t elem_paddr = phyaddr;
>> >> >> +
>> >> >> + ? ? for (sgprev = sghead;
>> >> >> + ? ? ? ? ? ? sgprev < sghead + nelem;
>> >> >> + ? ? ? ? ? ? sgprev++) {
>> >> >> +
>> >> >> + ? ? ? ? ? ? sgcurr = sgprev + 1;
>> >> >> + ? ? ? ? ? ? sgprev->next = sgcurr;
>> >> >> + ? ? ? ? ? ? elem_paddr += (int)sizeof(*sgcurr);
>> >> >> + ? ? ? ? ? ? sgprev->next_desc_add_ptr = elem_paddr;
>> >> >> +
>> >> >> + ? ? ? ? ? ? switch (sgcurr->desc_type) {
>> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
>> >> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 1);
>> >> >> + ? ? ? ? ? ? ? ? ? ? break;
>> >> >> +
>> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
>> >> >> + ? ? ? ? ? ? /* intentional no break */
>> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
>> >> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 2);
>> >> >> + ? ? ? ? ? ? ? ? ? ? break;
>> >> >> +
>> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
>> >> >> + ? ? ? ? ? ? ? ? ? ? /* intentional no break */
>> >> >> + ? ? ? ? ? ? case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
>> >> >> + ? ? ? ? ? ? ? ? ? ? omap_dma_list_set_ntype(sgprev, 3);
>> >> >> + ? ? ? ? ? ? ? ? ? ? break;
>> >> >> +
>> >> >> + ? ? ? ? ? ? default:
>> >> >> + ? ? ? ? ? ? ? ? ? ? return -EINVAL;
>> >> >> +
>> >> >> + ? ? ? ? ? ? }
>> >> > Are we supporting all the descriptor types. I think only type2a is
>> >> > supported. In that case please add FIXME, or WARN message here.
>> >>
>> >> From DMA perspective, all are supported - no restrictions. Only I have
>> >> not figured
>> >> out how to use type 2b and type 3b descriptors. It's not the fault of
>> >> DMA driver or
>> >> specification :-) It's actually upto the client to select the right type.
>> > OK. Then the question which I wanted to ask.
>> > For TX, 2b should have been better choice than 2a isn't it?
>>
>> Not much of a difference (as the space allocation is common), but I
>> couldn't get 2b working correctly.
>> Will try that once I get some clarification from hardware team.
> Add a FIXME then with description in the code so that it's not forgotten once the code
> is merged.
OK. I am assuming the FIXME has to be in MMC driver, not here.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-05-06 8:59 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-29 17:35 [PATCH v8 1/2] sDMA: descriptor autoloading feature Venkatraman S
2010-05-05 9:32 ` Shilimkar, Santosh
2010-05-05 11:50 ` Venkatraman S
2010-05-05 12:01 ` Shilimkar, Santosh
2010-05-05 16:25 ` Venkatraman S
2010-05-06 7:51 ` Shilimkar, Santosh
2010-05-06 8:59 ` Venkatraman S
2010-05-05 10:05 ` Adrian Hunter
2010-05-05 11:51 ` Venkatraman S
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).