From patchwork Mon Jul 27 19:10:36 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: s-paulraj@ti.com X-Patchwork-Id: 37614 Received: from comal.ext.ti.com (comal.ext.ti.com [198.47.26.152]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6RJCu98024301 for ; Mon, 27 Jul 2009 19:12:57 GMT Received: from dlep34.itg.ti.com ([157.170.170.115]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id n6RJAg3C022834; Mon, 27 Jul 2009 14:10:48 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep34.itg.ti.com (8.13.7/8.13.7) with ESMTP id n6RJAfgr011072; Mon, 27 Jul 2009 14:10:42 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 70A7F80627; Mon, 27 Jul 2009 14:10:39 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dlep34.itg.ti.com (dlep34.itg.ti.com [157.170.170.115]) by linux.omap.com (Postfix) with ESMTP id CABE080626 for ; Mon, 27 Jul 2009 14:10:37 -0500 (CDT) Received: from legion.dal.design.ti.com (localhost [127.0.0.1]) by dlep34.itg.ti.com (8.13.7/8.13.7) with ESMTP id n6RJAb56011047; Mon, 27 Jul 2009 14:10:37 -0500 (CDT) Received: from gt5d9d821.telogy.design.ti.com (gt5d9d821.telogy.design.ti.com [158.218.100.23]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id n6RJAa921765; Mon, 27 Jul 2009 14:10:36 -0500 (CDT) Received: from gt5d9d821.telogy.design.ti.com (localhost.localdomain [127.0.0.1]) by gt5d9d821.telogy.design.ti.com (8.13.1/8.13.1) with ESMTP id n6RJAaRR025902; Mon, 27 Jul 2009 15:10:36 -0400 Received: (from a0866907@localhost) by gt5d9d821.telogy.design.ti.com (8.13.1/8.13.1/Submit) id n6RJAaNK025899; Mon, 27 Jul 2009 15:10:36 -0400 From: s-paulraj@ti.com To: davinci-linux-open-source@linux.davincidsp.com Date: Mon, 27 Jul 2009 15:10:36 -0400 Message-Id: <1248721836-25876-1-git-send-email-s-paulraj@ti.com> X-Mailer: git-send-email 1.6.0.4 Cc: Subject: [PATCH] DaVinci: EDMA: Adding 2 new APIs for allocating/freeing PARAMs X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.4 Precedence: list List-Id: davinci-linux-open-source.linux.davincidsp.com List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com From: Sandeep Paulraj For best performance, codecs often setup linked triggered transfers with a contiguous block of params, and that is when this API is used. Setup/configuration of these parameter RAMs is most efficient if they are contiguous. There is an API to allocate a set of contiguous parameter RAMs and a corresponding API to free a set of contiguous parameter RAMs Signed-off-by: Sandeep Paulraj --- arch/arm/mach-davinci/dma.c | 137 +++++++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/edma.h | 7 ++ 2 files changed, 144 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index e6d7e6a..f2e57d2 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -509,6 +509,45 @@ static irqreturn_t dma_tc1err_handler(int irq, void *data) return IRQ_HANDLED; } +static int reserve_contiguous_params(int ctlr, unsigned int id, + unsigned int num_params, + unsigned int start_param) +{ + int i, j; + unsigned int count = num_params; + + for (i = start_param; i < edma_info[ctlr]->num_slots; ++i) { + j = EDMA_CHAN_SLOT(i); + if (!test_and_set_bit(j, edma_info[ctlr]->edma_inuse)) + count--; + if (count == 0) + break; + else if (id == EDMA_CONT_PARAMS_FIXED_EXACT) + break; + else + count = num_params; + } + + /* + * We have to clear any bits that we set + * if we run out parameter RAMs, i.e we do find a set + * of contiguous parameter RAMs but do not find the exact number + * requested as we may reach the total number of parameter RAMs + */ + if (count) { + for (j = i - num_params + count + 1; j <= i ; ++j) + clear_bit(j, edma_info[ctlr]->edma_inuse); + + return -EBUSY; + } + + for (j = i - num_params + 1; j <= i; ++j) + memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j), + &dummy_paramset, PARM_SIZE); + + return EDMA_CTLR_CHAN(ctlr, i - num_params + 1); +} + /*-----------------------------------------------------------------------*/ /* Resource alloc/free: dma channels, parameter RAM slots */ @@ -700,6 +739,104 @@ void edma_free_slot(unsigned slot) } EXPORT_SYMBOL(edma_free_slot); + +/** + * edma_alloc_cont_slots- alloc contiguous parameter RAM slots + * The API will return the starting point of a set of + * contiguous PARAM's that have been requested + * + * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT + * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT + * @count: number of contiguous Paramter RAM's + * @param - the start value of Parameter RAM that should be passed if id + * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT + * + * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of + * contiguous Parameter RAMs from parameter RAM 64 in the case of DaVinci SOCs + * and 32 in the case of Primus + * + * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a + * set of contiguous parameter RAMs from the "param" that is passed as an + * argument to the API. + * + * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries + * starts looking for a set of contiguous parameter RAMs from the "param" + * that is passed as an argument to the API. On failure the API will try to + * find a set of contiguous Parameter RAMs in the remaining Parameter RAMs + */ +int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) +{ + /* + * The start slot requested should be greater than + * the number of channels and lesser than the total number + * of slots + */ + if (slot < edma_info[ctlr]->num_channels || + slot >= edma_info[ctlr]->num_slots) + return -EINVAL; + + /* + * The number of parameter RAMs requested cannot be less than 1 + * and cannot be more than the number of slots minus the number of + * channels + */ + if (count < 1 || count > + (edma_info[ctlr]->num_slots - edma_info[ctlr]->num_channels)) + return -EINVAL; + + switch (id) { + case EDMA_CONT_PARAMS_ANY: + return reserve_contiguous_params(ctlr, id, count, + edma_info[ctlr]->num_channels); + case EDMA_CONT_PARAMS_FIXED_EXACT: + case EDMA_CONT_PARAMS_FIXED_NOT_EXACT: + return reserve_contiguous_params(ctlr, id, count, slot); + default: + return -EINVAL; + } + +} +EXPORT_SYMBOL(edma_alloc_cont_slots); + +/** + * edma_free_cont_slots - deallocate DMA parameter RAMs + * @slot: first parameter RAM of a set of parameter RAMs to be freed + * @count: the number of contiguous parameter RAMs to be freed + * + * This deallocates the parameter RAM slots allocated by + * edma_alloc_cont_slots. + * Callers/applications need to keep track of sets of contiguous + * parameter RAMs that have been allocated using the edma_alloc_cont_slots + * API. + * Callers are responsible for ensuring the slots are inactive, and will + * not be activated. + */ +int edma_free_cont_slots(unsigned slot, int count) +{ + unsigned ctlr; + int i; + + ctlr = EDMA_CTLR(slot); + slot = EDMA_CHAN_SLOT(slot); + + if (slot < edma_info[ctlr]->num_channels || + slot >= edma_info[ctlr]->num_slots || + count < 1) + return -EINVAL; + + for (i = slot; i < slot + count; ++i) { + ctlr = EDMA_CTLR(i); + slot = EDMA_CHAN_SLOT(i); + + memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), + &dummy_paramset, PARM_SIZE); + clear_bit(slot, edma_info[ctlr]->edma_inuse); + } + + return 0; +} +EXPORT_SYMBOL(edma_free_cont_slots); + /*-----------------------------------------------------------------------*/ /* Parameter RAM operations (i) -- read/write partial slots */ diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h index 3c7dc2d..b96b2f4 100644 --- a/arch/arm/mach-davinci/include/mach/edma.h +++ b/arch/arm/mach-davinci/include/mach/edma.h @@ -226,6 +226,9 @@ enum sync_dimension { #define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */ #define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */ +#define EDMA_CONT_PARAMS_ANY 1001 +#define EDMA_CONT_PARAMS_FIXED_EXACT 1002 +#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003 /* alloc/free DMA channels and their dedicated parameter RAM slots */ int edma_alloc_channel(int channel, @@ -237,6 +240,10 @@ void edma_free_channel(unsigned channel); int edma_alloc_slot(unsigned ctlr, int slot); void edma_free_slot(unsigned slot); +/* alloc/free a set of contiguous parameter RAM slots */ +int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count); +int edma_free_cont_slots(unsigned slot, int count); + /* calls that operate on part of a parameter RAM slot */ void edma_set_src(unsigned slot, dma_addr_t src_port, enum address_mode mode, enum fifo_width);