From patchwork Sun Jun 16 20:54:11 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Figa X-Patchwork-Id: 2728911 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 61997C0AB1 for ; Sun, 16 Jun 2013 20:57:37 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5FD9F20172 for ; Sun, 16 Jun 2013 20:57:36 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E59122016E for ; Sun, 16 Jun 2013 20:57:34 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UoJzZ-0006tj-Em; Sun, 16 Jun 2013 20:56:07 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UoJz9-00084R-Bu; Sun, 16 Jun 2013 20:55:39 +0000 Received: from mail-bk0-x22e.google.com ([2a00:1450:4008:c01::22e]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UoJyU-0007xZ-Im for linux-arm-kernel@lists.infradead.org; Sun, 16 Jun 2013 20:55:01 +0000 Received: by mail-bk0-f46.google.com with SMTP id na10so880003bkb.33 for ; Sun, 16 Jun 2013 13:54:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=GCdzq0fklYB2nLq3pVj49EH4FXFyRKEd6z/146mOaQc=; b=SMv3fT5/NcAxmfc/q6GOcNHYLyAuiTecounazsXfsjEbonjFBMOTmcexuPtnrMyaAN RN+P7JJNoryqkO9Sy4rmB3kt2pTBFTwfBDP/oLBcyrImlixSRdXSYGBK8a+XKHnQ2i0D 5ypw8osfwN7Bl5e4/nWYsbCKMmEpEZ2/EwJRFrJ8eozG5EQPv10BlB+ySGIkgp56Rxam Zj6LmEJviAv+GfCOueMXpeG1rbRAw9f7CsNy+HIqHKK558SXALCUPW/h9U3GHVZ6Fc1P HQtQESbk7C/Ja4gOQaTouHgBNbljbUpht1FB+INRVeTivsYCFa//hFY6GcBfT8uFGCf0 iSqQ== X-Received: by 10.204.70.1 with SMTP id b1mr1546104bkj.3.1371416077543; Sun, 16 Jun 2013 13:54:37 -0700 (PDT) Received: from flatron.tomeq (87-207-52-162.dynamic.chello.pl. [87.207.52.162]) by mx.google.com with ESMTPSA id m6sm1996010bki.7.2013.06.16.13.54.34 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 16 Jun 2013 13:54:36 -0700 (PDT) From: Tomasz Figa To: linux-samsung-soc@vger.kernel.org Subject: [RFC PATCH 04/11] dma: amba-pl08x: Add support for PL080S variant Date: Sun, 16 Jun 2013 22:54:11 +0200 Message-Id: <1371416058-22047-5-git-send-email-tomasz.figa@gmail.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1371416058-22047-1-git-send-email-tomasz.figa@gmail.com> References: <1371416058-22047-1-git-send-email-tomasz.figa@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130616_165458_977552_77379F55 X-CRM114-Status: GOOD ( 20.90 ) X-Spam-Score: -2.0 (--) Cc: alsa-devel@alsa-project.org, =?UTF-8?q?Heiko=20St=C3=BCbner?= , Padmavathi Venna , Takashi Iwai , Linus Walleij , Tomasz Figa , linux-kernel@vger.kernel.org, Giancarlo Asnaghi , Kukjin Kim , Russell King - ARM Linux , Vinod Koul , Thomas Abraham , Grant Likely , Alessandro Rubini , Arnd Bergmann , Mark Brown , Sylwester Nawrocki , Jaroslav Kysela , linux-arm-kernel@lists.infradead.org, Sangbeom Kim , Liam Girdwood , linux-spi@vger.kernel.org, Dan Williams , Olof Johansson , Alban Bedel X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP PL080S is a modified version of PL080 that can be found on Samsung SoCs, such as S3C6400 and S3C6410. It has different offset of CONFIG register, separate CONTROL1 register that holds transfer size and larger maximum transfer size. Signed-off-by: Tomasz Figa Acked-by: Linus Walleij --- drivers/dma/amba-pl08x.c | 68 +++++++++++++++++++++++++++++++++++++++------- include/linux/amba/pl080.h | 1 + 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 93913b4..d1f1333 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -100,6 +100,8 @@ struct pl08x_driver_data; * for permission before use and some registers are missing. */ #define PL08X_IS_NOMADIK (1 << 1) +/** Controller is PL080S (PL080 modified by Samsung) */ +#define PL08X_IS_PL080S (1 << 2) /** * struct vendor_data - vendor-specific config parameters for PL08x derivatives @@ -123,6 +125,7 @@ struct pl08x_lli { u32 dst; u32 lli; u32 cctl; + u32 cctl1; }; /** @@ -381,6 +384,9 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan) writel(lli->cctl, phychan->base + PL080_CH_CONTROL); writel(txd->ccfg, phychan->base + pl08x->vd->config_offset); + if (pl08x->vd->flags & PL08X_IS_PL080S) + writel(lli->cctl1, phychan->base + PL080S_CH_CONTROL2); + /* Enable the DMA channel */ /* Do not access config register until channel shows as disabled */ while (readl(pl08x->base + PL080_EN_CHAN) & (1 << phychan->id)) @@ -476,9 +482,28 @@ static inline u32 get_bytes_in_cctl(u32 cctl) return bytes; } +static inline u32 get_bytes_in_cctl_pl080s(u32 cctl, u32 cctl1) +{ + /* The source width defines the number of bytes */ + u32 bytes = cctl1 & PL080S_CONTROL_TRANSFER_SIZE_MASK; + + switch (cctl >> PL080_CONTROL_SWIDTH_SHIFT) { + case PL080_WIDTH_8BIT: + break; + case PL080_WIDTH_16BIT: + bytes *= 2; + break; + case PL080_WIDTH_32BIT: + bytes *= 4; + break; + } + return bytes; +} + /* The channel should be paused when calling this */ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan) { + struct pl08x_driver_data *pl08x = plchan->host; struct pl08x_lli *llis_va; struct pl08x_phy_chan *ch; dma_addr_t llis_bus; @@ -500,7 +525,12 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan) clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2; /* First get the remaining bytes in the active transfer */ - bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL)); + if (pl08x->vd->flags & PL08X_IS_PL080S) + bytes = get_bytes_in_cctl_pl080s( + readl(ch->base + PL080_CH_CONTROL), + readl(ch->base + PL080S_CH_CONTROL2)); + else + bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL)); if (!clli) return bytes; @@ -518,7 +548,11 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan) index = (clli - llis_bus) / sizeof(struct pl08x_lli); for (; index < MAX_NUM_TSFR_LLIS; index++) { - bytes += get_bytes_in_cctl(llis_va[index].cctl); + if (pl08x->vd->flags & PL08X_IS_PL080S) + bytes += get_bytes_in_cctl_pl080s(llis_va[index].cctl, + llis_va[index].cctl1); + else + bytes += get_bytes_in_cctl(llis_va[index].cctl); /* * A LLI pointer of 0 terminates the LLI list @@ -780,7 +814,7 @@ static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd, * Fills in one LLI for a certain transfer descriptor and advance the counter */ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd, - int num_llis, int len, u32 cctl) + int num_llis, int len, u32 cctl, u32 cctl1) { struct pl08x_lli *llis_va = bd->txd->llis_va; dma_addr_t llis_bus = bd->txd->llis_bus; @@ -788,6 +822,7 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd, BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS); llis_va[num_llis].cctl = cctl; + llis_va[num_llis].cctl1 = cctl1; llis_va[num_llis].src = bd->srcbus.addr; llis_va[num_llis].dst = bd->dstbus.addr; llis_va[num_llis].lli = llis_bus + (num_llis + 1) * @@ -804,11 +839,12 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd, bd->remainder -= len; } -static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd, +static inline void prep_byte_width_lli(struct pl08x_driver_data *pl08x, + struct pl08x_lli_build_data *bd, u32 *cctl, u32 len, int num_llis, size_t *total_bytes) { *cctl = pl08x_cctl_bits(*cctl, 1, 1, len); - pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl); + pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl, len); (*total_bytes) += len; } @@ -912,7 +948,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x, cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth, bd.dstbus.buswidth, 0); - pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl); + pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl, 0); break; } @@ -934,7 +970,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x, dev_vdbg(&pl08x->adev->dev, "%s byte width LLIs (remain 0x%08x)\n", __func__, bd.remainder); - prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++, + prep_byte_width_lli(pl08x, &bd, &cctl, early_bytes, num_llis++, &total_bytes); } @@ -992,7 +1028,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x, cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth, bd.dstbus.buswidth, tsize); pl08x_fill_lli_for_desc(&bd, num_llis++, - lli_len, cctl); + lli_len, cctl, tsize); total_bytes += lli_len; } @@ -1003,8 +1039,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x, dev_vdbg(&pl08x->adev->dev, "%s align with boundary, send odd bytes (remain %zu)\n", __func__, bd.remainder); - prep_byte_width_lli(&bd, &cctl, bd.remainder, - num_llis++, &total_bytes); + prep_byte_width_lli(pl08x, &bd, &cctl, + bd.remainder, num_llis++, &total_bytes); } } @@ -2064,6 +2100,12 @@ static struct vendor_data vendor_nomadik = { .config_offset = PL080_CH_CONFIG, }; +static struct vendor_data vendor_pl080s = { + .channels = 8, + .flags = PL08X_IS_DUALMASTER | PL08X_IS_PL080S, + .config_offset = PL080S_CH_CONFIG, +}; + static struct vendor_data vendor_pl081 = { .channels = 2, .flags = 0, @@ -2071,6 +2113,12 @@ static struct vendor_data vendor_pl081 = { }; static struct amba_id pl08x_ids[] = { + /* Samsung PL080S variant */ + { + .id = 0x0a141080, + .mask = 0xffffffff, + .data = &vendor_pl080s, + }, /* PL080 */ { .id = 0x00041080, diff --git a/include/linux/amba/pl080.h b/include/linux/amba/pl080.h index 3e7b62f..ef36a0a 100644 --- a/include/linux/amba/pl080.h +++ b/include/linux/amba/pl080.h @@ -87,6 +87,7 @@ #define PL080_CONTROL_SB_SIZE_MASK (0x7 << 12) #define PL080_CONTROL_SB_SIZE_SHIFT (12) #define PL080_CONTROL_TRANSFER_SIZE_MASK (0xfff << 0) +#define PL080S_CONTROL_TRANSFER_SIZE_MASK (0xffffff << 0) #define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0) #define PL080_BSIZE_1 (0x0)