Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100
On Mon, Mar 29, 2010 at 4:48 AM, Feng Tang feng.t...@intel.com wrote: Hi, Hi, I modified the code a little and run it on our HW platform, it really show some sigh of life: it can boots to console (the print format is not so good), I can input command and it execute correctly, but very slow, I type 3 characters and it takes about 2 seconds to echo back on screen and start the execution, and after about 1 minute, the console hang there and input stopped to work. never seen such a behavior. Which platform are you using? Which SPI driver? Do you have a low level printk (printascii) that puts output somewhere else so I can send you a patch with some debugging output? Can you log in some other way (like via network) and see if the CPU load is at 100% for some reason? This patch adds console support for the MAX3100 UART (console=ttyMAX0,11500). The SPI subsystem and an 115200? ack Does this imply to have to work with HW flow control? on my platform I have to remove the RTS bit to make it work. no, I put RTS on because it looks like a good default. I can make it configurable. I just noticed on the data sheet that RTS is actually inverted so a more sensible default would be to put it off. For testing you should have flow control set to none on the machine you are using as a terminal emulator. + max3100_sr(s, tx, rx); It doesn't handle received characters here? If the console is printing out a bulk of message while user input some command, the command may be ignored. Myself have met the same problem in our driver. yes but I think it's quite difficult to solve this problem in every case. Console output is massively used only on boot when the user is not supposed to type a lot. + if (next != s-console_tail) { + s-console_buf[next] = ch; + s-console_head = next; + } Also I saw max3100_sr() uses cpu_to_be16() and be16_to_cpu(), is it really necessary, our platform is little-endian(x86), and I have to disable them to make the code work. Is your test platform big-endian? Have you configured your SPI controller as LSB first somehow, haven't you? BTW my platform is a quite usual ARM9 S3C2440 which is little endian. -- Christian Pellegrin, see http://www.evolware.org/chri/ Real Programmers don't play tennis, or any other sport which requires you to change clothes. Mountain climbing is OK, and Real Programmers wear their climbing boots to work in case a mountain should suddenly spring up in the middle of the computer room. -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100
On Mon, 29 Mar 2010 14:11:15 +0800 christian pellegrin chrip...@fsfe.org wrote: I modified the code a little and run it on our HW platform, it really show some sigh of life: it can boots to console (the print format is not so good), I can input command and it execute correctly, but very slow, I type 3 characters and it takes about 2 seconds to echo back on screen and start the execution, and after about 1 minute, the console hang there and input stopped to work. never seen such a behavior. Which platform are you using? Which SPI driver? Do you have a low level printk (printascii) that puts output somewhere else so I can send you a patch with some debugging output? Can you log in some other way (like via network) and see if the CPU load is at 100% for some reason? Hi, Our platform is Intel Moorestown platform, and use a spi controller core from Designware (drivers/spi/dw_*.c). I know the problem may probably be caused by my setting, but the dw_spi driver works fine with our own 3110 driver. For debug method, sadly I don't get another output port yet, but if you have some debug patch, that's great, it will help when I find another debug output than max3110. + max3100_sr(s, tx, rx); It doesn't handle received characters here? If the console is printing out a bulk of message while user input some command, the command may be ignored. Myself have met the same problem in our driver. yes but I think it's quite difficult to solve this problem in every case. Console output is massively used only on boot when the user is not supposed to type a lot. It's difficult but not impossible, actually our driver checks every word read back and handle it if it contains a valid data + if (next != s-console_tail) { + s-console_buf[next] = ch; + s-console_head = next; + } Also I saw max3100_sr() uses cpu_to_be16() and be16_to_cpu(), is it really necessary, our platform is little-endian(x86), and I have to disable them to make the code work. Is your test platform big-endian? Have you configured your SPI controller as LSB first somehow, haven't you? BTW my platform is a quite usual ARM9 S3C2440 which is little endian. yeah, you hit the point that our spi controller is LSB naturally (not configured to), here may need a check for whether to do a swap -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100
On Mon, Mar 29, 2010 at 9:06 AM, Feng Tang feng.t...@intel.com wrote: Our platform is Intel Moorestown platform, and use a spi controller core from Designware (drivers/spi/dw_*.c). I know the problem may probably be caused by my setting, but the dw_spi driver works fine with our own 3110 driver. I had a look at the dw_spi driver. The spi_transfer path queues some work to a worqueue that itself schedules a tasklet. I don't think this is good for latency, I won't bet that such an architecture could deliver good performance. Now I see why you needed to do only big fat SPI transfers. Anyway this doesn't justify the 2 seconds delay between chars coming in and going out through the max31x0 you are seeing. I will try to analyze what's going on. BTW is only input slow or output is sluggish too? The initial messages from the console are coming out fast? If you disable the MAX3110 for console but you use just as a normal terminal (set console=/dev/null in the kernel command line and add getty 115200 /dev/ttyMAX0 in iniitab) is the interaction with the system fine? Thanks for helping sorting out this. yes but I think it's quite difficult to solve this problem in every case. Console output is massively used only on boot when the user is not supposed to type a lot. It's difficult but not impossible, actually our driver checks every word read back and handle it if it contains a valid data Of course it is possible, I just wanted to keep the max3100 a small clean driver. Unfortunately console and serial drivers are two different beings in the Linux kernel, but the max3100 implements the tx-rx in one indivisible instruction (that is slow compared to registers IO and has to be called in an preemptible contex for added fun). To implement what you are saying we need: 1) the console code has to check if the serial port associated to the same physical max3100 is up (console driver start their life much before serial ones). 2) if yes send data to the tty associated to the serial driver. Locking is needed here. I will implement this ASAP. Have you configured your SPI controller as LSB first somehow, haven't you? BTW my platform is a quite usual ARM9 S3C2440 which is little endian. yeah, you hit the point that our spi controller is LSB naturally (not configured to), here may need a check for whether to do a swap ok, I think the dw_spi driver has to be fixed. -- Christian Pellegrin, see http://www.evolware.org/chri/ Real Programmers don't play tennis, or any other sport which requires you to change clothes. Mountain climbing is OK, and Real Programmers wear their climbing boots to work in case a mountain should suddenly spring up in the middle of the computer room. -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
[spi-devel-general] [PATCH 0/5] ARM: PrimeCell DMA patches v4
This is a fourth iteration of the PrimeCell DMA API on top of the generic DMA devices (sibling to the DMA engine). It's based on the suggestion from Russell to try and define a specific extension subset for DMA devices. Since last iteration the changes are: - Some necessary extensions to the DMA engine were folded into the generic DMA engine framework and are now pending in Dan's -next tree. - I have now also implemented support for the PL022 PrimeCell. PL011, PL022 and PL180 drivers were tested on the U300 with the COH 901 318 DMA device. The PL011 driver was also tested on the U8500 with the pending DMA40 DMA device. We're running huge and high-speed transfers on all peripherals. It works. Patches will be added to the patch tracker soonish, but if this is eventually OK:ed by Russell I guess it will have to go in through Dan's DMA tree. Also Grant has to OK it as maintainer of the SPI subsystem. Yours, Linus Walleij ST-Ericsson SA -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
[spi-devel-general] [PATCH 1/6] ARM: define the PrimeCell DMA API
This patch extends the DMA engine with a PrimeCell superset with three functions: configure DMA channel, stop channel, and one for getting the number of bytes pending on a channel. These have been identified as the basic extensions needed to drive DMA on top of the PL011, PL022 and PL180 PrimeCells. Signed-off-by: Linus Walleij linus.wall...@stericsson.com --- Changes since last version: - Two functions were moved into the DMA engine API instead --- include/linux/amba/dma.h | 50 ++ 1 files changed, 50 insertions(+), 0 deletions(-) create mode 100644 include/linux/amba/dma.h diff --git a/include/linux/amba/dma.h b/include/linux/amba/dma.h new file mode 100644 index 000..1adbcfc --- /dev/null +++ b/include/linux/amba/dma.h @@ -0,0 +1,50 @@ +/* + * linux/include/amba/dma.h + * + * Copyright (C) 2010 ST-Ericsson AB + * + * 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. + */ +#if !defined(AMBA_DMA_H) defined(CONFIG_DMADEVICES) +#define AMBA_DMA_H + +/** + * struct amba_dma_channel_request - this struct is passed in as + * configuration data to a DMA engine in order to set up a certain + * channel for DMA transport. Anything the DMA engine needs to + * know about the PrimeCell shall be passed through this struct. + * The DMA engine has to provide an additional function: + * dma_set_ambaconfig() in order for it to work with PrimeCells. + * @addr: this is the physical address where DMA data should be + * read (RX) or written (TX) + * @addr_width: this is the width of the source (RX) or target + * (TX) register where DMA data shall be read/written, in bytes. + * legal values: 1, 2, 4, 8. + * @direction: whether the data goes in or out on this channel, + * right now. + * @maxburst: the maximum number of words (note: words, not bytes) + * that can be sent in one burst to the device. Typically something + * like half the FIFO depth on I/O peripherals so you don't + * overflow it. + */ +struct amba_dma_channel_config { + dma_addr_t addr; + u8 addr_width:4; + enum dma_data_direction direction; + int maxburst; +}; + +/* + * The following are extensions to the DMA engine framework + * that are needed to use the engine with PrimeCells. We need + * to configure devices and be able to stop transfers and + * retrieve the number of bytes left on the channel for some + * RX transfers when we don't know where and how the transfer + * will occur. + */ +void dma_set_ambaconfig(struct dma_chan *chan, + struct amba_dma_channel_config *config); + +#endif /* AMBA_DMA_H */ -- 1.6.3.3 -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general
[spi-devel-general] [PATCH 2/6] ARM: add generic PrimeCell interface to COH 901 318
This extends the DMA engine driver for the COH 901 318 used in the U300 platform with the generic PrimeCell interface, Signed-off-by: Linus Walleij linus.wall...@stericsson.com --- drivers/dma/coh901318.c | 146 +++ drivers/dma/coh901318_lli.c | 78 ++- 2 files changed, 221 insertions(+), 3 deletions(-) diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 4233440..1d5ed16 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -21,6 +21,7 @@ #include linux/uaccess.h #include linux/debugfs.h #include mach/coh901318.h +#include linux/amba/dma.h #include coh901318_lli.h @@ -72,6 +73,9 @@ struct coh901318_chan { unsigned long nbr_active_done; unsigned long busy; + u32 amba_addr; + u32 amba_ctrl; + struct coh901318_base *base; }; @@ -190,6 +194,9 @@ static inline struct coh901318_chan *to_coh901318_chan(struct dma_chan *chan) static inline dma_addr_t cohc_dev_addr(struct coh901318_chan *cohc) { + /* PrimeCell supplied address will take precedence */ + if (cohc-amba_addr) + return cohc-amba_addr; return cohc-base-platform-chan_conf[cohc-id].dev_addr; } @@ -1055,6 +1062,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, params = cohc_chan_param(cohc); config = params-config; + /* +* Add primecell-specific control on top, make +* sure the bits you set per peripheral channel are +* cleared in the default config from the platform. +*/ + ctrl_chained |= cohc-amba_ctrl; + ctrl_last |= cohc-amba_ctrl; + ctrl |= cohc-amba_ctrl; if (direction == DMA_TO_DEVICE) { u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | @@ -1113,6 +1128,12 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (ret) goto err_lli_fill; + /* +* Set the default ctrl for the channel to the one from the lli, +* things may have changed due to odd buffer alignment etc. +*/ + coh901318_set_ctrl(cohc, lli-control); + COH_DBG(coh901318_list_print(cohc, lli)); /* Pick a descriptor to handle this transfer */ @@ -1239,6 +1260,131 @@ coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) return 0; } + +/* + * Here we wrap in the PrimeCell dma interface + */ +struct burst_table { + int burst_8bit; + int burst_16bit; + int burst_32bit; + u32 reg; +}; + +static const struct burst_table burst_sizes[] = { + { + .burst_8bit = 64, + .burst_16bit = 32, + .burst_32bit = 16, + .reg = COH901318_CX_CTRL_BURST_COUNT_64_BYTES, + }, + { + .burst_8bit = 48, + .burst_16bit = 24, + .burst_32bit = 12, + .reg = COH901318_CX_CTRL_BURST_COUNT_48_BYTES, + }, + { + .burst_8bit = 32, + .burst_16bit = 16, + .burst_32bit = 8, + .reg = COH901318_CX_CTRL_BURST_COUNT_32_BYTES, + }, + { + .burst_8bit = 16, + .burst_16bit = 8, + .burst_32bit = 4, + .reg = COH901318_CX_CTRL_BURST_COUNT_16_BYTES, + }, + { + .burst_8bit = 8, + .burst_16bit = 4, + .burst_32bit = 2, + .reg = COH901318_CX_CTRL_BURST_COUNT_8_BYTES, + }, + { + .burst_8bit = 4, + .burst_16bit = 2, + .burst_32bit = 1, + .reg = COH901318_CX_CTRL_BURST_COUNT_4_BYTES, + }, + { + .burst_8bit = 2, + .burst_16bit = 1, + .burst_32bit = 0, + .reg = COH901318_CX_CTRL_BURST_COUNT_2_BYTES, + }, + { + .burst_8bit = 1, + .burst_16bit = 0, + .burst_32bit = 0, + .reg = COH901318_CX_CTRL_BURST_COUNT_1_BYTE, + }, +}; + +void dma_set_ambaconfig(struct dma_chan *chan, + struct amba_dma_channel_config *config) +{ + struct coh901318_chan *cohc = to_coh901318_chan(chan); + int maxburst = config-maxburst; + u32 amba_ctrl = 0; + int i = 0; + + dev_dbg(COHC_2_DEV(cohc), configure channel for %d byte transfers\n, + config-addr_width); + switch (config-addr_width) { + case 1: + amba_ctrl |= + COH901318_CX_CTRL_SRC_BUS_SIZE_8_BITS | + COH901318_CX_CTRL_DST_BUS_SIZE_8_BITS; + + while (i ARRAY_SIZE(burst_sizes)) { + if (burst_sizes[i].burst_8bit = maxburst) + break; + i++; + } + + break; + case 2: +
[spi-devel-general] [PATCH 6/6] ARM: config U300 PL180 PL011 PL022 for DMA
This will configure the platform data for the PL180, PL011 and PL022 PrimeCells found in the U300 to use DMA with the generic PrimeCell DMA engine. Signed-off-by: Linus Walleij linus.wall...@stericsson.com --- arch/arm/mach-u300/core.c | 173 - arch/arm/mach-u300/mmc.c | 13 +++- arch/arm/mach-u300/spi.c | 21 -- 3 files changed, 181 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 5f34eb6..7f7e738 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -3,7 +3,7 @@ * arch/arm/mach-u300/core.c * * - * Copyright (C) 2007-2010 ST-Ericsson AB + * Copyright (C) 2007-2010 ST-Ericsson SA * License terms: GNU General Public License (GPL) version 2 * Core platform support, IRQ handling and device definitions. * Author: Linus Walleij linus.wall...@stericsson.com @@ -16,7 +16,9 @@ #include linux/device.h #include linux/mm.h #include linux/termios.h +#include linux/dmaengine.h #include linux/amba/bus.h +#include linux/amba/serial.h #include linux/platform_device.h #include linux/gpio.h #include mach/coh901318.h @@ -92,10 +94,20 @@ void __init u300_map_io(void) * Declaration of devices found on the U300 board and * their respective memory locations. */ + +static struct amba_pl011_data uart0_plat_data = { +#ifdef CONFIG_COH901318 + .dma_filter = coh901318_filter_id, + .dma_rx_param = (void *) U300_DMA_UART0_RX, + .dma_tx_param = (void *) U300_DMA_UART0_TX, +#endif +}; + static struct amba_device uart0_device = { .dev = { + .coherent_dma_mask = ~0, .init_name = uart0, /* Slow device at 0x3000 offset */ - .platform_data = NULL, + .platform_data = uart0_plat_data, }, .res = { .start = U300_UART0_BASE, @@ -107,10 +119,19 @@ static struct amba_device uart0_device = { /* The U335 have an additional UART1 on the APP CPU */ #ifdef CONFIG_MACH_U300_BS335 +static struct amba_pl011_data uart1_plat_data = { +#ifdef CONFIG_COH901318 + .dma_filter = coh901318_filter_id, + .dma_rx_param = (void *) U300_DMA_UART1_RX, + .dma_tx_param = (void *) U300_DMA_UART1_TX, +#endif +}; + static struct amba_device uart1_device = { .dev = { + .coherent_dma_mask = ~0, .init_name = uart1, /* Fast device at 0x7000 offset */ - .platform_data = NULL, + .platform_data = uart1_plat_data, }, .res = { .start = U300_UART1_BASE, @@ -949,20 +970,21 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { .priority_high = 0, .dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220, }, + /* +* Don't set up device address, burst count or size of src +* or dst bus for this peripheral - handled by PrimeCell +* DMA extension. +*/ { .number = U300_DMA_MMCSD_RX_TX, .name = MMCSD RX TX, .priority_high = 0, - .dev_addr = U300_MMCSD_BASE + 0x080, .param.config = COH901318_CX_CFG_CH_DISABLE | COH901318_CX_CFG_LCR_DISABLE | COH901318_CX_CFG_TC_IRQ_ENABLE | COH901318_CX_CFG_BE_IRQ_ENABLE, .param.ctrl_lli_chained = 0 | COH901318_CX_CTRL_TC_ENABLE | - COH901318_CX_CTRL_BURST_COUNT_32_BYTES | - COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | - COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | COH901318_CX_CTRL_MASTER_MODE_M1RW | COH901318_CX_CTRL_TCP_ENABLE | COH901318_CX_CTRL_TC_IRQ_ENABLE | @@ -971,9 +993,6 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { COH901318_CX_CTRL_DDMA_LEGACY, .param.ctrl_lli = 0 | COH901318_CX_CTRL_TC_ENABLE | - COH901318_CX_CTRL_BURST_COUNT_32_BYTES | - COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | - COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | COH901318_CX_CTRL_MASTER_MODE_M1RW | COH901318_CX_CTRL_TCP_ENABLE | COH901318_CX_CTRL_TC_IRQ_ENABLE | @@ -982,9 +1001,6 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { COH901318_CX_CTRL_DDMA_LEGACY, .param.ctrl_lli_last = 0 | COH901318_CX_CTRL_TC_ENABLE | - COH901318_CX_CTRL_BURST_COUNT_32_BYTES | -
[spi-devel-general] [PATCH 3/6] ARM: add PrimeCell generic DMA to MMCI/PL180
This extends the MMCI/PL180 driver with generic DMA engine support using the PrimeCell DMA engine interface. Signed-off-by: Linus Walleij linus.wall...@stericsson.com --- Changes since last version: - Folded in the new extensions to the DMA engine --- drivers/mmc/host/mmci.c | 290 ++--- drivers/mmc/host/mmci.h |7 +- include/linux/amba/mmci.h | 16 +++ 3 files changed, 268 insertions(+), 45 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index ff115d9..37ab678 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -2,7 +2,7 @@ * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver * * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * Copyright (C) 2010 ST-Ericsson AB. + * Copyright (C) 2010 ST-Ericsson SA * * 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 @@ -23,8 +23,11 @@ #include linux/clk.h #include linux/scatterlist.h #include linux/gpio.h -#include linux/amba/mmci.h #include linux/regulator/consumer.h +#include linux/dmaengine.h +#include linux/dma-mapping.h +#include linux/amba/dma.h +#include linux/amba/mmci.h #include asm/cacheflush.h #include asm/div64.h @@ -98,12 +101,209 @@ static void mmci_stop_data(struct mmci_host *host) host-data = NULL; } +static void +mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) +{ + void __iomem *base = host-base; + + dev_dbg(mmc_dev(host-mmc), op %02x arg %08x flags %08x\n, + cmd-opcode, cmd-arg, cmd-flags); + + if (readl(base + MMCICOMMAND) MCI_CPSM_ENABLE) { + writel(0, base + MMCICOMMAND); + udelay(1); + } + + c |= cmd-opcode | MCI_CPSM_ENABLE; + if (cmd-flags MMC_RSP_PRESENT) { + if (cmd-flags MMC_RSP_136) + c |= MCI_CPSM_LONGRSP; + c |= MCI_CPSM_RESPONSE; + } + if (/*interrupt*/0) + c |= MCI_CPSM_INTERRUPT; + + host-cmd = cmd; + + writel(cmd-arg, base + MMCIARGUMENT); + writel(c, base + MMCICOMMAND); +} + +/* + * All the DMA operation mode stuff goes inside this ifdef. + * This assumes that you have a generic DMA device interface, + * no custom DMA interfaces are supported. + */ +#ifdef CONFIG_DMADEVICES +static void __devinit mmci_setup_dma(struct mmci_host *host) +{ + struct mmci_platform_data *plat = host-plat; + dma_cap_mask_t mask; + + /* Try to acquire a generic DMA engine slave channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + /* +* If only an RX channel is specified, the driver will +* attempt to use it bidirectionally, however if it is +* is specified but cannot be located, DMA will be disabled. +*/ + host-dma_rx_channel = dma_request_channel(mask, + plat-dma_filter, + plat-dma_rx_param); + if (plat-dma_tx_param) { + host-dma_tx_channel = dma_request_channel(mask, + plat-dma_filter, + plat-dma_tx_param); + if (!host-dma_tx_channel) { + dma_release_channel(host-dma_rx_channel); + host-dma_rx_channel = NULL; + } + } else { + host-dma_tx_channel = host-dma_rx_channel; + } +} + +static void __devexit mmci_disable_dma(struct mmci_host *host) +{ + if (host-dma_rx_channel) + dma_release_channel(host-dma_rx_channel); + if (host-dma_tx_channel) + dma_release_channel(host-dma_tx_channel); +} + +static void mmci_dma_data_end(struct mmci_host *host) +{ + struct mmc_data *data = host-data; + + dma_unmap_sg(mmc_dev(host-mmc), data-sg, data-sg_len, +(data-flags MMC_DATA_WRITE) +? DMA_TO_DEVICE : DMA_FROM_DEVICE); +} + +static void mmci_dma_data_error(struct mmci_host *host) +{ + struct mmc_data *data = host-data; + struct dma_chan *chan; + + dev_err(mmc_dev(host-mmc), error during DMA transfer!\n); + if (data-flags MMC_DATA_READ) + chan = host-dma_rx_channel; + else + chan = host-dma_tx_channel; + dma_unmap_sg(mmc_dev(host-mmc), data-sg, data-sg_len, +(data-flags MMC_DATA_WRITE) +? DMA_TO_DEVICE : DMA_FROM_DEVICE); + chan-device-device_control(chan, DMA_TERMINATE_ALL); +} + +/* + * This one gets called repeatedly to copy data using + * DMA until there is no more data left to copy. + */ +static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) +{ + struct amba_dma_channel_config
[spi-devel-general] [PATCH 5/6] ARM: add PrimeCell generic DMA to PL022
This extends the PL022 UART driver with generic DMA engine support using the PrimeCell DMA engine interface. Also fix up the test code for the U300 platform. Signed-off-by: Linus Walleij linus.wall...@stericsson.com --- arch/arm/mach-u300/dummyspichip.c |1 + drivers/spi/amba-pl022.c | 517 +++-- include/linux/amba/pl022.h|6 + 3 files changed, 438 insertions(+), 86 deletions(-) diff --git a/arch/arm/mach-u300/dummyspichip.c b/arch/arm/mach-u300/dummyspichip.c index 5f55012..5672189 100644 --- a/arch/arm/mach-u300/dummyspichip.c +++ b/arch/arm/mach-u300/dummyspichip.c @@ -268,6 +268,7 @@ static struct spi_driver pl022_dummy_driver = { .driver = { .name = spi-dummy, .owner = THIS_MODULE, + .bus = spi_bus_type, }, .probe = pl022_dummy_probe, .remove = __devexit_p(pl022_dummy_remove), diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index e9aeee1..09a701c 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -27,7 +27,6 @@ /* * TODO: * - add timeout on polled transfers - * - add generic DMA framework support */ #include linux/init.h @@ -45,6 +44,10 @@ #include linux/amba/pl022.h #include linux/io.h #include linux/slab.h +#include linux/dmaengine.h +#include linux/dma-mapping.h +#include linux/scatterlist.h +#include linux/amba/dma.h /* * This macro is used to define some register default values. @@ -365,6 +368,14 @@ struct pl022 { enum ssp_readingread; enum ssp_writingwrite; u32 exp_fifo_level; + /* DMA settings */ +#ifdef CONFIG_DMADEVICES + struct dma_chan *dma_rx_channel; + struct dma_chan *dma_tx_channel; + struct sg_table sgt_rx; + struct sg_table sgt_tx; + char*dummypage; +#endif }; /** @@ -699,6 +710,367 @@ static void *next_transfer(struct pl022 *pl022) } return STATE_DONE; } + +/* + * This DMA functionality is only compiled in if we have + * access to the generic DMA devices/DMA engine. + */ +#ifdef CONFIG_DMADEVICES +static void unmap_free_dma_scatter(struct pl022 *pl022) +{ + /* Unmap and free the SG tables */ + dma_unmap_sg(pl022-adev-dev, pl022-sgt_tx.sgl, +pl022-sgt_tx.nents, DMA_TO_DEVICE); + dma_unmap_sg(pl022-adev-dev, pl022-sgt_rx.sgl, +pl022-sgt_rx.nents, DMA_FROM_DEVICE); + sg_free_table(pl022-sgt_rx); + sg_free_table(pl022-sgt_tx); +} + +static void dma_callback(void *data) +{ + struct pl022 *pl022 = data; + struct spi_message *msg = pl022-cur_msg; + + /* Sync in RX buffer to CPU */ + BUG_ON(!pl022-sgt_rx.sgl); + dma_sync_sg_for_cpu(pl022-adev-dev, + pl022-sgt_rx.sgl, + pl022-sgt_rx.nents, + DMA_FROM_DEVICE); + +#ifdef VERBOSE_DEBUG + /* +* Optionally dump out buffers to inspect contents, this is +* good if you want to convince yourself that the loopback +* read/write contents are the same, when adopting to a new +* DMA engine. +*/ + { + struct scatterlist *sg; + unsigned int i; + + for_each_sg(pl022-sgt_rx.sgl, sg, pl022-sgt_rx.nents, i) { + dev_dbg(pl022-adev-dev, SPI RX SG ENTRY: %d, i); + print_hex_dump(KERN_ERR, SPI RX: , + DUMP_PREFIX_OFFSET, + 16, + 1, + sg_virt(sg), + sg_dma_len(sg), + 1); + } + for_each_sg(pl022-sgt_tx.sgl, sg, pl022-sgt_tx.nents, i) { + dev_dbg(pl022-adev-dev, SPI TX SG ENTRY: %d, i); + print_hex_dump(KERN_ERR, SPI TX: , + DUMP_PREFIX_OFFSET, + 16, + 1, + sg_virt(sg), + sg_dma_len(sg), + 1); + } + } +#endif + + unmap_free_dma_scatter(pl022); + + /* Update total bytes transfered */ + msg-actual_length += pl022-cur_transfer-len; + if (pl022-cur_transfer-cs_change) + pl022-cur_chip- + cs_control(SSP_CHIP_DESELECT); + + /* Move to next transfer */ + msg-state = next_transfer(pl022); + tasklet_schedule(pl022-pump_transfers); +} + +static void setup_dma_scatter(struct pl022 *pl022, + void *buffer, +
[spi-devel-general] [PATCH 4/6] ARM: add PrimeCell generic DMA to PL011
This extends the PL011 UART driver with generic DMA engine support using the PrimeCell DMA engine interface. Signed-off-by: Linus Walleij linus.wall...@stericsson.com --- Changes since last version: - Fixed some bugs appearing under huge load, spinlock issues etc - Adapted to the new generic DMA engine interface --- drivers/serial/amba-pl011.c | 713 ++- include/linux/amba/serial.h |6 + 2 files changed, 712 insertions(+), 7 deletions(-) diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index eb4cb48..086b777 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -7,6 +7,7 @@ * * Copyright 1999 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd. + * Copyright (C) 2010 ST-Ericsson SA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,6 +49,11 @@ #include linux/amba/serial.h #include linux/clk.h #include linux/slab.h +#include linux/dmaengine.h +#include linux/dma-mapping.h +#include linux/scatterlist.h +#include linux/completion.h +#include linux/amba/dma.h #include asm/io.h #include asm/sizes.h @@ -63,6 +69,24 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 16) +/* Deals with DMA transactions */ +struct pl011_dma_rx_transaction { + struct completion complete; + bool use_buffer_b; + struct scatterlist scatter_a; + struct scatterlist scatter_b; + char *rx_dma_buf_a; + char *rx_dma_buf_b; + dma_cookie_t cookie; +}; + +struct pl011_dma_tx_transaction { + struct completion complete; + struct scatterlist scatter; + char *tx_dma_buf; + dma_cookie_t cookie; +}; + /* * We wrap our port structure around the generic uart_port. */ @@ -73,6 +97,15 @@ struct uart_amba_port { unsigned intold_status; unsigned intifls; /* vendor-specific */ boolautorts; + unsigned intfifosize; + /* DMA stuff */ + booluse_dma; +#ifdef CONFIG_DMADEVICES + struct dma_chan *dma_rx_channel; + struct dma_chan *dma_tx_channel; + struct pl011_dma_rx_transaction dmarx; + struct pl011_dma_tx_transaction dmatx; +#endif }; /* There is by now at least one vendor with differing details, so handle it */ @@ -91,18 +124,641 @@ static struct vendor_data vendor_st = { .fifosize = 64, }; + +/* + * All the DMA operation mode stuff goes inside this ifdef. + * This assumes that you have a generic DMA device interface, + * no custom DMA interfaces are supported. + */ +#ifdef CONFIG_DMADEVICES + +#define PL011_DMA_BUFFER_SIZE PAGE_SIZE + +static void __init pl011_dma_probe_initcall(struct uart_amba_port *uap) +{ + /* DMA is the sole user of the platform data right now */ + struct amba_pl011_data *plat = uap-port.dev-platform_data; + struct pl011_dma_rx_transaction *dmarx = uap-dmarx; + struct pl011_dma_tx_transaction *dmatx = uap-dmatx; + struct amba_dma_channel_config rx_conf = { + .addr = uap-port.mapbase + UART01x_DR, + .addr_width = 1, + .direction = DMA_FROM_DEVICE, + .maxburst = uap-port.fifosize 1, + }; + struct amba_dma_channel_config tx_conf = { + .addr = uap-port.mapbase + UART01x_DR, + .addr_width = 1, + .direction = DMA_TO_DEVICE, + .maxburst = uap-port.fifosize 1, + }; + dma_cap_mask_t mask; + int sglen; + + /* We need platform data */ + if (!plat) { + dev_err(uap-port.dev, no platform data!\n); + return; + } + + /* Try to acquire a generic DMA engine slave channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + /* +* We need both RX and TX channels to do DMA, else do none +* of them. +*/ + uap-dma_rx_channel = dma_request_channel(mask, + plat-dma_filter, + plat-dma_rx_param); + if (!uap-dma_rx_channel) { + dev_err(uap-port.dev, no RX DMA channel!\n); + return; + } + dma_set_ambaconfig(uap-dma_rx_channel, rx_conf); + + uap-dma_tx_channel = dma_request_channel(mask, + plat-dma_filter, + plat-dma_tx_param); + if (!uap-dma_tx_channel) { + dev_err(uap-port.dev, no TX DMA channel!\n); + goto err_no_txchan; + } + dma_set_ambaconfig(uap-dma_tx_channel, tx_conf); + + /* Allocate DMA RX and TX buffers */ + dmarx-rx_dma_buf_a =
Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100
On Mon, 29 Mar 2010 20:55:51 +0800 christian pellegrin chrip...@fsfe.org wrote: On Mon, Mar 29, 2010 at 9:06 AM, Feng Tang feng.t...@intel.com wrote: Our platform is Intel Moorestown platform, and use a spi controller core from Designware (drivers/spi/dw_*.c). I know the problem may probably be caused by my setting, but the dw_spi driver works fine with our own 3110 driver. I had a look at the dw_spi driver. The spi_transfer path queues some work to a worqueue that itself schedules a tasklet. I don't think this is good for latency, I won't bet that such an architecture could deliver good performance. Now I see why you needed to do only big fat SPI transfers. Anyway this doesn't justify the 2 seconds delay between Hi DW controller driver don't need max3110 driver to use big spi transfer, the early version of our max3110 is also one word per spi transfer mode, and the 2 drivers work fine, though the rx performance is not good (copy paste a bulk message to console). Let me use some example to explain why I use big spi transfer for 3110: When the HW works at 230400 bps, when we copy bulk data to the console, max3110 will probably receive about 20K characters, so the time for handling each char is 50us. If you use one char per spi transfer, it will have to execute 20K spi_transfer in one second, and each need be done in 50us, in this 50us you'll have to deal with controller IRQ handler + spi system overhead + tty receiving overhead. Is it a little over-killing to use one char per spi transfer? while the HW does have a 8 words RX FIFO chars coming in and going out through the max31x0 you are seeing. I will try to analyze what's going on. BTW is only input slow or output is sluggish too? The initial messages from the console are coming out fast? If you disable the MAX3110 for console but you use just as a normal terminal (set console=/dev/null in the kernel command line and add getty 115200 /dev/ttyMAX0 in iniitab) is the interaction with the system fine? Thanks for helping sorting out this. The output is not so slow as input, if we set the console=/dev/ttyMAX0, the output is sluggish, looks like below, but when enter command line console the output is smooth, while the input is very slow. -- kernel print log of max3100 over Moorestown platform -- 0.00] Moorestown CPU Lincroft identified [[..00 iiuu eessoo 44rr11((eeggffnn--77 ggccvvrriinn11((bbnnuu1144bbnnuu [[..00 BBOO--8800 1100--8800 uuaall)) ]] IISSee22::00 11 - 0f200 (usabl)) [ .000 BIOS-e822:: 022000110 00((eserved) [0.00] BIISSe820:: ee0 --0fec01000 (reseree)) ]] IISSee200 [[..00 BBOO--8800 ff00-- rrssrree)) ]]NNttcc::NN [[..00 8800uuddtt aagg::((ssbbee == rrssrree)) 00 00]]ee22 eeooeerrnnee 00aa--0011 uuaall)) ]]llss__ffxx 2200mmxxaacc__ffxx00 ]]MMRR eeaall yyee nnaahhbbee ]]MMRR iiee aa [[..00-- rrtt--aakk [[..00-- rrtt--aakk]] AABBuuaall ]]MMRR aaiibbeerrnnee nnbbee:: 1) the console code has to check if the serial port associated to the same physical max3100 is up (console driver start their life much before serial ones). 2) if yes send data to the tty associated to the serial driver. Locking is needed here. I will implement this ASAP. cool! -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general