From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964855AbbLOJpt (ORCPT ); Tue, 15 Dec 2015 04:45:49 -0500 Received: from mail-by2on0143.outbound.protection.outlook.com ([207.46.100.143]:5267 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933171AbbLOJpo (ORCPT ); Tue, 15 Dec 2015 04:45:44 -0500 Authentication-Results: spf=permerror (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; mentor.com; dkim=none (message not signed) header.d=none;mentor.com; dmarc=none action=none header.from=freescale.com; Date: Tue, 15 Dec 2015 17:41:29 +0800 From: Robin Gong To: Anton Bondarenko CC: , , , , , , Subject: Re: [PATCH v6 8/8] spi: imx: add support for all SPI word width for DMA Message-ID: <20151215094111.GA11427@shlinux2> References: <1449557030-27525-1-git-send-email-anton.bondarenko.sama@gmail.com> <1449557030-27525-9-git-send-email-anton.bondarenko.sama@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline In-Reply-To: <1449557030-27525-9-git-send-email-anton.bondarenko.sama@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11FD039;1:vCS6378CbkMq0+B7C1UvYzKe799W9fSz+RTEnmXdeU8rnmo9K2smFv4/hbqVNLEL6ONNwXoEB7Z/4GIJvBzPVmFF536imU6+KbNIqYhEyQVGBbc29mOZ7g8RZ93qIXX6SQMr6uX0x7yWzOpexUBuAUkeiYQQgVTakeb5va9hTvxLen4FY6D6ls4ArAdcyVa/9E2HaSL8aKjurJWRZTZMyLvOHWxLp8vq0cZZvbE1J04+7Ob1+cLfTMLkeUgIFF0xXBxDrkjZuoi+fJNWNoWqNxsfrmMl9OQQzt22UhTBW4HoyRDaKGI5Ry66RBoA5JbEjHJyedwsWtLf/mJPD/iqgSrm/cuqnwQY6Itja3S18Bm7bIrDQEB9saO4KnqOjayvwheNJSk55hYlI0td0mrQRg== X-Forefront-Antispam-Report: CIP:192.88.168.50;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(2980300002)(448002)(24454002)(189002)(199003)(50986999)(97756001)(586003)(1096002)(1076002)(33716001)(87936001)(104016004)(106466001)(11100500001)(92566002)(54356999)(1220700001)(33656002)(83506001)(85326001)(76176999)(46406003)(23726003)(19580405001)(2950100001)(19580395003)(6806005)(77096005)(81156007)(5008740100001)(5001960100002)(189998001)(47776003)(110136002)(4001350100001)(97736004)(50466002)(42262002);DIR:OUT;SFP:1102;SCL:1;SRVR:BLUPR03MB1345;H:tx30smr01.am.freescale.net;FPR:;SPF:PermError;PTR:InfoDomainNonexistent;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB1345;2:7/pC/P7XtlzxmFVfKE/eiZcwpIJttaYn9fKOD8LIRkmyvO0e7OJaZAK7kiXxwDq0M2vesw6C61YExvkzt4qP9A5wdk9T/Ddy0YmHAlnHjmBygrcukk/0snIDaTfoAydPOPsfrRRuQMs+hYr+veKmVQ==;3:2Qn8Z/YB5Cl+ItvouKee7e+wzg4Eh7FMaxk42FEHZptfOBvHf0Ve2f/qOQ8zG3IBrKT/Muj4gedw0k/lkkgZV/rgDLJb5snPtK04MMSD3Ky4hXyXcGbvPVdYG7eNhDL5n6J+r4r+zfZM8x2MryDAeK/uZSl+G4t1hHXYCEJMjjvF2lKirnB31/5N4Zm70PRWgdQCt1xjTdpB2XycvKdcg5Dp7/dpSGBJh1r0Yz/rAUM=;25:c3tbJBOUc9pEkgfgK/GFTehcwy+D7AZyf4Tzkei0KNjahRXBMaxcRPi56fEjIm5BFDb/BmL5l4cGRafVVS+IvBurSlSxFCFDwK6f2iythpdQef9TirPV4y1H9QfCaNYmG7GBNQy5fvMotlHCc/H7tMqsqGog+Pxr2ObVMUO6pVvXDVgPgKYlrGpv8ZrARL0Mb5D4HmK9LBQ7wDuApYkWuHZP6sPxxrjwnXPhExCyLcDpAbQg4H0dd/oK4F8idKFn X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB1345; X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB1345;20:W/3J9NOodjJjb0wcZw2cSmub+XPtJNCS0s2suzdiRdXmoy2tTQyE91RfccqHVZPyq729Tro+ENq32YA/uQVLbLE9QE5FUI+sI004DyfEZkUVytN3sPfKK/7uDKOA1hfrZhQWjNqixGFeaJCG5g32T98fwUxZLaeBveqqGRSu1TQX04pZpxivXo6/pO9BOok1gbRAr27yHq5q5XZuVlmA8TY3uLpt5u3ylM2doX3FbvxUkwjyzqJzpfTj3EFPl/XG0FDyI/+6hpkppqsrYMl7HmN5ER7KhF69ayojvZ4aoySfMBAvVSYzMXajz+f3ML+WlWMewhFf9GY8A0G0foF/9mysQtWQNqEOds6kWD6dy/E=;4:PWnp+TquspPnx6+NkUqEPKyFYngLcaw8n/6T3VLx/HZVv1+KXckkEurTqyjrfIGP9TIX3xYwPkDVlqlsjcJU1et2S3LXIJUPbYi4P26YFNyXaGRZL/1Z+hrrbh47LLuVnequfVF9wdfjScdOMYu8kONi+P8KyOg6ct4mvmz8xL/HtfxvcH1vmaA8L6B9AmukiaqSfmZvMkPppfQVtHZpp47SNyT+LUiZSs70OExvy5X+pQabz8p9R1yF+ji9RCIxUyLRXLxXITIKRC5i4cL3cMBA4yEun2PGtN/y+UoR3xow/u7SMWEHMQwzrBIYLh6RfYSg699rq7Xrznfh8nhv6Iuk1auevnUY00rJ/K7kfGSqJHDhZc6ScrTZF5ZQJxGw X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(520078)(8121501046)(5005006)(3002001)(10201501046);SRVR:BLUPR03MB1345;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB1345; X-Forefront-PRVS: 07915F544A X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BLUPR03MB1345;23:vy21bs9ZYZnT9aSa6H2LOavLm2DOlZNSKcZR5mU1y?= =?us-ascii?Q?QXL0+8dfCLd5kWe2J1nBkalHA/R8N3mWANeY0bkuIJt9gQqBa71XggSm9aRl?= =?us-ascii?Q?VYKLgJlWhPoVi/8CmyYYYMxL8rC5h44W+2pwrmNvoTdZSjgdqXOKMqPNM5ML?= =?us-ascii?Q?qdVM+MmTV+rpLAWU5zDOtsyYoT0VIfuLef71StPmwi+le3bg1GSQvRUZ7BKX?= =?us-ascii?Q?Z0jmSh8mLkxeg+BVPrOOfaqAtHQ87LfMsO6mL53XpcbS3mDaG+iOqjit7ByQ?= =?us-ascii?Q?Prqq2hc2yL9bO4lDkOY+RveqMAP3ZD73OF9yj1qrClhWpiOnZsr1otBksU73?= =?us-ascii?Q?cG/IHPof0+qjNYh1MTmNkyBGh/Lm3SNKaQQaF91wSj+97EJZjpVwlvuP9SnZ?= =?us-ascii?Q?SngacAVl2IUGDdSdLVFTRaNuwu/sBhiQhwj1YGw7qCvegUInI8iYU4h8ICc3?= =?us-ascii?Q?bIcF0AvDiACuFgTTJFU2gvRUDRgdXL2EaG5Z054eEhEj8taRqyDgoZ6P/+7y?= =?us-ascii?Q?BRm3wHC/T1AsvwPEnOgs4ojHRU+HweOoCv4Gxsr5iOD6EX089QS2RC77EEd6?= =?us-ascii?Q?17hAGvWD4JkYnFhopJRHu4vb54U9kdk+ewZGfpz7nbYji4LC6D0WkJC3B+x6?= =?us-ascii?Q?dbzMQ00Z4reTwiKGhWVFXyUsDkgtFilAkwFZsxQP2Egk3NndMjOSfPjvx782?= =?us-ascii?Q?YKHRBwBokHQ6cjb9grILfVukPNdhv5as7U6Xj/8jLDW7IQVpHNnGFDAIE+9n?= =?us-ascii?Q?QI+OM0YY8iNQBWz1cWrsWTe6yiZX2Kdd5CzeXlRjCClBTycKjD7mrXtgqrDo?= =?us-ascii?Q?1bvjHOmXVsyD5KbXMcYZlPLAh8XxAvGL+tSWe8Ubw0jMtDxJG0sJT02A+KDo?= =?us-ascii?Q?WTKM4oOqwwUFE91A6AjCkNIZkN5lT6c2wnzk1cXn6lsooVl9Lkk+wWZUVr+1?= =?us-ascii?Q?TeqZAdoD2nWB5F7drhyC2CcGPzzf6j2uLYTQhea38qC5lovoWuOoBzDDaiw1?= =?us-ascii?Q?R5LAhW3MX+rR/4luEWt1MIz+bT4M7msafQKo0oRnV8eijRdqGFnvUOA9XeQ7?= =?us-ascii?Q?sggS3w=3D?= X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB1345;5:702lnu/QRHldIUGCu6A7V8Fn8RvpwD1mUIJFHbVpYCME5WXJ6InDQZkRDy3bO/4iGt2t+K+QCstMwlpb4QvO1wASYzr+IV5dOQ9K7DnuS0m9w6rNQZZsqTJ2QoGjjSVsOQa31QZGMujnoNxGlo3B2w==;24:/T02uMYtpIISXCNzSB5WrAjg3HNSRpgVw8VU9/E4sweq9kiHnWDUwdGUmw1X5X7K09ZjqpBB9EJVwTYfos/ayGqPlyCDv344uF+F1yWO8hQ= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Dec 2015 09:45:41.2147 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR03MB1345 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Dec 08, 2015 at 07:43:50AM +0100, Anton Bondarenko wrote: > DMA transfer for SPI was limited to up to 8 bits word size until now. > Sync in SPI burst size and DMA bus width is necessary to correctly > support 16 and 32 BPW. > > Signed-off-by: Anton Bondarenko > --- > drivers/spi/spi-imx.c | 121 +++++++++++++++++++++++++++++++++++++++----------- > 1 file changed, 95 insertions(+), 26 deletions(-) > > diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c > index d74d809..750001c 100644 > --- a/drivers/spi/spi-imx.c > +++ b/drivers/spi/spi-imx.c > @@ -88,11 +88,15 @@ struct spi_imx_data { > > struct completion xfer_done; > void __iomem *base; > + unsigned long base_phys; > + > struct clk *clk_per; > struct clk *clk_ipg; > unsigned long spi_clk; > unsigned int spi_bus_clk; > > + unsigned int bytes_per_word; > + > unsigned int count; > void (*tx)(struct spi_imx_data *); > void (*rx)(struct spi_imx_data *); > @@ -199,13 +203,32 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, > return 7; > } > > +static int spi_imx_get_bytes_per_word(const int bpw) > +{ > + return DIV_ROUND_UP(bpw, BITS_PER_BYTE); > +} > + > static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, > struct spi_transfer *transfer) > { > struct spi_imx_data *spi_imx = spi_master_get_devdata(master); > + unsigned int bpw = transfer->bits_per_word; > + > + if (!bpw) > + bpw = spi->bits_per_word; > > - if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml && > - (transfer->len % spi_imx->wml) == 0) > + bpw = spi_imx_get_bytes_per_word(bpw); > + > + /* > + * We need to use SPI word size in calculation to decide > + * if we want to go with DMA or PIO mode. Just a short example: > + * We need to transfer 24 SPI words with BPW == 32. This will take > + * 24 PIO writes to FIFO (and same for reads). But transfer->len will > + * be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect > + * if we do not take into account SPI bits per word. > + */ > + if (spi_imx->dma_is_inited && transfer->len >= (spi_imx->wml * bpw) && > + (transfer->len % (spi_imx->wml * bpw)) == 0) > return true; > return false; > } > @@ -785,11 +808,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id) > return IRQ_HANDLED; > } > > +static int spi_imx_sdma_configure(struct spi_master *master) > +{ > + int ret; > + enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE; > + struct dma_slave_config slave_config = {}; > + struct spi_imx_data *spi_imx = spi_master_get_devdata(master); > + > + switch (spi_imx->bytes_per_word) { > + case 4: > + dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES; > + break; > + case 2: > + dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES; > + break; > + case 1: > + dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE; > + break; > + default: > + pr_err("Not supported word size %d\n", spi_imx->bytes_per_word); > + ret = -EINVAL; > + goto err; > + } > + > + slave_config.direction = DMA_MEM_TO_DEV; > + slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA; > + slave_config.dst_addr_width = dsb_default; > + slave_config.dst_maxburst = spi_imx->wml; > + ret = dmaengine_slave_config(master->dma_tx, &slave_config); > + if (ret) { > + pr_err("error in TX dma configuration.\n"); > + goto err; > + } > + > + memset(&slave_config, 0, sizeof(slave_config)); > + > + slave_config.direction = DMA_DEV_TO_MEM; > + slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA; > + slave_config.src_addr_width = dsb_default; > + slave_config.src_maxburst = spi_imx->wml; > + ret = dmaengine_slave_config(master->dma_rx, &slave_config); > + if (ret) > + pr_err("error in RX dma configuration.\n"); > + > +err: > + return ret; > +} > + > static int spi_imx_setupxfer(struct spi_device *spi, > struct spi_transfer *t) > { > struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); > struct spi_imx_config config; > + unsigned int new_bytes_per_word; > + int ret = 0; > > config.bpw = t ? t->bits_per_word : spi->bits_per_word; > config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; > @@ -813,9 +885,19 @@ static int spi_imx_setupxfer(struct spi_device *spi, > spi_imx->tx = spi_imx_buf_tx_u32; > } > > - spi_imx->devtype_data->config(spi_imx, &config); > + new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw); > + if (spi_imx->dma_is_inited && > + spi_imx->bytes_per_word != new_bytes_per_word) { Configure dma even in PIO mode for some minimal data transfer case?It's better to check can_dma here. > + spi_imx->bytes_per_word = new_bytes_per_word; > + ret = spi_imx_sdma_configure(spi->master); > + if (ret != 0) > + pr_err("Can't configure SDMA, error %d\n", ret); > + } > > - return 0; > + if (!ret) > + ret = spi_imx->devtype_data->config(spi_imx, &config); > + > + return ret; > } > > static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx) > @@ -839,7 +921,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, > struct spi_master *master, > const struct resource *res) > { > - struct dma_slave_config slave_config = {}; > int ret; > > /* use pio mode for i.mx6dl chip TKT238285 */ > @@ -857,16 +938,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, > goto err; > } > > - slave_config.direction = DMA_MEM_TO_DEV; > - slave_config.dst_addr = res->start + MXC_CSPITXDATA; > - slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; > - slave_config.dst_maxburst = spi_imx->wml; > - ret = dmaengine_slave_config(master->dma_tx, &slave_config); > - if (ret) { > - dev_err(dev, "error in TX dma configuration.\n"); > - goto err; > - } > - > /* Prepare for RX : */ > master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); > if (IS_ERR(master->dma_rx)) { > @@ -876,22 +947,20 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, > goto err; > } > > - slave_config.direction = DMA_DEV_TO_MEM; > - slave_config.src_addr = res->start + MXC_CSPIRXDATA; > - slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; > - slave_config.src_maxburst = spi_imx->wml; > - ret = dmaengine_slave_config(master->dma_rx, &slave_config); > - if (ret) { > - dev_err(dev, "error in RX dma configuration.\n"); > - goto err; > - } > - > init_completion(&spi_imx->dma_rx_completion); > init_completion(&spi_imx->dma_tx_completion); > master->can_dma = spi_imx_can_dma; > master->max_dma_len = MAX_SDMA_BD_BYTES; > spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | > SPI_MASTER_MUST_TX; > + spi_imx->bytes_per_word = 1; > + spi_imx->base_phys = res->start; > + ret = spi_imx_sdma_configure(master); > + if (ret) { > + dev_info(dev, "cannot get setup DMA.\n"); > + goto err; > + } > + > spi_imx->dma_is_inited = 1; > > return 0; > @@ -993,7 +1062,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, > dmaengine_terminate_all(master->dma_rx); > } else { > transfer_timeout = spi_imx_calculate_timeout(spi_imx, > - spi_imx->wml); > + spi_imx->bytes_per_word * spi_imx->wml); > timeout = wait_for_completion_timeout( > &spi_imx->dma_rx_completion, transfer_timeout); > if (!timeout) { > -- > 2.6.3 >