From patchwork Wed Oct 16 19:10:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Figa X-Patchwork-Id: 3056971 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 211449F2B7 for ; Wed, 16 Oct 2013 19:14:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8E55C204B9 for ; Wed, 16 Oct 2013 19:14:23 +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 D924F204B5 for ; Wed, 16 Oct 2013 19:14:20 +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 1VWWWS-00048L-Fl; Wed, 16 Oct 2013 19:12:46 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VWWW3-0003TX-T1; Wed, 16 Oct 2013 19:12:19 +0000 Received: from mail-ee0-x231.google.com ([2a00:1450:4013:c00::231]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VWWVL-0003NK-L8 for linux-arm-kernel@lists.infradead.org; Wed, 16 Oct 2013 19:11:42 +0000 Received: by mail-ee0-f49.google.com with SMTP id d41so580745eek.36 for ; Wed, 16 Oct 2013 12:11:13 -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:in-reply-to:references; bh=o0n2/twJVGgnhER5DtW4a8gDRervGmtOBaN4ccIAblc=; b=ZgAp3P6uH1GnMX8M+aqxkmJL/+5ojkLOsrGNBAnzTkSg29kY/1P6hTLWcVatdwqfHM b4JI9PTx+bElZhuK9jqVDaBLZu82Hu9oPh3l5ifzanG0xkgnMnw0UmHmQzgS88sdQlgw Pg7De7LTbU+pDe3QZMPN8if84fvMRBilKc25vT7klY3BT6FAET0lWHUDZAJ89AaGjCQT LPlI4KxLcAJV2ZDDkA6pjhYU4g+nxX2E0yXRjml42YnhIBpWC3t8yfaYBVzoiRwxaLcQ RhQrOymD0E3td9nMhfx2n9StXTrYVqY2gaDrB8zaJ9C5tTINllZSC8pJdPD9+vgw+pkp eiQw== X-Received: by 10.14.211.136 with SMTP id w8mr69245eeo.80.1381950673894; Wed, 16 Oct 2013 12:11:13 -0700 (PDT) Received: from flatron.tomeq (87-207-52-162.dynamic.chello.pl. [87.207.52.162]) by mx.google.com with ESMTPSA id z12sm182995059eev.6.1969.12.31.16.00.00 (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 16 Oct 2013 12:11:13 -0700 (PDT) From: Tomasz Figa To: linux-samsung-soc@vger.kernel.org Subject: [PATCH v2 3/8] ARM: s3c64xx: Add support for DMA using generic amba-pl08x driver Date: Wed, 16 Oct 2013 21:10:54 +0200 Message-Id: <1381950659-12703-4-git-send-email-tomasz.figa@gmail.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1381950659-12703-1-git-send-email-tomasz.figa@gmail.com> References: <1381950659-12703-1-git-send-email-tomasz.figa@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131016_151135_972664_30600681 X-CRM114-Status: GOOD ( 23.73 ) X-Spam-Score: 1.0 (+) Cc: alsa-devel@alsa-project.org, Kukjin Kim , Mike Turquette , Arnd Bergmann , Padmavathi Venna , Sachin Kamat , Takashi Iwai , Liam Girdwood , Jaroslav Kysela , Sangbeom Kim , Mark Brown , Ben Dooks , Russell King , linux-spi@vger.kernel.org, Tomasz Figa , linux-arm-kernel@lists.infradead.org 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=-1.6 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, KHOP_BIG_TO_CC, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=no 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 This patch adds all required platform-specific data and initialization code to support the generic amba-pl08x driver on S3C64xx SoCs. Also some compatibility definitions are added to make the transition from legacy API to DMA engine easier. The biggest hack here is passing const char * pointers through DMA resource, casted to unsigned long, but this is how Samsung DMA wrappers (used to support both s3c-dma and DMA engine in drivers) are designed. Signed-off-by: Tomasz Figa --- arch/arm/Kconfig | 1 + arch/arm/mach-s3c64xx/Kconfig | 8 +- arch/arm/mach-s3c64xx/Makefile | 1 + arch/arm/mach-s3c64xx/common.h | 5 + arch/arm/mach-s3c64xx/include/mach/dma.h | 63 ++++++++ arch/arm/mach-s3c64xx/pl080.c | 244 +++++++++++++++++++++++++++++++ arch/arm/plat-samsung/devs.c | 10 +- arch/arm/plat-samsung/dma-ops.c | 8 +- 8 files changed, 336 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-s3c64xx/pl080.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e639a30..8f541e0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -724,6 +724,7 @@ config ARCH_S3C64XX bool "Samsung S3C64XX" select ARCH_HAS_CPUFREQ select ARCH_REQUIRE_GPIOLIB + select ARM_AMBA select ARM_VIC select CLKDEV_LOOKUP select CLKSRC_SAMSUNG_PWM diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index 2cb8dc5..d8e0288 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -17,9 +17,15 @@ config CPU_S3C6410 help Enable S3C6410 CPU support +config S3C64XX_PL080 + bool "S3C64XX DMA using generic PL08x driver" + select AMBA_PL08X + select SAMSUNG_DMADEV + config S3C64XX_DMA - bool "S3C64XX DMA" + bool "S3C64XX DMA using legacy S3C DMA API" select S3C_DMA + depends on !S3C64XX_PL080 config S3C64XX_SETUP_SDHCI bool diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 6faedcf..e8e9a46 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle.o # DMA support obj-$(CONFIG_S3C64XX_DMA) += dma.o +obj-$(CONFIG_S3C64XX_PL080) += pl080.o # Device support diff --git a/arch/arm/mach-s3c64xx/common.h b/arch/arm/mach-s3c64xx/common.h index bd3bd56..7043e7a 100644 --- a/arch/arm/mach-s3c64xx/common.h +++ b/arch/arm/mach-s3c64xx/common.h @@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void); static inline int s3c64xx_pm_late_initcall(void) { return 0; } #endif +#ifdef CONFIG_S3C64XX_PL080 +extern struct pl08x_platform_data s3c64xx_dma0_plat_data; +extern struct pl08x_platform_data s3c64xx_dma1_plat_data; +#endif + #endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h index fe1a98c..26a6bc3 100644 --- a/arch/arm/mach-s3c64xx/include/mach/dma.h +++ b/arch/arm/mach-s3c64xx/include/mach/dma.h @@ -11,6 +11,8 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H __FILE__ +#ifdef CONFIG_S3C64XX_DMA + #define S3C_DMA_CHANNELS (16) /* see mach-s3c2410/dma.h for notes on dma channel numbers */ @@ -128,4 +130,65 @@ struct s3c2410_dma_chan { #include +#else + +#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name)) + +/* DMA0/SDMA0 */ +#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx") +#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx") +#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx") +#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx") +#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx") +#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx") +#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx") +#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx") +#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx") +#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx") +#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx") +#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx") +#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx") +#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx") +#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx") +#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx") + +/* DMA1/SDMA1 */ +#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx") +#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx") +#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx") +#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx") +#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx") +#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx") +#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out") +#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in") +#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic") +#define DMACH_PWM S3C64XX_DMA_CHAN("pwm") +#define DMACH_IRDA S3C64XX_DMA_CHAN("irda") +#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external") +#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx") +#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx") + +enum dma_ch { + DMACH_MAX = 32 +}; + +struct s3c2410_dma_client { + char *name; +}; + +static inline bool samsung_dma_has_circular(void) +{ + return true; +} + +static inline bool samsung_dma_is_dmadev(void) +{ + return true; +} + +#include +#include + +#endif + #endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c64xx/pl080.c b/arch/arm/mach-s3c64xx/pl080.c new file mode 100644 index 0000000..901a984 --- /dev/null +++ b/arch/arm/mach-s3c64xx/pl080.c @@ -0,0 +1,244 @@ +/* + * Samsung's S3C64XX generic DMA support using amba-pl08x driver. + * + * Copyright (c) 2013 Tomasz Figa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "regs-sys.h" + +static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd) +{ + return cd->min_signal; +} + +static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch) +{ +} + +/* + * DMA0 + */ + +static struct pl08x_channel_data s3c64xx_dma0_info[] = { + { + .bus_id = "uart0_tx", + .min_signal = 0, + .max_signal = 0, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart0_rx", + .min_signal = 1, + .max_signal = 1, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart1_tx", + .min_signal = 2, + .max_signal = 2, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart1_rx", + .min_signal = 3, + .max_signal = 3, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart2_tx", + .min_signal = 4, + .max_signal = 4, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart2_rx", + .min_signal = 5, + .max_signal = 5, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart3_tx", + .min_signal = 6, + .max_signal = 6, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "uart3_rx", + .min_signal = 7, + .max_signal = 7, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "pcm0_tx", + .min_signal = 8, + .max_signal = 8, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "pcm0_rx", + .min_signal = 9, + .max_signal = 9, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "i2s0_tx", + .min_signal = 10, + .max_signal = 10, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "i2s0_rx", + .min_signal = 11, + .max_signal = 11, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "spi0_tx", + .min_signal = 12, + .max_signal = 12, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "spi0_rx", + .min_signal = 13, + .max_signal = 13, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "i2s2_tx", + .min_signal = 14, + .max_signal = 14, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "i2s2_rx", + .min_signal = 15, + .max_signal = 15, + .periph_buses = PL08X_AHB2, + } +}; + +struct pl08x_platform_data s3c64xx_dma0_plat_data = { + .memcpy_channel = { + .bus_id = "memcpy", + .cctl_memcpy = + (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT | + PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | + PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | + PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | + PL080_CONTROL_PROT_SYS), + }, + .lli_buses = PL08X_AHB1, + .mem_buses = PL08X_AHB1, + .get_xfer_signal = pl08x_get_xfer_signal, + .put_xfer_signal = pl08x_put_xfer_signal, + .slave_channels = s3c64xx_dma0_info, + .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info), +}; + +static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0, + 0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data); + +/* + * DMA1 + */ + +static struct pl08x_channel_data s3c64xx_dma1_info[] = { + { + .bus_id = "pcm1_tx", + .min_signal = 0, + .max_signal = 0, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "pcm1_rx", + .min_signal = 1, + .max_signal = 1, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "i2s1_tx", + .min_signal = 2, + .max_signal = 2, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "i2s1_rx", + .min_signal = 3, + .max_signal = 3, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "spi1_tx", + .min_signal = 4, + .max_signal = 4, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "spi1_rx", + .min_signal = 5, + .max_signal = 5, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "ac97_out", + .min_signal = 6, + .max_signal = 6, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "ac97_in", + .min_signal = 7, + .max_signal = 7, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "ac97_mic", + .min_signal = 8, + .max_signal = 8, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "pwm", + .min_signal = 9, + .max_signal = 9, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "irda", + .min_signal = 10, + .max_signal = 10, + .periph_buses = PL08X_AHB2, + }, { + .bus_id = "external", + .min_signal = 11, + .max_signal = 11, + .periph_buses = PL08X_AHB2, + }, +}; + +struct pl08x_platform_data s3c64xx_dma1_plat_data = { + .memcpy_channel = { + .bus_id = "memcpy", + .cctl_memcpy = + (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT | + PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | + PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | + PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | + PL080_CONTROL_PROT_SYS), + }, + .lli_buses = PL08X_AHB1, + .mem_buses = PL08X_AHB1, + .get_xfer_signal = pl08x_get_xfer_signal, + .put_xfer_signal = pl08x_put_xfer_signal, + .slave_channels = s3c64xx_dma1_info, + .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info), +}; + +static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0, + 0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data); + +static int __init s3c64xx_pl080_init(void) +{ + /* Set all DMA configuration to be DMA, not SDMA */ + writel(0xffffff, S3C64XX_SDMA_SEL); + + if (of_have_populated_dt()) + return 0; + + amba_device_register(&s3c64xx_dma0_device, &iomem_resource); + amba_device_register(&s3c64xx_dma1_device, &iomem_resource); + + return 0; +} +arch_initcall(s3c64xx_pl080_init); diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index a7b9b9e..d034048 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -1502,6 +1502,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio; #if defined(CONFIG_PL330_DMA) pd.filter = pl330_filter; +#elif defined(CONFIG_S3C64XX_PL080) + pd.filter = pl08x_filter_id; #elif defined(CONFIG_S3C24XX_DMAC) pd.filter = s3c24xx_dma_filter; #endif @@ -1543,8 +1545,10 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, pd.num_cs = num_cs; pd.src_clk_nr = src_clk_nr; pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio; -#ifdef CONFIG_PL330_DMA +#if defined(CONFIG_PL330_DMA) pd.filter = pl330_filter; +#elif defined(CONFIG_S3C64XX_PL080) + pd.filter = pl08x_filter_id; #endif s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1); @@ -1584,8 +1588,10 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, pd.num_cs = num_cs; pd.src_clk_nr = src_clk_nr; pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio; -#ifdef CONFIG_PL330_DMA +#if defined(CONFIG_PL330_DMA) pd.filter = pl330_filter; +#elif defined(CONFIG_S3C64XX_PL080) + pd.filter = pl08x_filter_id; #endif s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2); diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index ec0d731..886326e 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c @@ -18,6 +18,12 @@ #include +#if defined(CONFIG_PL330_DMA) +#define dma_filter pl330_filter +#elif defined(CONFIG_S3C64XX_PL080) +#define dma_filter pl08x_filter_id +#endif + static unsigned samsung_dmadev_request(enum dma_ch dma_ch, struct samsung_dma_req *param, struct device *dev, char *ch_name) @@ -30,7 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch, if (dev->of_node) return (unsigned)dma_request_slave_channel(dev, ch_name); else - return (unsigned)dma_request_channel(mask, pl330_filter, + return (unsigned)dma_request_channel(mask, dma_filter, (void *)dma_ch); }