From patchwork Tue Jun 9 11:45:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: haikun wang X-Patchwork-Id: 6572011 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B9BFE9F326 for ; Tue, 9 Jun 2015 12:05:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B0646204DE for ; Tue, 9 Jun 2015 12:05:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5F53220480 for ; Tue, 9 Jun 2015 12:05:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753812AbbFIMFf (ORCPT ); Tue, 9 Jun 2015 08:05:35 -0400 Received: from mail-bl2on0114.outbound.protection.outlook.com ([65.55.169.114]:32537 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753122AbbFIMFe (ORCPT ); Tue, 9 Jun 2015 08:05:34 -0400 X-Greylist: delayed 944 seconds by postgrey-1.27 at vger.kernel.org; Tue, 09 Jun 2015 08:05:34 EDT Received: from CH1PR03CA011.namprd03.prod.outlook.com (10.255.156.156) by CY1PR0301MB0620.namprd03.prod.outlook.com (10.160.142.27) with Microsoft SMTP Server (TLS) id 15.1.190.14; Tue, 9 Jun 2015 11:49:48 +0000 Received: from BN1AFFO11OLC001.protection.gbl (10.255.156.132) by CH1PR03CA011.outlook.office365.com (10.255.156.156) with Microsoft SMTP Server (TLS) id 15.1.184.17 via Frontend Transport; Tue, 9 Jun 2015 11:49:48 +0000 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Received: from az84smr01.freescale.net (192.88.158.2) by BN1AFFO11OLC001.mail.protection.outlook.com (10.58.53.72) with Microsoft SMTP Server (TLS) id 15.1.190.9 via Frontend Transport; Tue, 9 Jun 2015 11:49:48 +0000 Received: from titan.ap.freescale.net ([10.192.208.233]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id t59Bnj39025286; Tue, 9 Jun 2015 04:49:46 -0700 From: Haikun Wang To: CC: , Haikun Wang Subject: [PATCH v2 2/2] spi: spi-fsl-dspi: Change the way of increasing spi_message->actual_length Date: Tue, 9 Jun 2015 19:45:37 +0800 Message-ID: <1433850337-30713-1-git-send-email-haikun.wang@freescale.com> X-Mailer: git-send-email 2.1.0.27.g96db324 X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BN1AFFO11OLC001; 1:RtnLUfaUDHuToMPtI1hogp2PnD1MsensNFFSu4ThjN09tUQkJV/39qywmSc0SgdMhdbjvMpuza1qqL9HMj3Va3Z4Fc0tKquME1uK8Bg+vf2zN9olYbggqN1DVhHRWkc85mBTh4RT5BrEXVXwxK9Q9xtI3AHagSHuBdUa143IDRT+xuSd5Fvg7h8byaL3yM2Ki04gMH8ZeWKfW7e6ViTvP8Vny70cy+k9MXLAgcPC3OF2pjo9ux5cLjeX8QHp6Xfy4NSe+5b3GcFbU59LxJWmhz2r4VR1cP0vyG50ZqmxCK2Uhfq0z5i5CJyY/T1DMewoPVgqkDmfn4S1aas7na709A== X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(199003)(189002)(106466001)(104016003)(87936001)(19580395003)(110136002)(107886002)(189998001)(50226001)(85426001)(33646002)(5001960100002)(92566002)(62966003)(77156002)(77096005)(50986999)(6806004)(19580405001)(230783001)(50466002)(2351001)(229853001)(46102003)(86362001)(575784001)(48376002)(105606002)(47776003)(36756003)(21314002)(4001430100001); DIR:OUT; SFP:1102; SCL:1; SRVR:CY1PR0301MB0620; H:az84smr01.freescale.net; FPR:; SPF:Fail; MLV:sfv; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0620; 2:gR29lkq718y4gxQmO8L/EGiZHgv7QTEORAngARngMnjx+xA8dtVY7UQNdm49c86K; 2:PQ1ibSUx/O149PoHyQB8jAgZY1N0bdK/h00z83/flAbViKvVJWxY0EbVo5HJkOb3siq7uKSUwSW0KgN8LKXsxTnh5OR7q4shYr/tS0Cmz/uT9f6TDr9nTBnOBVaepi4Hw1nHIox3aiCKp/+bXSz6atylKOIPTkzqXBcuj3kXoApXFEsW0jsI2d3YnwTCp8OMFEpy9AHf2hb5LhruhABgQFPIZMre8U7J4nSBVn/dNwo=; 6:P9+bj8foNP2UxmrB+DbMVpHPjT7j76bwCjmcZrZNH1+bmqwe5Ul5McJPjud3P5RtT0B0S60XZnSaRnuDsmsQLphLgGNA3LXGowCNPfyS0WFGhdr9fv6Nlh3wHkEjRdrcmQdd1MYv6WIU+wYYxjhXTpcv6LYbhLIzJNm1ldyI+5R9UAFrhgNL8AHnYLUKy3ThYhVZQ2d+DO6hDcrLr3k9Yw/AZC6GVG9NQY10T/Hju8h8hFcbSB50STbr+Ao5AOf5OsmeWrnHY20FBEzN2zQUDwVXg8TtGp44xksx2xDsHeAQfj84biBjOjx8/wcyjJOeHzTfjicxbMZwwG/+fDJ+eQ== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR0301MB0620; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(520003)(5005006)(3002001); SRVR:CY1PR0301MB0620; BCL:0; PCL:0; RULEID:; SRVR:CY1PR0301MB0620; X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0620; 3:aEbIYdi0EG/+/Dl8jCpRgjf0h0/BcKGh0sasiOLr/l+e+hMH9129N8UxPbS5EWfVK0lsVfad4jhH8mV1/u5B3ibbtABS6D0BQzDhdpT+oL0QdwnEnu3cOw0i46CspIMOANn1IA2rZ/iYJb4sM9H157P0gstLtFPayNVLIRa9CEqZq+/mafxpbSVswYG+zOx5SUbr1ftTzv0ZZZLTU+MHYcJi5GBpTQgbeOslfIoTUThkEZB3f/QN3MSw2Wxzs8H/WMujgaDgf/EdWDMOF534G4/pKYTUQxshRP5j/oYhRwDKOgfr5A4a/NJ6jP9L/ZOp X-Forefront-PRVS: 06022AA85F X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0620; 9:5fqyLDYfiZLd003TOlYBI/WwjuYYvAMB1HmzqQdPZT6eNRZaCPJ56rSX0BIackbtccWm5bSgd1tXuaHnR8SusQ3Y0SXM/2tybYXNtzdcb1sIUtty/Cij5RN1n3OQjwq5gwq2AkCbimDvPa2I77A6ukRtH4BNxL41+cksfdG72obxDl0NjceavSjP+V8b19sJwJe4ZArbi83cEFoS3ZcatcXz6emMnz6+FFx77oUsOVKm5lVRtfu1ZquO4ZZYFKGe30TBeW1O708ywQjVor8WaeICLtKVKz8TwgMZCDyqUa4OrFGNUA6aie4sOFtCs3USRtLFUJvLdkvk7p7TPuQZjOzmmGYsIU9ksWm4ZHvV+UalnErymQMbKUrenU6RXtXX+blaH1xmv1057nXSn5UcnxG8gBY+Kxm243ZfoTut+MRjFRWobRtm0ZFCNWxQx+T0rHIyWnt9+sANT0SNAlcyJPqfm3wNEp+uxEzib+m50UzLIU5cQVVNrE2VU75FAC531CjcPSE/wbJCvMmlx9wa1gYJaV5hnCvrFYR6+dii8dfRZMsrp1C01LA0FbSoDWxWpYa3jjk+3YdKaZOTWhbhsgjZIJNPvnKuG7ovFbgiuzfM1ZU9DYOqb/Nux1hdy61cLQJlLI/dGgYiv8nu58nW8Q/JOWLA6hENPpnU2I+Hx7Wzb4Bmz7/xoAN8g5gidp5IHhL/nJJE+m3vG+tU9rgNo4Mpg0+NDPjJ9hDokiJAayvPPmEC3yN7xsp95v01ufCxIsG1yWkgmLYPHFidL4tEPwy0XfkTTLXg9Zb7WUWWoVabV8Fo2DCU/PkLUGHkknvEIDfiqOTARcPC1FiJsrynC8SXxL2zK4voLTBNoP5J015dbh2wMvW5afo+mXQIBlNnMqHsWz8dF+0sexGu4fSi/dPjpD55MwGG4DmcHlgj O/0= X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0620; 3:0RNLmSs5L6sHGcSyS3zu8ZgeSDjCMnqI4A1vTDVH+OQvALj/D3x4M2GeCHX3wNKAVnwyNXLX6UYnR+rGl/aczcRumiNXmBqTxzrpYIXYKh61VJZqHMPZw5U76JUMBEo7f3XJj0Xl4HVaCOGDYUB2Hg==; 10:nMvIwgPnCvobGMdWN0HUjflFVCJMYQv62ZAZCK54HpUWATvGJIlw6m7Gu73A7CDJn15cPdkeAxOOcp6Ulf3xkILzozj4f/9Bemi7JIlf1VE=; 6:bM+zppQ0EK6B3aFcvxC1TCF0e2Qa9e1ifmhqdX8mVXVPTVmrDGVbEkjveXykY9mi X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Jun 2015 11:49:48.5632 (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.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR0301MB0620 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, 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 In current driver, we increase actual_length in the following way: message->actual_length += dspi_xxx_transfer() It has two defects. First, transmitting maybe in process when the function call finished and we don't know the transmitting result in this moment. Secondly, the last sentence in function before returning is accessing the SPI register and trigger the data transmitting. If we enable interrupt, interrupt may be generated before function return and we also have the same sentence "message->actual_length += dspi_xxx_transfer()" in the IRQ handler. And usually dspi_xxx_transfer will trigger a new IRQ. The original dspi_xxx_transfer call may return when no new IRQ generate. This may mess the variable spi_message->actual_length. Now we increase the variable in the IRQ handler and only when we get the TCF or EOQ interrupt And we get the transmitted data length from the SPI transfer counter instead of the function return value. Signed-off-by: Haikun Wang --- Changes in v2: - rebase Changes in v1: None drivers/spi/spi-fsl-dspi.c | 101 ++++++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 64e311a..706b10c 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -47,6 +47,7 @@ #define SPI_MCR_CLR_RXF (1 << 10) #define SPI_TCR 0x08 +#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16) #define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) #define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) @@ -104,6 +105,8 @@ #define SPI_CS_ASSERT 0x02 #define SPI_CS_DROP 0x04 +#define SPI_TCR_TCNT_MAX 0x10000 + struct chip_data { u32 mcr_val; u32 ctar_val; @@ -155,6 +158,8 @@ struct fsl_dspi { wait_queue_head_t waitq; u32 waitflags; + + u32 spi_tcnt; }; static inline int is_double_byte_mode(struct fsl_dspi *dspi) @@ -274,7 +279,6 @@ static int dspi_eoq_write(struct fsl_dspi *dspi) int tx_count = 0; int tx_word; u32 dspi_pushr = 0; - int first = 1; tx_word = is_double_byte_mode(dspi); @@ -300,11 +304,6 @@ static int dspi_eoq_write(struct fsl_dspi *dspi) } else if (tx_word && (dspi->len == 1)) dspi_pushr |= SPI_PUSHR_EOQ; - if (first) { - first = 0; - dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ - } - regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); tx_count++; @@ -372,6 +371,10 @@ static int dspi_transfer_one_message(struct spi_master *master, struct spi_transfer *transfer; int status = 0; enum dspi_trans_mode trans_mode; + u32 spi_tcr; + + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + dspi->spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); message->actual_length = 0; @@ -413,11 +416,11 @@ static int dspi_transfer_one_message(struct spi_master *master, switch (trans_mode) { case DSPI_EOQ_MODE: regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); - message->actual_length += dspi_eoq_write(dspi); + dspi_eoq_write(dspi); break; case DSPI_TCFQ_MODE: regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE); - message->actual_length += dspi_tcfq_write(dspi); + dspi_tcfq_write(dspi); break; default: dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", @@ -516,47 +519,79 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; struct spi_message *msg = dspi->cur_msg; enum dspi_trans_mode trans_mode; - u32 spi_sr; + u32 spi_sr, spi_tcr; + u32 spi_tcnt, tcnt_diff; + int tx_word; regmap_read(dspi->regmap, SPI_SR, &spi_sr); regmap_write(dspi->regmap, SPI_SR, spi_sr); - trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } - if (!dspi->len) { - if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) { - regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), - SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); - dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM; - } + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { + tx_word = is_double_byte_mode(dspi); - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - } else { + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); + /* + * The width of SPI Transfer Counter in SPI_TCR is 16bits, + * so the max couner is 65535. When the counter reach 65535, + * it will wrap around, counter reset to zero. + * spi_tcnt my be less than dspi->spi_tcnt, it means the + * counter already wrapped around. + * SPI Transfer Counter is a counter of transmitted frames. + * The size of frame maybe two bytes. + */ + tcnt_diff = ((spi_tcnt + SPI_TCR_TCNT_MAX) - dspi->spi_tcnt) + % SPI_TCR_TCNT_MAX; + tcnt_diff *= (tx_word + 1); + if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) + tcnt_diff--; + + msg->actual_length += tcnt_diff; + + dspi->spi_tcnt = spi_tcnt; + + trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { case DSPI_EOQ_MODE: - msg->actual_length += dspi_eoq_write(dspi); + dspi_eoq_read(dspi); break; case DSPI_TCFQ_MODE: - msg->actual_length += dspi_tcfq_write(dspi); + dspi_tcfq_read(dspi); break; default: dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", trans_mode); + return IRQ_HANDLED; + } + + if (!dspi->len) { + if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) { + regmap_update_bits(dspi->regmap, + SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, + SPI_FRAME_BITS(16)); + dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM; + } + + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + } else { + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_write(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_write(dspi); + break; + default: + dev_err(&dspi->pdev->dev, + "unsupported trans_mode %u\n", + trans_mode); + } } } + return IRQ_HANDLED; }